server-state.c 121 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322
  1. /*
  2. * Copyright © 2026 Pierre Le Marre <dev@wismill.eu>
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "config.h"
  6. #include "test-config.h"
  7. #include <assert.h>
  8. #include <stdint.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include "xkbcommon/xkbcommon.h"
  12. #include "xkbcommon/xkbcommon-errors.h"
  13. #include "xkbcommon/xkbcommon-keysyms.h"
  14. #include "xkbcommon/xkbcommon-names.h"
  15. #include "context.h"
  16. #include "evdev-scancodes.h"
  17. #include "src/keysym.h"
  18. #include "src/keymap.h"
  19. #include "src/state-priv.h"
  20. #include "state.h"
  21. #include "test.h"
  22. #include "utils.h"
  23. #define GOLDEN_TESTS_OUTPUTS "keymaps/"
  24. static enum xkb_state_component
  25. xkb_state_update_enabled_controls(struct xkb_state *state,
  26. enum xkb_keyboard_control_flags affect,
  27. enum xkb_keyboard_control_flags controls)
  28. {
  29. const struct xkb_state_components_update components = {
  30. .size = sizeof(components),
  31. .components = XKB_STATE_CONTROLS,
  32. .affect_controls = affect,
  33. .controls = controls,
  34. };
  35. const struct xkb_state_update update = {
  36. .size = sizeof(update),
  37. .components = &components,
  38. };
  39. enum xkb_state_component changed = 0;
  40. /* Note: no error handling */
  41. assert(xkb_state_update_synthetic(state, &update, &changed) == XKB_SUCCESS);
  42. return changed;
  43. }
  44. /**
  45. * Update the keyboard server state to change the *boolean*
  46. * [global keyboard controls].
  47. *
  48. * @param machine The keyboard server state object.
  49. * @param events The event collection to store the events. It will be reset.
  50. * @param affect
  51. * *Boolean* global keyboard controls to modify. @p controls contains the
  52. * actual values.
  53. * @param controls
  54. * *Boolean* global keyboard controls to lock or unlock. Only controls in
  55. * @p affect are considered.
  56. *
  57. * @returns 0 on success, otherwise an error code.
  58. *
  59. * Non-boolean controls are ignored.
  60. *
  61. * @since 1.14.0
  62. *
  63. * @memberof xkb_machine
  64. *
  65. * [global keyboard controls]: @ref xkb_keyboard_control_flags
  66. */
  67. static enum xkb_error_code
  68. xkb_machine_update_enabled_controls(struct xkb_machine *machine,
  69. struct xkb_events *events,
  70. enum xkb_keyboard_control_flags affect,
  71. enum xkb_keyboard_control_flags controls)
  72. {
  73. const enum xkb_state_component components
  74. = ((affect || controls) ? XKB_STATE_CONTROLS : 0);
  75. const struct xkb_state_components_update components_update = {
  76. .size = sizeof(components_update),
  77. .components = components,
  78. .affect_controls = affect,
  79. .controls = controls,
  80. };
  81. const struct xkb_state_update update = {
  82. .size = sizeof(update),
  83. .components = &components_update
  84. };
  85. return xkb_machine_process_synthetic(machine, &update, events);
  86. }
  87. /**
  88. * Update the keyboard server state to change the latched and locked state of
  89. * the modifiers and layout.
  90. *
  91. * Use this function to update the latched and locked state according to
  92. * out-of-band (non-device) inputs, such as UI layout switchers.
  93. *
  94. * @par Layout out of range
  95. * @parblock
  96. *
  97. * If the effective layout, after taking into account the depressed, latched and
  98. * locked layout, is out of range (negative or greater than the maximum layout),
  99. * it is brought into range. Currently, the layout is wrapped using integer
  100. * modulus (with negative values wrapping from the end). The wrapping behavior
  101. * may be made configurable in the future.
  102. *
  103. * @endparblock
  104. *
  105. * @param machine The keyboard server state object.
  106. * @param events The event collection to store the events. It will be reset.
  107. * @param affect_latched_mods See @p latched_mods.
  108. * @param latched_mods
  109. * Modifiers to set as latched or unlatched. Only modifiers in
  110. * @p affect_latched_mods are considered.
  111. * @param affect_latched_layout See @p latched_layout.
  112. * @param latched_layout
  113. * Layout to latch. Only considered if @p affect_latched_layout is true.
  114. * Maybe be out of range (including negative) -- see note above.
  115. * @param affect_locked_mods See @p locked_mods.
  116. * @param locked_mods
  117. * Modifiers to set as locked or unlocked. Only modifiers in
  118. * @p affect_locked_mods are considered.
  119. * @param affect_locked_layout See @p locked_layout.
  120. * @param locked_layout
  121. * Layout to lock. Only considered if @p affect_locked_layout is true.
  122. * Maybe be out of range (including negative) -- see note above.
  123. *
  124. * @returns 0 on success, otherwise an error code.
  125. *
  126. * @memberof xkb_machine
  127. */
  128. static enum xkb_error_code
  129. xkb_machine_update_latched_locked(struct xkb_machine *machine,
  130. struct xkb_events *events,
  131. xkb_mod_mask_t affect_latched_mods,
  132. xkb_mod_mask_t latched_mods,
  133. bool affect_latched_layout,
  134. int32_t latched_layout,
  135. xkb_mod_mask_t affect_locked_mods,
  136. xkb_mod_mask_t locked_mods,
  137. bool affect_locked_layout,
  138. int32_t locked_layout)
  139. {
  140. const enum xkb_state_component components
  141. = ((affect_latched_mods || latched_mods) ? XKB_STATE_MODS_LATCHED : 0)
  142. | ((affect_locked_mods || locked_mods) ? XKB_STATE_MODS_LOCKED : 0)
  143. | (affect_latched_layout ? XKB_STATE_LAYOUT_LATCHED : 0)
  144. | (affect_locked_layout ? XKB_STATE_LAYOUT_LOCKED : 0);
  145. const struct xkb_state_components_update components_update = {
  146. .size = sizeof(components_update),
  147. .components = components,
  148. .affect_latched_mods = affect_latched_mods,
  149. .latched_mods = latched_mods,
  150. .latched_layout = latched_layout,
  151. .affect_locked_mods = affect_locked_mods,
  152. .locked_mods = locked_mods,
  153. .locked_layout = locked_layout,
  154. };
  155. const struct xkb_state_update update = {
  156. .size = sizeof(update),
  157. .components = &components_update,
  158. };
  159. return xkb_machine_process_synthetic(machine, &update, events);
  160. }
  161. static void
  162. test_machine_builder(struct xkb_context *ctx)
  163. {
  164. struct xkb_keymap *keymap =
  165. xkb_keymap_new_from_names(ctx, NULL, TEST_KEYMAP_COMPILE_FLAGS);
  166. assert(keymap);
  167. struct xkb_machine_builder *builder =
  168. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  169. assert(builder);
  170. /* Valid flags */
  171. static_assert(XKB_A11Y_NO_FLAGS == 0, "default flags");
  172. assert(xkb_machine_builder_update_a11y_flags(
  173. builder, XKB_A11Y_NO_FLAGS, XKB_A11Y_NO_FLAGS) == XKB_SUCCESS);
  174. /* Invalid flags */
  175. assert(xkb_machine_builder_update_a11y_flags(builder, -1000, 0) ==
  176. XKB_ERROR_UNSUPPORTED_A11Y_FLAGS);
  177. assert(xkb_machine_builder_update_a11y_flags(builder, 0, -1000) ==
  178. XKB_ERROR_UNSUPPORTED_A11Y_FLAGS);
  179. assert(xkb_machine_builder_update_a11y_flags(builder, 1000, 0) ==
  180. XKB_ERROR_UNSUPPORTED_A11Y_FLAGS);
  181. assert(xkb_machine_builder_update_a11y_flags(builder, 0, 1000) ==
  182. XKB_ERROR_UNSUPPORTED_A11Y_FLAGS);
  183. struct xkb_machine *sm = xkb_machine_new(builder);
  184. assert(sm);
  185. xkb_machine_unref(sm);
  186. xkb_machine_builder_destroy(builder);
  187. xkb_keymap_unref(keymap);
  188. }
  189. /* Check that derived state is correctly initialized */
  190. static void
  191. test_initial_derived_values(struct xkb_context *ctx)
  192. {
  193. struct xkb_keymap * const keymap = test_compile_rules(
  194. ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
  195. "pc104", "us", NULL, "grp1_led:scroll"
  196. );
  197. assert(keymap);
  198. struct xkb_machine_builder *builder =
  199. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  200. assert(builder);
  201. struct xkb_machine * const sm = xkb_machine_new(builder);
  202. assert(sm);
  203. struct xkb_state * const state = xkb_machine_get_state(sm);
  204. assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_SCROLL));
  205. xkb_machine_unref(sm);
  206. xkb_machine_builder_destroy(builder);
  207. xkb_keymap_unref(keymap);
  208. }
  209. /* ABI checks */
  210. static void
  211. test_state_update(struct xkb_context *ctx)
  212. {
  213. struct xkb_keymap * const keymap = test_compile_rules(
  214. ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
  215. "empty", "empty", NULL, NULL
  216. );
  217. assert(keymap);
  218. struct xkb_state * const state = xkb_state_new(keymap);
  219. assert(state);
  220. struct xkb_machine_builder *builder =
  221. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  222. struct xkb_machine * const sm = xkb_machine_new(builder);
  223. assert(sm);
  224. xkb_machine_builder_destroy(builder);
  225. struct xkb_events * const events = xkb_events_new_batch(ctx,
  226. XKB_EVENTS_NO_FLAGS);
  227. assert(events);
  228. /* Simulate a new version with some new fields */
  229. struct xkb_state_update_newer {
  230. union {
  231. size_t size;
  232. struct xkb_state_update current;
  233. };
  234. uint64_t extra;
  235. };
  236. /* Simulate a new version with some new fields */
  237. struct xkb_state_components_update_newer {
  238. union {
  239. size_t size;
  240. struct xkb_state_components_update current;
  241. };
  242. uint64_t extra;
  243. };
  244. /* Simulate a new version with some new fields */
  245. struct xkb_layout_policy_update_newer {
  246. union {
  247. size_t size;
  248. struct xkb_layout_policy_update current;
  249. };
  250. uint64_t extra;
  251. };
  252. static const struct {
  253. struct params {
  254. size_t size;
  255. uint64_t extra;
  256. bool enabled;
  257. } root;
  258. struct params components;
  259. struct params layout_policy;
  260. enum xkb_error_code error;
  261. } tests[] = {
  262. /*
  263. * Too small
  264. */
  265. {
  266. .root = { 0, 0 },
  267. .components = { .enabled = false },
  268. .layout_policy = { .enabled = false },
  269. .error = XKB_ERROR_ABI_INVALID_STRUCT_SIZE,
  270. },
  271. {
  272. .root = { 1, 0 },
  273. .components = { .enabled = false },
  274. .layout_policy = { .enabled = false },
  275. .error = XKB_ERROR_ABI_INVALID_STRUCT_SIZE,
  276. },
  277. {
  278. .root = { sizeof(struct xkb_state_update), 0 },
  279. .components = { .size = 0, .enabled = true },
  280. .layout_policy = { .enabled = false },
  281. .error = XKB_ERROR_ABI_INVALID_STRUCT_SIZE,
  282. },
  283. {
  284. .root = { sizeof(struct xkb_state_update), 0 },
  285. .components = { .size = 1, .enabled = true },
  286. .layout_policy = { .enabled = false },
  287. .error = XKB_ERROR_ABI_INVALID_STRUCT_SIZE,
  288. },
  289. {
  290. .root = { sizeof(struct xkb_state_update), 0 },
  291. .components = { .enabled = false },
  292. .layout_policy = { .size = 0, .enabled = true },
  293. .error = XKB_ERROR_ABI_INVALID_STRUCT_SIZE,
  294. },
  295. {
  296. .root = { sizeof(struct xkb_state_update), 0 },
  297. .components = { .enabled = false },
  298. .layout_policy = { .size = 1, .enabled = true },
  299. .error = XKB_ERROR_ABI_INVALID_STRUCT_SIZE,
  300. },
  301. /*
  302. * OK: current size
  303. */
  304. {
  305. .root = { sizeof(struct xkb_state_update), 0 },
  306. .components = { .enabled = false },
  307. .layout_policy = { .enabled = false },
  308. .error = XKB_SUCCESS,
  309. },
  310. {
  311. .root = { sizeof(struct xkb_state_update), 0 },
  312. .components = {
  313. .size = sizeof(struct xkb_state_components_update),
  314. .enabled = true
  315. },
  316. .layout_policy = { .enabled = false },
  317. .error = XKB_SUCCESS,
  318. },
  319. {
  320. .root = { sizeof(struct xkb_state_update), 0 },
  321. .components = { .enabled = false },
  322. .layout_policy = {
  323. .size = sizeof(struct xkb_layout_policy_update),
  324. .enabled = true
  325. },
  326. .error = XKB_SUCCESS,
  327. },
  328. /*
  329. * OK: too big, but no new field is set
  330. */
  331. {
  332. .root = { sizeof(struct xkb_state_update_newer), 0 },
  333. .components = { .enabled = false },
  334. .layout_policy = { .enabled = false },
  335. .error = XKB_SUCCESS,
  336. },
  337. {
  338. .root = { sizeof(struct xkb_state_update), 0 },
  339. .components = {
  340. .size = sizeof(struct xkb_state_components_update_newer),
  341. .enabled = true
  342. },
  343. .layout_policy = { .enabled = false },
  344. .error = XKB_SUCCESS,
  345. },
  346. {
  347. .root = { sizeof(struct xkb_state_update), 0 },
  348. .components = { .enabled = false },
  349. .layout_policy = {
  350. .size = sizeof(struct xkb_layout_policy_update_newer),
  351. .enabled = true
  352. },
  353. .error = XKB_SUCCESS,
  354. },
  355. /*
  356. * Too big
  357. */
  358. {
  359. .root = {
  360. sizeof(struct xkb_state_update_newer),
  361. (UINT64_C(1) << 0)
  362. },
  363. .components = { .enabled = false },
  364. .layout_policy = { .enabled = false },
  365. .error = XKB_ERROR_ABI_FORWARD_COMPAT,
  366. },
  367. {
  368. .root = {
  369. sizeof(struct xkb_state_update_newer),
  370. (UINT64_C(1) << 63)
  371. },
  372. .components = { .enabled = false },
  373. .layout_policy = { .enabled = false },
  374. .error = XKB_ERROR_ABI_FORWARD_COMPAT,
  375. },
  376. {
  377. .root = { sizeof(struct xkb_state_update), 0 },
  378. .components = {
  379. .enabled = true,
  380. .size = sizeof(struct xkb_state_components_update_newer),
  381. .extra = (UINT64_C(1) << 63),
  382. },
  383. .layout_policy = { .enabled = false },
  384. .error = XKB_ERROR_ABI_FORWARD_COMPAT,
  385. },
  386. {
  387. .root = { sizeof(struct xkb_state_update), 0 },
  388. .components = { .enabled = false },
  389. .layout_policy = {
  390. .enabled = true,
  391. .size = sizeof(struct xkb_layout_policy_update_newer),
  392. .extra = (UINT64_C(1) << 63),
  393. },
  394. .error = XKB_ERROR_ABI_FORWARD_COMPAT,
  395. },
  396. };
  397. for (size_t s = 0; s < ARRAY_SIZE(tests); s++) {
  398. fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, s);
  399. const struct xkb_state_components_update_newer components = {
  400. .current = {
  401. .size = tests[s].components.size,
  402. },
  403. .extra = tests[s].components.extra
  404. };
  405. const struct xkb_layout_policy_update_newer layout_policy = {
  406. .current = {
  407. .size = tests[s].layout_policy.size,
  408. },
  409. .extra = tests[s].layout_policy.extra
  410. };
  411. const struct xkb_state_update_newer update = {
  412. .current = {
  413. .size = tests[s].root.size,
  414. .components = (tests[s].components.enabled)
  415. ? (struct xkb_state_components_update*)&components
  416. : NULL,
  417. .layout_policy = (tests[s].layout_policy.enabled)
  418. ? (struct xkb_layout_policy_update*)&layout_policy
  419. : NULL,
  420. },
  421. .extra = tests[s].root.extra
  422. };
  423. assert_eq(
  424. "xkb_state_update_synthetic",
  425. tests[s].error,
  426. xkb_state_update_synthetic(state, (struct xkb_state_update *)&update,
  427. NULL),
  428. "%d"
  429. );
  430. assert_eq(
  431. "xkb_machine_process_synthetic",
  432. tests[s].error,
  433. xkb_machine_process_synthetic(sm, (struct xkb_state_update *)&update,
  434. events),
  435. "%d"
  436. );
  437. }
  438. xkb_events_destroy(events);
  439. xkb_machine_unref(sm);
  440. xkb_state_unref(state);
  441. xkb_keymap_unref(keymap);
  442. }
  443. static enum xkb_state_component
  444. update_key(struct xkb_machine *sm,
  445. struct xkb_events *events,
  446. struct xkb_state *state,
  447. bool use_machine, xkb_keycode_t key,
  448. enum xkb_key_direction direction)
  449. {
  450. if (use_machine) {
  451. assert(xkb_machine_process_key(sm, key, direction, events) == 0);
  452. const struct xkb_event *event;
  453. enum xkb_state_component changed = 0;
  454. while ((event = xkb_events_next(events))) {
  455. changed |= xkb_state_update_event(state, event);
  456. }
  457. return changed;
  458. } else {
  459. return xkb_state_update_key(state, key, direction);
  460. }
  461. }
  462. static enum xkb_state_component
  463. update_controls(struct xkb_machine *sm,
  464. struct xkb_events *events,
  465. struct xkb_state *state,
  466. bool use_machine,
  467. enum xkb_keyboard_control_flags affect,
  468. enum xkb_keyboard_control_flags controls)
  469. {
  470. if (use_machine) {
  471. assert(xkb_machine_update_enabled_controls(sm, events,
  472. affect, controls)
  473. == XKB_SUCCESS);
  474. const struct xkb_event *event;
  475. enum xkb_state_component changed = 0;
  476. while ((event = xkb_events_next(events))) {
  477. changed |= xkb_state_update_event(state, event);
  478. }
  479. return changed;
  480. } else {
  481. return xkb_state_update_enabled_controls(state, affect, controls);
  482. }
  483. }
  484. static void
  485. test_group_wrap(struct xkb_context *ctx)
  486. {
  487. static const char keymap_str[] =
  488. "default xkb_keymap {\n"
  489. " xkb_keycodes { <> = 1; };\n"
  490. " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n"
  491. " xkb_symbols {\n"
  492. " key <> { [a], [b], [c], [d] };\n"
  493. " };\n"
  494. "};";
  495. struct xkb_keymap * const keymap = test_compile_buffer(
  496. ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymap_str, sizeof(keymap_str)
  497. );
  498. assert(keymap);
  499. const xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(keymap);
  500. assert(num_layouts == 4);
  501. struct xkb_machine_builder *builder =
  502. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  503. assert(builder);
  504. struct xkb_machine * const sm = xkb_machine_new(builder);
  505. assert(sm);
  506. xkb_machine_builder_destroy(builder);
  507. struct xkb_state * const state = xkb_state_new(keymap);
  508. assert(state);
  509. struct xkb_events * const events = xkb_events_new_batch(ctx,
  510. XKB_EVENTS_NO_FLAGS);
  511. assert(events);
  512. const struct xkb_event *event;
  513. struct {
  514. enum xkb_layout_out_of_range_policy policy;
  515. xkb_layout_index_t redirect_group;
  516. xkb_layout_index_t locked_group;
  517. xkb_layout_index_t expected_group;
  518. } tests[] = {
  519. /*
  520. * Explicit: wrap
  521. */
  522. {
  523. .policy = XKB_LAYOUT_OUT_OF_RANGE_WRAP,
  524. .redirect_group = 0,
  525. .locked_group = (xkb_layout_index_t)-1,
  526. .expected_group = num_layouts - 1,
  527. },
  528. {
  529. .policy = XKB_LAYOUT_OUT_OF_RANGE_WRAP,
  530. .redirect_group = 0,
  531. .locked_group = num_layouts + 1,
  532. .expected_group = 1,
  533. },
  534. /*
  535. * Explicit: clamp
  536. */
  537. {
  538. .policy = XKB_LAYOUT_OUT_OF_RANGE_CLAMP,
  539. .redirect_group = 0,
  540. .locked_group = (xkb_layout_index_t)-1,
  541. .expected_group = 0,
  542. },
  543. {
  544. .policy = XKB_LAYOUT_OUT_OF_RANGE_CLAMP,
  545. .redirect_group = 0,
  546. .locked_group = num_layouts + 1,
  547. .expected_group = num_layouts - 1,
  548. },
  549. /*
  550. * Explicit: redirect
  551. */
  552. {
  553. .policy = XKB_LAYOUT_OUT_OF_RANGE_REDIRECT,
  554. .redirect_group = 2,
  555. .locked_group = (xkb_layout_index_t)-1,
  556. .expected_group = 2,
  557. },
  558. {
  559. .policy = XKB_LAYOUT_OUT_OF_RANGE_REDIRECT,
  560. .redirect_group = 2,
  561. .locked_group = num_layouts + 1,
  562. .expected_group = 2,
  563. },
  564. };
  565. for (uint8_t t = 0; t < (uint8_t) ARRAY_SIZE(tests); t++) {
  566. fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, t);
  567. struct xkb_layout_policy_update layout_policy = {
  568. .size = sizeof(layout_policy),
  569. .policy = tests[t].policy,
  570. .redirect = tests[t].redirect_group,
  571. };
  572. const struct xkb_state_components_update components = {
  573. .size = sizeof(components),
  574. .components = XKB_STATE_LAYOUT_LOCKED,
  575. .locked_layout = (int32_t)tests[t].locked_group
  576. };
  577. const struct xkb_state_update req = {
  578. .size = sizeof(req),
  579. .layout_policy = &layout_policy,
  580. .components = &components,
  581. };
  582. assert(xkb_machine_process_synthetic(sm, &req, events) == XKB_SUCCESS);
  583. while ((event = xkb_events_next(events)))
  584. xkb_state_update_event(state, event);
  585. assert_eq("unexpected effective group", tests[t].expected_group,
  586. xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE),
  587. "%"PRIu32);
  588. }
  589. xkb_events_destroy(events);
  590. xkb_state_unref(state);
  591. xkb_machine_unref(sm);
  592. xkb_keymap_unref(keymap);
  593. }
  594. static void
  595. test_sticky_keys(struct xkb_context *ctx)
  596. {
  597. struct xkb_keymap * const keymap = test_compile_rmlvo(
  598. ctx, XKB_KEYMAP_FORMAT_TEXT_V1,
  599. "evdev", "pc104", "ca,cz,de", NULL, "controls,grp:lwin_switch,grp:menu_toggle"
  600. );
  601. assert(keymap);
  602. struct xkb_machine_builder *builder =
  603. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  604. assert(builder);
  605. struct xkb_machine *sm = xkb_machine_new(builder);
  606. assert(sm);
  607. xkb_machine_builder_destroy(builder);
  608. struct xkb_events *events = xkb_events_new_batch(ctx, XKB_EVENTS_NO_FLAGS);
  609. assert(events);
  610. struct xkb_state *state = xkb_state_new(keymap);
  611. assert(state);
  612. const xkb_mod_mask_t shift = xkb_keymap_mod_get_mask2(keymap,
  613. XKB_MOD_INDEX_SHIFT);
  614. const xkb_mod_mask_t caps = xkb_keymap_mod_get_mask2(keymap,
  615. XKB_MOD_INDEX_CAPS);
  616. const xkb_mod_mask_t ctrl = xkb_keymap_mod_get_mask2(keymap,
  617. XKB_MOD_INDEX_CTRL);
  618. xkb_mod_mask_t mods = 0;
  619. enum xkb_keyboard_control_flags controls;
  620. enum xkb_state_component changed;
  621. controls = xkb_state_serialize_enabled_controls(state, XKB_STATE_CONTROLS);
  622. assert(controls == 0);
  623. enum sticky_key_activation {
  624. STICKY_KEY_ACTION_SETCONTROLS = 0,
  625. STICKY_KEY_ACTION_LOCKCONTROLS,
  626. STICKY_KEY_EVENTS_API,
  627. STICKY_KEY_LEGACY_API,
  628. };
  629. enum sticky_key_activation tests[] = {
  630. STICKY_KEY_ACTION_SETCONTROLS,
  631. STICKY_KEY_ACTION_LOCKCONTROLS,
  632. STICKY_KEY_EVENTS_API,
  633. STICKY_KEY_LEGACY_API,
  634. };
  635. for (uint8_t t = 0; t < (uint8_t) ARRAY_SIZE(tests); t++) {
  636. fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, t);
  637. const bool use_events = tests[t] == STICKY_KEY_EVENTS_API;
  638. /* Enable controls */
  639. switch (tests[t]) {
  640. case STICKY_KEY_ACTION_SETCONTROLS:
  641. /* SetControls() */
  642. changed = update_key(sm, events, state, use_events,
  643. KEY_F1 + EVDEV_OFFSET, XKB_KEY_DOWN);
  644. assert(changed == XKB_STATE_CONTROLS);
  645. break;
  646. case STICKY_KEY_ACTION_LOCKCONTROLS:
  647. /* LockControls() */
  648. changed = update_key(sm, events, state, use_events,
  649. KEY_F2 + EVDEV_OFFSET, XKB_KEY_DOWN);
  650. assert(changed == XKB_STATE_CONTROLS);
  651. controls = xkb_state_serialize_enabled_controls(state, XKB_STATE_CONTROLS);
  652. assert(controls == XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS);
  653. changed = update_key(sm, events, state, use_events,
  654. KEY_F2 + EVDEV_OFFSET, XKB_KEY_UP);
  655. assert(changed == 0);
  656. break;
  657. case STICKY_KEY_EVENTS_API: {
  658. changed = update_controls(sm, events, state, true,
  659. XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS,
  660. XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS);
  661. assert(changed == XKB_STATE_CONTROLS);
  662. controls = xkb_state_serialize_enabled_controls(state, XKB_STATE_CONTROLS);
  663. assert(controls == XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS);
  664. break;
  665. }
  666. case STICKY_KEY_LEGACY_API:
  667. changed = xkb_state_update_enabled_controls(
  668. state,
  669. XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS,
  670. XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS
  671. );
  672. assert(changed == XKB_STATE_CONTROLS);
  673. controls = xkb_state_serialize_enabled_controls(state, XKB_STATE_CONTROLS);
  674. assert(controls == XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS);
  675. break;
  676. }
  677. controls = xkb_state_serialize_enabled_controls(state, XKB_STATE_CONTROLS);
  678. assert(controls == XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS);
  679. /* Latch shift (sticky) */
  680. changed = update_key(sm, events, state, use_events,
  681. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
  682. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
  683. changed = update_key(sm, events, state, use_events,
  684. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
  685. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED));
  686. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  687. assert(mods == shift);
  688. /* No latch-to-lock */
  689. changed = update_key(sm, events, state, use_events,
  690. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
  691. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED));
  692. changed = update_key(sm, events, state, use_events,
  693. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
  694. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
  695. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  696. assert(mods == 0);
  697. /* Latch shift (sticky) and control */
  698. changed = update_key(sm, events, state, use_events,
  699. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
  700. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
  701. changed = update_key(sm, events, state, use_events,
  702. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
  703. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED));
  704. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  705. assert(mods == shift);
  706. changed = update_key(sm, events, state, use_events,
  707. KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN);
  708. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
  709. changed = update_key(sm, events, state, use_events,
  710. KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP);
  711. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED));
  712. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  713. assert(mods == (shift | ctrl));
  714. changed = update_key(sm, events, state, use_events,
  715. KEY_Q + EVDEV_OFFSET, XKB_KEY_DOWN);
  716. assert(changed == (XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE));
  717. changed = update_key(sm, events, state, use_events,
  718. KEY_Q + EVDEV_OFFSET, XKB_KEY_UP);
  719. assert(changed == 0);
  720. /* Latch (sticky) & lock groups */
  721. changed = update_key(sm, events, state, use_events,
  722. KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN);
  723. assert(changed == (XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE |
  724. XKB_STATE_LEDS));
  725. changed = update_key(sm, events, state, use_events,
  726. KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP);
  727. assert(changed == 0);
  728. assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED) == 1);
  729. assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 1);
  730. changed = update_key(sm, events, state, use_events,
  731. KEY_LEFTMETA + EVDEV_OFFSET, XKB_KEY_DOWN);
  732. assert(changed == (XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE));
  733. changed = update_key(sm, events, state, use_events,
  734. KEY_LEFTMETA + EVDEV_OFFSET, XKB_KEY_UP);
  735. assert(changed == (XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED));
  736. assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED) == 1);
  737. assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED) == 1);
  738. assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 2);
  739. /* Latch shift (sticky) and lock Caps */
  740. changed = update_key(sm, events, state, use_events,
  741. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
  742. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
  743. changed = update_key(sm, events, state, use_events,
  744. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
  745. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED));
  746. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  747. assert(mods == shift);
  748. changed = update_key(sm, events, state, use_events,
  749. KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
  750. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED |
  751. XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS));
  752. changed = update_key(sm, events, state, use_events,
  753. KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
  754. assert(changed == (XKB_STATE_MODS_DEPRESSED));
  755. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  756. assert(mods == (shift | caps));
  757. /* Disable controls */
  758. switch (tests[t]) {
  759. case STICKY_KEY_ACTION_SETCONTROLS:
  760. /* SetControls() */
  761. changed = update_key(sm, events, state, use_events,
  762. KEY_F1 + EVDEV_OFFSET, XKB_KEY_UP);
  763. assert(changed == (XKB_STATE_CONTROLS |
  764. XKB_STATE_LAYOUT_LATCHED |
  765. XKB_STATE_LAYOUT_LOCKED |
  766. XKB_STATE_LAYOUT_EFFECTIVE |
  767. XKB_STATE_MODS_LATCHED |
  768. XKB_STATE_MODS_LOCKED |
  769. XKB_STATE_MODS_EFFECTIVE |
  770. XKB_STATE_LEDS));
  771. break;
  772. case STICKY_KEY_ACTION_LOCKCONTROLS:
  773. /* LockControls() */
  774. changed = update_key(sm, events, state, use_events,
  775. KEY_F2 + EVDEV_OFFSET, XKB_KEY_DOWN);
  776. assert(changed == (XKB_STATE_MODS_LATCHED |
  777. XKB_STATE_MODS_EFFECTIVE |
  778. XKB_STATE_LAYOUT_LATCHED |
  779. XKB_STATE_LAYOUT_EFFECTIVE));
  780. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  781. assert(mods == caps);
  782. changed = update_key(sm, events, state, use_events,
  783. KEY_F2 + EVDEV_OFFSET, XKB_KEY_UP);
  784. assert(changed == (XKB_STATE_CONTROLS |
  785. XKB_STATE_LAYOUT_LOCKED |
  786. XKB_STATE_LAYOUT_EFFECTIVE |
  787. XKB_STATE_MODS_LOCKED |
  788. XKB_STATE_MODS_EFFECTIVE |
  789. XKB_STATE_LEDS));
  790. break;
  791. case STICKY_KEY_EVENTS_API: {
  792. changed = update_controls(sm, events, state, true,
  793. XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS, 0);
  794. assert(changed == (XKB_STATE_CONTROLS |
  795. XKB_STATE_LAYOUT_LATCHED |
  796. XKB_STATE_LAYOUT_LOCKED |
  797. XKB_STATE_LAYOUT_EFFECTIVE |
  798. XKB_STATE_MODS_LATCHED |
  799. XKB_STATE_MODS_LOCKED |
  800. XKB_STATE_MODS_EFFECTIVE |
  801. XKB_STATE_LEDS));
  802. break;
  803. }
  804. case STICKY_KEY_LEGACY_API:
  805. changed = xkb_state_update_enabled_controls(
  806. state, XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS, 0
  807. );
  808. assert(changed == (XKB_STATE_CONTROLS |
  809. XKB_STATE_LAYOUT_LATCHED |
  810. XKB_STATE_LAYOUT_LOCKED |
  811. XKB_STATE_LAYOUT_EFFECTIVE |
  812. XKB_STATE_MODS_LATCHED |
  813. XKB_STATE_MODS_LOCKED |
  814. XKB_STATE_MODS_EFFECTIVE |
  815. XKB_STATE_LEDS));
  816. break;
  817. }
  818. controls = xkb_state_serialize_enabled_controls(state, XKB_STATE_CONTROLS);
  819. assert(controls == 0);
  820. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  821. assert(mods == 0);
  822. assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0);
  823. /* Mods are not latched anymore */
  824. changed = update_key(sm, events, state, use_events,
  825. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
  826. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
  827. changed = update_key(sm, events, state, use_events,
  828. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
  829. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
  830. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  831. assert(mods == 0);
  832. controls = xkb_state_serialize_enabled_controls(state, XKB_STATE_CONTROLS);
  833. assert(controls == 0);
  834. }
  835. xkb_state_unref(state);
  836. xkb_events_destroy(events);
  837. xkb_machine_unref(sm);
  838. /*
  839. * Test latch-to-lock
  840. */
  841. struct xkb_machine_builder * const sm_builder =
  842. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  843. assert(sm_builder);
  844. assert(xkb_machine_builder_update_a11y_flags(
  845. sm_builder,
  846. XKB_A11Y_STICKY_KEYS_LATCH_TO_LOCK,
  847. XKB_A11Y_STICKY_KEYS_LATCH_TO_LOCK) == XKB_SUCCESS);
  848. sm = xkb_machine_new(sm_builder);
  849. assert(sm);
  850. xkb_machine_builder_destroy(sm_builder);
  851. events = xkb_events_new_batch(ctx, XKB_EVENTS_NO_FLAGS);
  852. assert(events);
  853. state = xkb_state_new(keymap);
  854. assert(state);
  855. update_controls(sm, events, state, true,
  856. XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS,
  857. XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS);
  858. /* Latch shift */
  859. changed = update_key(sm, events, state, true,
  860. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
  861. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
  862. changed = update_key(sm, events, state, true,
  863. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
  864. assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED));
  865. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
  866. assert(mods == shift);
  867. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  868. assert(mods == shift);
  869. /* Lock shift */
  870. changed = update_key(sm, events, state, true,
  871. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
  872. assert(changed == ( XKB_STATE_MODS_DEPRESSED |
  873. XKB_STATE_MODS_LATCHED |
  874. XKB_STATE_MODS_LOCKED |
  875. XKB_STATE_LEDS /* shift-lock */));
  876. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
  877. assert(mods == shift);
  878. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
  879. assert(mods == 0);
  880. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED);
  881. assert(mods == shift);
  882. changed = update_key(sm, events, state, true,
  883. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
  884. assert(changed == XKB_STATE_MODS_DEPRESSED);
  885. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  886. assert(mods == shift);
  887. /* Unlock shift */
  888. changed = update_key(sm, events, state, true,
  889. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
  890. assert(changed == XKB_STATE_MODS_DEPRESSED);
  891. changed = update_key(sm, events, state, true,
  892. KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
  893. assert(changed == ( XKB_STATE_MODS_DEPRESSED |
  894. XKB_STATE_MODS_LOCKED |
  895. XKB_STATE_MODS_EFFECTIVE |
  896. XKB_STATE_LEDS /* shift-lock */));
  897. mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
  898. assert(mods == 0);
  899. xkb_state_unref(state);
  900. xkb_events_destroy(events);
  901. xkb_machine_unref(sm);
  902. xkb_keymap_unref(keymap);
  903. }
  904. static void
  905. test_redirect_key(struct xkb_context *ctx)
  906. {
  907. struct xkb_keymap * const keymap = test_compile_file(
  908. ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "keymaps/redirect-key-1.xkb"
  909. );
  910. assert(keymap);
  911. struct xkb_machine_builder *builder =
  912. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  913. assert(builder);
  914. struct xkb_machine *sm = xkb_machine_new(builder);
  915. assert(sm);
  916. xkb_machine_builder_destroy(builder);
  917. static const xkb_mod_mask_t shift = UINT32_C(1) << XKB_MOD_INDEX_SHIFT;
  918. static const xkb_mod_mask_t ctrl = UINT32_C(1) << XKB_MOD_INDEX_CTRL;
  919. struct xkb_events *events = xkb_events_new_batch(ctx, XKB_EVENTS_NO_FLAGS);
  920. assert(events);
  921. assert(test_key_seq2(
  922. keymap, sm, events,
  923. KEY_A, BOTH, XKB_KEY_a, NEXT,
  924. KEY_A, DOWN, XKB_KEY_a, NEXT,
  925. KEY_A, REPEAT, XKB_KEY_a, NEXT,
  926. KEY_A, UP, XKB_KEY_a, NEXT,
  927. KEY_S, BOTH, XKB_KEY_a, NEXT,
  928. KEY_S, DOWN, XKB_KEY_a, NEXT,
  929. KEY_S, REPEAT, XKB_KEY_a, NEXT,
  930. KEY_S, UP, XKB_KEY_a, NEXT,
  931. KEY_D, BOTH, XKB_KEY_s, NEXT,
  932. KEY_D, DOWN, XKB_KEY_s, NEXT,
  933. KEY_D, REPEAT, XKB_KEY_s, NEXT,
  934. KEY_D, UP, XKB_KEY_s, FINISH
  935. ));
  936. xkb_machine_update_latched_locked(sm, events, 0, 0, false, 0,
  937. ctrl, ctrl, false, 0);
  938. const struct {
  939. xkb_keycode_t keycode;
  940. bool repeats;
  941. struct test_events {
  942. struct xkb_event events[3];
  943. unsigned int events_count;
  944. } down;
  945. struct test_events up;
  946. } tests[] = {
  947. {
  948. .keycode = EVDEV_OFFSET + KEY_A,
  949. .repeats = false,
  950. .down = {
  951. .events = {
  952. {
  953. .type = XKB_EVENT_TYPE_KEY_DOWN,
  954. .keycode = EVDEV_OFFSET + KEY_A
  955. }
  956. },
  957. .events_count = 1
  958. },
  959. .up = {
  960. .events = {
  961. {
  962. .type = XKB_EVENT_TYPE_KEY_UP,
  963. .keycode = EVDEV_OFFSET + KEY_A
  964. }
  965. },
  966. .events_count = 1
  967. }
  968. },
  969. {
  970. .keycode = EVDEV_OFFSET + KEY_S,
  971. .repeats = true,
  972. .down = {
  973. .events = {
  974. {
  975. .type = XKB_EVENT_TYPE_KEY_DOWN,
  976. .keycode = EVDEV_OFFSET + KEY_A
  977. }
  978. },
  979. .events_count = 1
  980. },
  981. .up = {
  982. .events = {
  983. {
  984. .type = XKB_EVENT_TYPE_KEY_UP,
  985. .keycode = EVDEV_OFFSET + KEY_A
  986. }
  987. },
  988. .events_count = 1
  989. }
  990. },
  991. {
  992. .keycode = EVDEV_OFFSET + KEY_D,
  993. .repeats = true,
  994. .down = {
  995. .events = {
  996. {
  997. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  998. .components = {
  999. .components = {
  1000. .base_mods = shift,
  1001. .latched_mods = shift,
  1002. .locked_mods = shift,
  1003. .mods = shift,
  1004. },
  1005. .changed = XKB_STATE_MODS_DEPRESSED
  1006. | XKB_STATE_MODS_LATCHED
  1007. | XKB_STATE_MODS_LOCKED
  1008. | XKB_STATE_MODS_EFFECTIVE
  1009. }
  1010. },
  1011. {
  1012. .type = XKB_EVENT_TYPE_KEY_DOWN,
  1013. .keycode = EVDEV_OFFSET + KEY_S
  1014. },
  1015. {
  1016. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1017. .components = {
  1018. .components = {
  1019. .base_mods = 0,
  1020. .latched_mods = 0,
  1021. .locked_mods = ctrl,
  1022. .mods = ctrl,
  1023. },
  1024. .changed = XKB_STATE_MODS_DEPRESSED
  1025. | XKB_STATE_MODS_LATCHED
  1026. | XKB_STATE_MODS_LOCKED
  1027. | XKB_STATE_MODS_EFFECTIVE
  1028. }
  1029. },
  1030. },
  1031. .events_count = 3
  1032. },
  1033. .up = {
  1034. .events = {
  1035. {
  1036. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1037. .components = {
  1038. .components = {
  1039. .base_mods = shift,
  1040. .latched_mods = shift,
  1041. .locked_mods = shift,
  1042. .mods = shift,
  1043. },
  1044. .changed = XKB_STATE_MODS_DEPRESSED
  1045. | XKB_STATE_MODS_LATCHED
  1046. | XKB_STATE_MODS_LOCKED
  1047. | XKB_STATE_MODS_EFFECTIVE
  1048. }
  1049. },
  1050. {
  1051. .type = XKB_EVENT_TYPE_KEY_UP,
  1052. .keycode = EVDEV_OFFSET + KEY_S
  1053. },
  1054. {
  1055. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1056. .components = {
  1057. .components = {
  1058. .base_mods = 0,
  1059. .latched_mods = 0,
  1060. .locked_mods = ctrl,
  1061. .mods = ctrl,
  1062. },
  1063. .changed = XKB_STATE_MODS_DEPRESSED
  1064. | XKB_STATE_MODS_LATCHED
  1065. | XKB_STATE_MODS_LOCKED
  1066. | XKB_STATE_MODS_EFFECTIVE
  1067. }
  1068. },
  1069. },
  1070. .events_count = 3
  1071. }
  1072. },
  1073. };
  1074. for (uint8_t t = 0; t < (uint8_t) ARRAY_SIZE(tests); t++) {
  1075. fprintf(stderr, "------\n*** %s: #%u, keycode: %"PRIu32" ***\n",
  1076. __func__, t, tests[t].keycode);
  1077. assert(xkb_keymap_key_repeats(keymap, tests[t].keycode) ==
  1078. tests[t].repeats);
  1079. assert(xkb_machine_process_key(sm, tests[t].keycode,
  1080. XKB_KEY_DOWN, events) == XKB_SUCCESS);
  1081. assert(check_events(events, tests[t].down.events,
  1082. tests[t].down.events_count));
  1083. assert(xkb_machine_process_key(sm, tests[t].keycode,
  1084. XKB_KEY_REPEATED, events) == XKB_SUCCESS);
  1085. if (tests[t].repeats) {
  1086. struct xkb_event ref[ARRAY_SIZE(tests->down.events)] = {0};
  1087. memcpy(ref, tests[t].down.events, sizeof(tests->down.events));
  1088. ref[tests[t].down.events_count == 3].type =
  1089. XKB_EVENT_TYPE_KEY_REPEATED;
  1090. assert(check_events(events, ref, tests[t].down.events_count));
  1091. } else {
  1092. assert(check_events(events, NULL, 0));
  1093. }
  1094. assert(xkb_machine_process_key(sm, tests[t].keycode,
  1095. XKB_KEY_UP, events) == XKB_SUCCESS);
  1096. assert(check_events(events, tests[t].up.events,
  1097. tests[t].up.events_count));
  1098. }
  1099. xkb_events_destroy(events);
  1100. xkb_machine_unref(sm);
  1101. xkb_keymap_unref(keymap);
  1102. }
  1103. static void
  1104. test_shortcuts_tweak(struct xkb_context *context)
  1105. {
  1106. struct xkb_keymap * const keymap =
  1107. test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V2,
  1108. "evdev", "pc104", "us,il,de,ru", ",,neo,",
  1109. "grp:menu_toggle,grp:win_switch,ctrl:rctrl_latch,ctrl:copy");
  1110. assert(keymap);
  1111. const xkb_mod_mask_t ctrl = UINT32_C(1) << XKB_MOD_INDEX_CTRL;
  1112. const xkb_mod_mask_t alt = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_ALT);
  1113. const xkb_mod_mask_t level3 = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_LEVEL3);
  1114. const xkb_mod_mask_t level5 = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_LEVEL5);
  1115. struct xkb_machine_builder *builder =
  1116. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  1117. assert(builder);
  1118. assert(xkb_machine_builder_update_shortcut_mods(builder, ctrl, ctrl) == XKB_SUCCESS);
  1119. assert(xkb_machine_builder_remap_shortcut_layout(builder, 1, 2) == XKB_SUCCESS);
  1120. assert(xkb_machine_builder_remap_shortcut_layout(builder, 3, 0) == XKB_SUCCESS);
  1121. struct xkb_machine * sm = xkb_machine_new(builder);
  1122. assert(sm);
  1123. struct xkb_events * const events = xkb_events_new_batch(context,
  1124. XKB_EVENTS_NO_FLAGS);
  1125. assert(events);
  1126. /*
  1127. * xkb_machine_process_key
  1128. */
  1129. assert(test_key_seq2(
  1130. keymap, sm, events,
  1131. KEY_Q , BOTH, XKB_KEY_q , NEXT,
  1132. KEY_Z , BOTH, XKB_KEY_z , NEXT,
  1133. KEY_C , BOTH, XKB_KEY_c , NEXT,
  1134. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  1135. KEY_Q , BOTH, XKB_KEY_q , NEXT,
  1136. KEY_Z , BOTH, XKB_KEY_z , NEXT,
  1137. KEY_C , BOTH, XKB_KEY_XF86Copy , NEXT,
  1138. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  1139. KEY_LEFTALT , DOWN, XKB_KEY_Alt_L , NEXT,
  1140. KEY_Q , BOTH, XKB_KEY_q , NEXT,
  1141. KEY_Z , BOTH, XKB_KEY_z , NEXT,
  1142. KEY_LEFTALT , UP , XKB_KEY_Alt_L , NEXT,
  1143. /* Layout 2: set */
  1144. KEY_LEFTMETA, DOWN, XKB_KEY_ISO_Group_Shift, NEXT,
  1145. KEY_Q , BOTH, XKB_KEY_slash , NEXT, /* Layout 2 */
  1146. KEY_Z , BOTH, XKB_KEY_hebrew_zain , NEXT,
  1147. KEY_LEFTMETA, UP , XKB_KEY_ISO_Group_Shift, NEXT,
  1148. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  1149. KEY_Q , BOTH, XKB_KEY_q , NEXT, /* Layout 1 (unchanged) */
  1150. KEY_Z , BOTH, XKB_KEY_z , NEXT,
  1151. KEY_LEFTMETA, DOWN, XKB_KEY_ISO_Group_Shift, NEXT, /* Layout 2 */
  1152. KEY_Q , BOTH, XKB_KEY_x , NEXT, /* Redirect to layout 3 */
  1153. KEY_Z , BOTH, XKB_KEY_udiaeresis , NEXT,
  1154. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  1155. KEY_Q , BOTH, XKB_KEY_slash , NEXT, /* Layout 2 */
  1156. KEY_Z , BOTH, XKB_KEY_hebrew_zain , NEXT,
  1157. KEY_LEFTALT , DOWN, XKB_KEY_Alt_L , NEXT,
  1158. KEY_Q , BOTH, XKB_KEY_slash , NEXT, /* No redirection with Alt */
  1159. KEY_Z , BOTH, XKB_KEY_hebrew_zain , NEXT,
  1160. KEY_LEFTALT , UP , XKB_KEY_Alt_L , NEXT,
  1161. KEY_LEFTMETA, UP , XKB_KEY_ISO_Group_Shift, NEXT, /* Layout 1 */
  1162. /* Layout 2: lock */
  1163. KEY_COMPOSE , BOTH, XKB_KEY_ISO_Next_Group, NEXT,
  1164. KEY_Q , BOTH, XKB_KEY_slash , NEXT,
  1165. KEY_Z , BOTH, XKB_KEY_hebrew_zain , NEXT,
  1166. KEY_102ND , BOTH, XKB_KEY_less , NEXT,
  1167. /* Match mask: redirect to layout 3 */
  1168. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  1169. KEY_Q , BOTH, XKB_KEY_x , NEXT,
  1170. KEY_Q , DOWN, XKB_KEY_x , NEXT,
  1171. KEY_Q , REPEAT, XKB_KEY_x , NEXT,
  1172. KEY_Q , UP , XKB_KEY_x , NEXT,
  1173. KEY_Z , BOTH, XKB_KEY_udiaeresis , NEXT,
  1174. KEY_102ND , DOWN, XKB_KEY_ISO_Level5_Shift, NEXT,
  1175. KEY_102ND , UP , XKB_KEY_ISO_Level5_Lock, NEXT,
  1176. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  1177. KEY_Q , BOTH, XKB_KEY_slash , NEXT,
  1178. KEY_Z , BOTH, XKB_KEY_hebrew_zain , NEXT,
  1179. /* No match: no redirect */
  1180. KEY_LEFTALT , DOWN, XKB_KEY_Alt_L , NEXT,
  1181. KEY_Q , BOTH, XKB_KEY_slash , NEXT,
  1182. KEY_Z , BOTH, XKB_KEY_hebrew_zain , NEXT,
  1183. KEY_102ND , BOTH, XKB_KEY_less , NEXT,
  1184. /* Match mask: redirect to layout 3 */
  1185. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  1186. KEY_Q , BOTH, XKB_KEY_x , NEXT,
  1187. KEY_Z , BOTH, XKB_KEY_udiaeresis , NEXT,
  1188. KEY_102ND , DOWN, XKB_KEY_ISO_Level5_Shift, NEXT,
  1189. KEY_102ND , UP , XKB_KEY_ISO_Level5_Lock, NEXT,
  1190. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  1191. KEY_Q , BOTH, XKB_KEY_slash , NEXT,
  1192. KEY_Z , BOTH, XKB_KEY_hebrew_zain , NEXT,
  1193. KEY_102ND , BOTH, XKB_KEY_less , NEXT,
  1194. KEY_LEFTALT , UP , XKB_KEY_Alt_L , NEXT,
  1195. KEY_COMPOSE , BOTH, XKB_KEY_ISO_Next_Group, NEXT,
  1196. /* Layout 3 */
  1197. KEY_Q , BOTH, XKB_KEY_x , NEXT,
  1198. KEY_Z , BOTH, XKB_KEY_udiaeresis , NEXT,
  1199. KEY_C , BOTH, XKB_KEY_adiaeresis , NEXT,
  1200. KEY_102ND , DOWN, XKB_KEY_ISO_Level5_Shift, NEXT,
  1201. KEY_102ND , UP , XKB_KEY_ISO_Level5_Lock, NEXT,
  1202. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  1203. KEY_Q , BOTH, XKB_KEY_x , NEXT,
  1204. KEY_Z , BOTH, XKB_KEY_udiaeresis , NEXT,
  1205. KEY_C , BOTH, XKB_KEY_adiaeresis , NEXT,
  1206. KEY_102ND , DOWN, XKB_KEY_ISO_Level5_Shift, NEXT,
  1207. KEY_102ND , UP , XKB_KEY_ISO_Level5_Lock, NEXT,
  1208. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  1209. KEY_LEFTALT , DOWN, XKB_KEY_Alt_L , NEXT,
  1210. KEY_Q , BOTH, XKB_KEY_x , NEXT,
  1211. KEY_Z , BOTH, XKB_KEY_udiaeresis , NEXT,
  1212. KEY_102ND , DOWN, XKB_KEY_ISO_Level5_Shift, NEXT,
  1213. KEY_102ND , UP , XKB_KEY_ISO_Level5_Lock, NEXT,
  1214. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  1215. KEY_Q , BOTH, XKB_KEY_x , NEXT,
  1216. KEY_Z , BOTH, XKB_KEY_udiaeresis , NEXT,
  1217. KEY_C , BOTH, XKB_KEY_adiaeresis , NEXT,
  1218. KEY_102ND , DOWN, XKB_KEY_ISO_Level5_Shift, NEXT,
  1219. KEY_102ND , UP , XKB_KEY_ISO_Level5_Lock, NEXT,
  1220. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  1221. KEY_LEFTALT , UP , XKB_KEY_Alt_L , NEXT,
  1222. KEY_COMPOSE , BOTH, XKB_KEY_ISO_Next_Group, NEXT,
  1223. /* Layout 4 */
  1224. KEY_Q , BOTH, XKB_KEY_Cyrillic_shorti, NEXT,
  1225. KEY_Z , BOTH, XKB_KEY_Cyrillic_ya , NEXT,
  1226. KEY_C , BOTH, XKB_KEY_Cyrillic_es , NEXT,
  1227. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  1228. KEY_Q , BOTH, XKB_KEY_q , NEXT,
  1229. KEY_Z , BOTH, XKB_KEY_z , NEXT,
  1230. KEY_C , BOTH, XKB_KEY_XF86Copy , NEXT,
  1231. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  1232. KEY_LEFTALT , DOWN, XKB_KEY_Alt_L , NEXT,
  1233. KEY_Q , BOTH, XKB_KEY_Cyrillic_shorti, NEXT,
  1234. KEY_Z , BOTH, XKB_KEY_Cyrillic_ya , NEXT,
  1235. KEY_C , BOTH, XKB_KEY_Cyrillic_es , NEXT,
  1236. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  1237. KEY_Q , BOTH, XKB_KEY_q , NEXT,
  1238. KEY_Z , BOTH, XKB_KEY_z , NEXT,
  1239. KEY_C , BOTH, XKB_KEY_XF86Copy , NEXT,
  1240. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  1241. KEY_LEFTALT , UP , XKB_KEY_Alt_L , NEXT,
  1242. KEY_COMPOSE , BOTH, XKB_KEY_ISO_Next_Group , NEXT,
  1243. /* Layout 1 */
  1244. KEY_Q , BOTH, XKB_KEY_q , NEXT,
  1245. KEY_Z , BOTH, XKB_KEY_z , NEXT,
  1246. /* Layout 2 */
  1247. KEY_COMPOSE , BOTH, XKB_KEY_ISO_Next_Group, NEXT,
  1248. KEY_Q , BOTH, XKB_KEY_slash , NEXT,
  1249. KEY_Z , BOTH, XKB_KEY_hebrew_zain , NEXT,
  1250. KEY_102ND , BOTH, XKB_KEY_less , NEXT,
  1251. KEY_RIGHTCTRL,BOTH, XKB_KEY_Control_R , FINISH
  1252. ));
  1253. const xkb_led_mask_t group2 =
  1254. UINT32_C(1) << xkb_keymap_led_get_index(keymap, "Group 2");
  1255. /*
  1256. * xkb_machine_process_key
  1257. */
  1258. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  1259. XKB_KEY_DOWN, events) == 0);
  1260. check_events_(
  1261. events,
  1262. {
  1263. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1264. .components = {
  1265. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1266. .components = {
  1267. .latched_mods = ctrl,
  1268. .locked_mods = 0,
  1269. .mods = ctrl,
  1270. .base_group = 1,
  1271. .latched_group = 0,
  1272. .locked_group = 1,
  1273. .group = 2,
  1274. .leds = group2,
  1275. }
  1276. }
  1277. },
  1278. {
  1279. .type = XKB_EVENT_TYPE_KEY_DOWN,
  1280. .keycode = KEY_Q + EVDEV_OFFSET
  1281. },
  1282. {
  1283. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1284. .components = {
  1285. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1286. .components = {
  1287. .latched_mods = ctrl,
  1288. .locked_mods = 0,
  1289. .mods = ctrl,
  1290. .base_group = 0,
  1291. .latched_group = 0,
  1292. .locked_group = 1,
  1293. .group = 1,
  1294. .leds = group2,
  1295. }
  1296. }
  1297. },
  1298. {
  1299. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1300. .components = {
  1301. .changed = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE,
  1302. .components = {
  1303. .latched_mods = 0,
  1304. .locked_mods = 0,
  1305. .mods = 0,
  1306. .base_group = 0,
  1307. .latched_group = 0,
  1308. .locked_group = 1,
  1309. .group = 1,
  1310. .leds = group2,
  1311. }
  1312. }
  1313. },
  1314. );
  1315. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  1316. XKB_KEY_REPEATED, events) == 0);
  1317. check_events_(
  1318. events,
  1319. {
  1320. .type = XKB_EVENT_TYPE_KEY_REPEATED,
  1321. .keycode = KEY_Q + EVDEV_OFFSET
  1322. },
  1323. );
  1324. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  1325. XKB_KEY_UP, events) == 0);
  1326. check_events_(
  1327. events,
  1328. {
  1329. .type = XKB_EVENT_TYPE_KEY_UP,
  1330. .keycode = KEY_Q + EVDEV_OFFSET
  1331. }
  1332. );
  1333. assert(xkb_machine_process_key(sm, KEY_RIGHTCTRL + EVDEV_OFFSET,
  1334. XKB_KEY_DOWN, events) == 0);
  1335. check_events_(
  1336. events,
  1337. {
  1338. .type = XKB_EVENT_TYPE_KEY_DOWN,
  1339. .keycode = KEY_RIGHTCTRL + EVDEV_OFFSET
  1340. },
  1341. {
  1342. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1343. .components = {
  1344. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  1345. .components = {
  1346. .base_mods = ctrl,
  1347. .latched_mods = 0,
  1348. .locked_mods = 0,
  1349. .mods = ctrl,
  1350. .base_group = 0,
  1351. .latched_group = 0,
  1352. .locked_group = 1,
  1353. .group = 1,
  1354. .leds = group2,
  1355. }
  1356. }
  1357. },
  1358. );
  1359. assert(xkb_machine_process_key(sm, KEY_RIGHTCTRL + EVDEV_OFFSET,
  1360. XKB_KEY_REPEATED, events) == 0);
  1361. check_events_(
  1362. events,
  1363. { .type = XKB_EVENT_TYPE_NONE }, /* does not repeat */
  1364. );
  1365. assert(xkb_machine_process_key(sm, KEY_RIGHTCTRL + EVDEV_OFFSET,
  1366. XKB_KEY_UP, events) == 0);
  1367. check_events_(
  1368. events,
  1369. {
  1370. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1371. .components = {
  1372. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1373. .components = {
  1374. .base_mods = ctrl,
  1375. .latched_mods = 0,
  1376. .locked_mods = 0,
  1377. .mods = ctrl,
  1378. .base_group = 1,
  1379. .latched_group = 0,
  1380. .locked_group = 1,
  1381. .group = 2,
  1382. .leds = group2,
  1383. }
  1384. }
  1385. },
  1386. {
  1387. .type = XKB_EVENT_TYPE_KEY_UP,
  1388. .keycode = KEY_RIGHTCTRL + EVDEV_OFFSET
  1389. },
  1390. {
  1391. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1392. .components = {
  1393. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1394. .components = {
  1395. .base_mods = ctrl,
  1396. .latched_mods = 0,
  1397. .locked_mods = 0,
  1398. .mods = ctrl,
  1399. .base_group = 0,
  1400. .latched_group = 0,
  1401. .locked_group = 1,
  1402. .group = 1,
  1403. .leds = group2,
  1404. }
  1405. }
  1406. },
  1407. {
  1408. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1409. .components = {
  1410. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED,
  1411. .components = {
  1412. .base_mods = 0,
  1413. .latched_mods = ctrl,
  1414. .locked_mods = 0,
  1415. .mods = ctrl,
  1416. .base_group = 0,
  1417. .latched_group = 0,
  1418. .locked_group = 1,
  1419. .group = 1,
  1420. .leds = group2,
  1421. }
  1422. }
  1423. },
  1424. );
  1425. assert(xkb_machine_process_key(sm, KEY_102ND + EVDEV_OFFSET,
  1426. XKB_KEY_DOWN, events) == 0);
  1427. check_events_(
  1428. events,
  1429. {
  1430. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1431. .components = {
  1432. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1433. .components = {
  1434. .latched_mods = ctrl,
  1435. .locked_mods = 0,
  1436. .mods = ctrl,
  1437. .base_group = 1,
  1438. .latched_group = 0,
  1439. .locked_group = 1,
  1440. .group = 2,
  1441. .leds = group2,
  1442. }
  1443. }
  1444. },
  1445. {
  1446. .type = XKB_EVENT_TYPE_KEY_DOWN,
  1447. .keycode = KEY_102ND + EVDEV_OFFSET
  1448. },
  1449. {
  1450. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1451. .components = {
  1452. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1453. .components = {
  1454. .base_mods = 0,
  1455. .latched_mods = ctrl,
  1456. .locked_mods = 0,
  1457. .mods = ctrl,
  1458. .base_group = 0,
  1459. .latched_group = 0,
  1460. .locked_group = 1,
  1461. .group = 1,
  1462. .leds = group2,
  1463. }
  1464. }
  1465. },
  1466. {
  1467. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1468. .components = {
  1469. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  1470. .components = {
  1471. .base_mods = level5,
  1472. .latched_mods = ctrl,
  1473. .locked_mods = 0,
  1474. .mods = ctrl | level5,
  1475. .base_group = 0,
  1476. .latched_group = 0,
  1477. .locked_group = 1,
  1478. .group = 1,
  1479. .leds = group2,
  1480. }
  1481. }
  1482. },
  1483. );
  1484. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  1485. XKB_KEY_DOWN, events) == 0);
  1486. check_events_(
  1487. events,
  1488. {
  1489. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1490. .components = {
  1491. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1492. .components = {
  1493. .base_mods = level5,
  1494. .latched_mods = ctrl,
  1495. .locked_mods = 0,
  1496. .mods = ctrl | level5,
  1497. .base_group = 1,
  1498. .latched_group = 0,
  1499. .locked_group = 1,
  1500. .group = 2,
  1501. .leds = group2,
  1502. }
  1503. }
  1504. },
  1505. {
  1506. .type = XKB_EVENT_TYPE_KEY_DOWN,
  1507. .keycode = KEY_Q + EVDEV_OFFSET
  1508. },
  1509. {
  1510. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1511. .components = {
  1512. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1513. .components = {
  1514. .base_mods = level5,
  1515. .latched_mods = ctrl,
  1516. .locked_mods = 0,
  1517. .mods = ctrl | level5,
  1518. .base_group = 0,
  1519. .latched_group = 0,
  1520. .locked_group = 1,
  1521. .group = 1,
  1522. .leds = group2,
  1523. }
  1524. }
  1525. },
  1526. {
  1527. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1528. .components = {
  1529. .changed = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE,
  1530. .components = {
  1531. .base_mods = level5,
  1532. .latched_mods = 0,
  1533. .locked_mods = 0,
  1534. .mods = level5,
  1535. .base_group = 0,
  1536. .latched_group = 0,
  1537. .locked_group = 1,
  1538. .group = 1,
  1539. .leds = group2,
  1540. }
  1541. }
  1542. },
  1543. );
  1544. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  1545. XKB_KEY_UP, events) == 0);
  1546. check_events_(
  1547. events,
  1548. {
  1549. .type = XKB_EVENT_TYPE_KEY_UP,
  1550. .keycode = KEY_Q + EVDEV_OFFSET
  1551. }
  1552. );
  1553. assert(xkb_machine_process_key(sm, KEY_102ND + EVDEV_OFFSET,
  1554. XKB_KEY_UP, events) == 0);
  1555. check_events_(
  1556. events,
  1557. {
  1558. .type = XKB_EVENT_TYPE_KEY_UP,
  1559. .keycode = KEY_102ND + EVDEV_OFFSET
  1560. },
  1561. {
  1562. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1563. .components = {
  1564. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  1565. .components = {
  1566. .base_mods = 0,
  1567. .latched_mods = 0,
  1568. .locked_mods = 0,
  1569. .mods = 0,
  1570. .base_group = 0,
  1571. .latched_group = 0,
  1572. .locked_group = 1,
  1573. .group = 1,
  1574. .leds = group2,
  1575. }
  1576. }
  1577. },
  1578. );
  1579. /*
  1580. * xkb_machine_update_latched_locked
  1581. */
  1582. /* Layout 1 locked, Ctrl latched */
  1583. assert(xkb_machine_update_latched_locked(sm, events,
  1584. ctrl, ctrl, false, 0,
  1585. 0, 0, true, 1) == XKB_SUCCESS);
  1586. check_events_(
  1587. events,
  1588. {
  1589. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1590. .components = {
  1591. .changed = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE,
  1592. .components = {
  1593. .latched_mods = ctrl,
  1594. .locked_mods = 0,
  1595. .mods = ctrl,
  1596. .base_group = 0,
  1597. .latched_group = 0,
  1598. .locked_group = 1,
  1599. .group = 1,
  1600. .leds = group2,
  1601. }
  1602. }
  1603. }
  1604. );
  1605. /* Layout 1 locked, Ctrl locked */
  1606. assert(xkb_machine_update_latched_locked(sm, events,
  1607. ctrl, 0, false, 0,
  1608. ctrl, ctrl, false, 0) == XKB_SUCCESS);
  1609. check_events_(
  1610. events,
  1611. {
  1612. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1613. .components = {
  1614. .changed = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED,
  1615. .components = {
  1616. .latched_mods = 0,
  1617. .locked_mods = ctrl,
  1618. .mods = ctrl,
  1619. .base_group = 0,
  1620. .latched_group = 0,
  1621. .locked_group = 1,
  1622. .group = 1,
  1623. .leds = group2,
  1624. }
  1625. }
  1626. }
  1627. );
  1628. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  1629. XKB_KEY_DOWN, events) == 0);
  1630. check_events_(
  1631. events,
  1632. {
  1633. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1634. .components = {
  1635. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1636. .components = {
  1637. .base_mods = 0,
  1638. .latched_mods = 0,
  1639. .locked_mods = ctrl,
  1640. .mods = ctrl,
  1641. .base_group = 1,
  1642. .latched_group = 0,
  1643. .locked_group = 1,
  1644. .group = 2,
  1645. .leds = group2,
  1646. }
  1647. }
  1648. },
  1649. {
  1650. .type = XKB_EVENT_TYPE_KEY_DOWN,
  1651. .keycode = KEY_Q + EVDEV_OFFSET
  1652. },
  1653. {
  1654. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1655. .components = {
  1656. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1657. .components = {
  1658. .base_mods = 0,
  1659. .latched_mods = 0,
  1660. .locked_mods = ctrl,
  1661. .mods = ctrl,
  1662. .base_group = 0,
  1663. .latched_group = 0,
  1664. .locked_group = 1,
  1665. .group = 1,
  1666. .leds = group2,
  1667. }
  1668. }
  1669. },
  1670. );
  1671. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  1672. XKB_KEY_REPEATED, events) == 0);
  1673. check_events_(
  1674. events,
  1675. {
  1676. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1677. .components = {
  1678. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1679. .components = {
  1680. .base_mods = 0,
  1681. .latched_mods = 0,
  1682. .locked_mods = ctrl,
  1683. .mods = ctrl,
  1684. .base_group = 1,
  1685. .latched_group = 0,
  1686. .locked_group = 1,
  1687. .group = 2,
  1688. .leds = group2,
  1689. }
  1690. }
  1691. },
  1692. {
  1693. .type = XKB_EVENT_TYPE_KEY_REPEATED,
  1694. .keycode = KEY_Q + EVDEV_OFFSET
  1695. },
  1696. {
  1697. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1698. .components = {
  1699. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1700. .components = {
  1701. .base_mods = 0,
  1702. .latched_mods = 0,
  1703. .locked_mods = ctrl,
  1704. .mods = ctrl,
  1705. .base_group = 0,
  1706. .latched_group = 0,
  1707. .locked_group = 1,
  1708. .group = 1,
  1709. .leds = group2,
  1710. }
  1711. }
  1712. },
  1713. );
  1714. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  1715. XKB_KEY_UP, events) == 0);
  1716. check_events_(
  1717. events,
  1718. {
  1719. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1720. .components = {
  1721. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1722. .components = {
  1723. .base_mods = 0,
  1724. .latched_mods = 0,
  1725. .locked_mods = ctrl,
  1726. .mods = ctrl,
  1727. .base_group = 1,
  1728. .latched_group = 0,
  1729. .locked_group = 1,
  1730. .group = 2,
  1731. .leds = group2,
  1732. }
  1733. }
  1734. },
  1735. {
  1736. .type = XKB_EVENT_TYPE_KEY_UP,
  1737. .keycode = KEY_Q + EVDEV_OFFSET
  1738. },
  1739. {
  1740. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1741. .components = {
  1742. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE,
  1743. .components = {
  1744. .base_mods = 0,
  1745. .latched_mods = 0,
  1746. .locked_mods = ctrl,
  1747. .mods = ctrl,
  1748. .base_group = 0,
  1749. .latched_group = 0,
  1750. .locked_group = 1,
  1751. .group = 1,
  1752. .leds = group2,
  1753. }
  1754. }
  1755. },
  1756. );
  1757. /* Layout 1 latched, layout 2 locked, Ctrl locked */
  1758. assert(xkb_machine_update_latched_locked(sm, events,
  1759. 0, 0, true, 1,
  1760. 0, 0, true, 2) == XKB_SUCCESS);
  1761. check_events_(
  1762. events,
  1763. {
  1764. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1765. .components = {
  1766. .changed = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_LOCKED
  1767. | XKB_STATE_LAYOUT_EFFECTIVE,
  1768. .components = {
  1769. .latched_mods = 0,
  1770. .locked_mods = ctrl,
  1771. .mods = ctrl,
  1772. .base_group = 0,
  1773. .latched_group = 1,
  1774. .locked_group = 2,
  1775. .group = 3,
  1776. .leds = group2,
  1777. }
  1778. }
  1779. }
  1780. );
  1781. /* Layout 1 latched, layout 2 locked, Ctrl disabled */
  1782. assert(xkb_machine_update_latched_locked(sm, events,
  1783. 0, 0, false, 0,
  1784. ctrl, 0, false, 0) == XKB_SUCCESS);
  1785. check_events_(
  1786. events,
  1787. {
  1788. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1789. .components = {
  1790. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  1791. .components = {
  1792. .latched_mods = 0,
  1793. .locked_mods = 0,
  1794. .mods = 0,
  1795. .base_group = 0,
  1796. .latched_group = 1,
  1797. .locked_group = 2,
  1798. .group = 3,
  1799. .leds = group2,
  1800. }
  1801. }
  1802. }
  1803. );
  1804. /* Layout 1 latched, layout 2 locked, Ctrl latched */
  1805. assert(xkb_machine_update_latched_locked(sm, events,
  1806. ctrl, ctrl, false, 0,
  1807. 0, 0, false, 0) == XKB_SUCCESS);
  1808. check_events_(
  1809. events,
  1810. {
  1811. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1812. .components = {
  1813. .changed = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE,
  1814. .components = {
  1815. .latched_mods = ctrl,
  1816. .locked_mods = 0,
  1817. .mods = ctrl,
  1818. .base_group = 0,
  1819. .latched_group = 1,
  1820. .locked_group = 2,
  1821. .group = 3,
  1822. .leds = group2,
  1823. }
  1824. }
  1825. }
  1826. );
  1827. /*
  1828. * xkb_machine_update_enabled_controls
  1829. */
  1830. const enum xkb_keyboard_control_flags controls =
  1831. XKB_KEYBOARD_CONTROL_A11Y_STICKY_KEYS;
  1832. /* Disable already disabled sticky keys: no change */
  1833. assert(xkb_machine_update_enabled_controls(sm, events, controls, 0)
  1834. == XKB_SUCCESS);
  1835. check_events_(events, { .type = XKB_EVENT_TYPE_NONE });
  1836. /* Enable disabled sticky keys: no change */
  1837. assert(xkb_machine_update_enabled_controls(sm, events, controls, controls)
  1838. == XKB_SUCCESS);
  1839. check_events_(
  1840. events,
  1841. {
  1842. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1843. .components = {
  1844. .changed = XKB_STATE_CONTROLS,
  1845. .components = {
  1846. .latched_mods = ctrl,
  1847. .locked_mods = 0,
  1848. .mods = ctrl,
  1849. .base_group = 0,
  1850. .latched_group = 1,
  1851. .locked_group = 2,
  1852. .group = 3,
  1853. .leds = group2,
  1854. .controls = CONTROL_STICKY_KEYS,
  1855. }
  1856. }
  1857. }
  1858. );
  1859. /* Enable already enabled sticky keys: no change */
  1860. assert(xkb_machine_update_enabled_controls(sm, events, controls, controls)
  1861. == XKB_SUCCESS);
  1862. check_events_(events, { .type = XKB_EVENT_TYPE_NONE });
  1863. /* Disable sticky keys: clear latches & locks */
  1864. assert(xkb_machine_update_enabled_controls(sm, events, controls, 0)
  1865. == XKB_SUCCESS);
  1866. check_events_(
  1867. events,
  1868. {
  1869. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1870. .components = {
  1871. .changed = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
  1872. | XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_LOCKED
  1873. | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_CONTROLS
  1874. | XKB_STATE_LEDS,
  1875. .components = {
  1876. .latched_mods = 0,
  1877. .locked_mods = 0,
  1878. .mods = 0,
  1879. .base_group = 0,
  1880. .latched_group = 0,
  1881. .locked_group = 0,
  1882. .group = 0,
  1883. .leds = 0,
  1884. .controls = 0,
  1885. }
  1886. }
  1887. }
  1888. );
  1889. assert(xkb_machine_update_enabled_controls(sm, events, controls, 0)
  1890. == XKB_SUCCESS);
  1891. /*
  1892. * Check RedirectKey()
  1893. */
  1894. /* Layout 4 locked, Ctrl locked */
  1895. assert(xkb_machine_update_latched_locked(sm, events,
  1896. 0, 0, false, 0,
  1897. ctrl, ctrl, true, 3) == XKB_SUCCESS);
  1898. check_events_(
  1899. events,
  1900. {
  1901. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1902. .components = {
  1903. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
  1904. | XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE
  1905. | XKB_STATE_LEDS,
  1906. .components = {
  1907. .latched_mods = 0,
  1908. .locked_mods = ctrl,
  1909. .mods = ctrl,
  1910. .base_group = 0,
  1911. .latched_group = 0,
  1912. .locked_group = 3,
  1913. .group = 3,
  1914. .leds = group2,
  1915. }
  1916. }
  1917. }
  1918. );
  1919. assert(xkb_machine_process_key(sm, KEY_C + EVDEV_OFFSET,
  1920. XKB_KEY_DOWN, events) == 0);
  1921. check_events_(
  1922. events,
  1923. {
  1924. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1925. .components = {
  1926. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
  1927. | XKB_STATE_LEDS,
  1928. .components = {
  1929. .latched_mods = 0,
  1930. .locked_mods = ctrl,
  1931. .mods = ctrl,
  1932. .base_group = -3,
  1933. .latched_group = 0,
  1934. .locked_group = 3,
  1935. .group = 0,
  1936. .leds = 0,
  1937. }
  1938. }
  1939. },
  1940. {
  1941. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1942. .components = {
  1943. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  1944. .components = {
  1945. .latched_mods = 0,
  1946. .locked_mods = 0,
  1947. .mods = 0,
  1948. .base_group = -3,
  1949. .latched_group = 0,
  1950. .locked_group = 3,
  1951. .group = 0,
  1952. .leds = 0,
  1953. }
  1954. }
  1955. },
  1956. {
  1957. .type = XKB_EVENT_TYPE_KEY_DOWN,
  1958. .keycode = KEY_COPY + EVDEV_OFFSET
  1959. },
  1960. {
  1961. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1962. .components = {
  1963. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  1964. .components = {
  1965. .latched_mods = 0,
  1966. .locked_mods = ctrl,
  1967. .mods = ctrl,
  1968. .base_group = -3,
  1969. .latched_group = 0,
  1970. .locked_group = 3,
  1971. .group = 0,
  1972. .leds = 0,
  1973. }
  1974. }
  1975. },
  1976. {
  1977. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  1978. .components = {
  1979. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
  1980. | XKB_STATE_LEDS,
  1981. .components = {
  1982. .latched_mods = 0,
  1983. .locked_mods = ctrl,
  1984. .mods = ctrl,
  1985. .base_group = 0,
  1986. .latched_group = 0,
  1987. .locked_group = 3,
  1988. .group = 3,
  1989. .leds = group2,
  1990. }
  1991. }
  1992. },
  1993. );
  1994. xkb_machine_unref(sm);
  1995. /*
  1996. * Use modifiers tweak in addition to the shortcuts tweak
  1997. */
  1998. assert(xkb_machine_builder_remap_mods(builder, ctrl | alt, level3) ==
  1999. XKB_SUCCESS);
  2000. sm = xkb_machine_new(builder);
  2001. assert(sm);
  2002. assert(xkb_machine_update_latched_locked(sm, events,
  2003. 0, 0, false, 0,
  2004. ctrl, ctrl, true, 3) == XKB_SUCCESS);
  2005. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  2006. XKB_KEY_DOWN, events) == 0);
  2007. check_events_(
  2008. events,
  2009. {
  2010. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2011. .components = {
  2012. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
  2013. | XKB_STATE_LEDS,
  2014. .components = {
  2015. .latched_mods = 0,
  2016. .locked_mods = ctrl,
  2017. .mods = ctrl,
  2018. .base_group = -3,
  2019. .latched_group = 0,
  2020. .locked_group = 3,
  2021. .group = 0,
  2022. .leds = 0,
  2023. }
  2024. }
  2025. },
  2026. {
  2027. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2028. .keycode = KEY_Q + EVDEV_OFFSET
  2029. },
  2030. {
  2031. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2032. .components = {
  2033. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
  2034. | XKB_STATE_LEDS,
  2035. .components = {
  2036. .latched_mods = 0,
  2037. .locked_mods = ctrl,
  2038. .mods = ctrl,
  2039. .base_group = 0,
  2040. .latched_group = 0,
  2041. .locked_group = 3,
  2042. .group = 3,
  2043. .leds = group2,
  2044. }
  2045. }
  2046. },
  2047. );
  2048. assert(xkb_machine_process_key(sm, KEY_C + EVDEV_OFFSET,
  2049. XKB_KEY_DOWN, events) == 0);
  2050. check_events_(
  2051. events,
  2052. {
  2053. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2054. .components = {
  2055. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
  2056. | XKB_STATE_LEDS,
  2057. .components = {
  2058. .latched_mods = 0,
  2059. .locked_mods = ctrl,
  2060. .mods = ctrl,
  2061. .base_group = -3,
  2062. .latched_group = 0,
  2063. .locked_group = 3,
  2064. .group = 0,
  2065. .leds = 0,
  2066. }
  2067. }
  2068. },
  2069. {
  2070. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2071. .components = {
  2072. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  2073. .components = {
  2074. .latched_mods = 0,
  2075. .locked_mods = 0,
  2076. .mods = 0,
  2077. .base_group = -3,
  2078. .latched_group = 0,
  2079. .locked_group = 3,
  2080. .group = 0,
  2081. .leds = 0,
  2082. }
  2083. }
  2084. },
  2085. {
  2086. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2087. .keycode = KEY_COPY + EVDEV_OFFSET
  2088. },
  2089. {
  2090. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2091. .components = {
  2092. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  2093. .components = {
  2094. .latched_mods = 0,
  2095. .locked_mods = ctrl,
  2096. .mods = ctrl,
  2097. .base_group = -3,
  2098. .latched_group = 0,
  2099. .locked_group = 3,
  2100. .group = 0,
  2101. .leds = 0,
  2102. }
  2103. }
  2104. },
  2105. {
  2106. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2107. .components = {
  2108. .changed = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
  2109. | XKB_STATE_LEDS,
  2110. .components = {
  2111. .latched_mods = 0,
  2112. .locked_mods = ctrl,
  2113. .mods = ctrl,
  2114. .base_group = 0,
  2115. .latched_group = 0,
  2116. .locked_group = 3,
  2117. .group = 3,
  2118. .leds = group2,
  2119. }
  2120. }
  2121. },
  2122. );
  2123. assert(xkb_machine_update_latched_locked(sm, events,
  2124. 0, 0, false, 0,
  2125. alt, alt, false, 0) == XKB_SUCCESS);
  2126. check_events_(
  2127. events,
  2128. {
  2129. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2130. .components = {
  2131. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  2132. .components = {
  2133. .latched_mods = 0,
  2134. .locked_mods = ctrl | alt,
  2135. .mods = ctrl | alt,
  2136. .base_group = 0,
  2137. .latched_group = 0,
  2138. .locked_group = 3,
  2139. .group = 3,
  2140. .leds = group2,
  2141. }
  2142. }
  2143. }
  2144. );
  2145. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  2146. XKB_KEY_DOWN, events) == 0);
  2147. check_events_(
  2148. events,
  2149. {
  2150. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2151. .components = {
  2152. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2153. | XKB_STATE_MODS_EFFECTIVE,
  2154. .components = {
  2155. .base_mods = level3,
  2156. .latched_mods = 0,
  2157. .locked_mods = 0,
  2158. .mods = level3,
  2159. .base_group = 0,
  2160. .latched_group = 0,
  2161. .locked_group = 3,
  2162. .group = 3,
  2163. .leds = group2,
  2164. }
  2165. }
  2166. },
  2167. {
  2168. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2169. .keycode = KEY_Q + EVDEV_OFFSET
  2170. },
  2171. {
  2172. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2173. .components = {
  2174. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2175. | XKB_STATE_MODS_EFFECTIVE,
  2176. .components = {
  2177. .base_mods = 0,
  2178. .latched_mods = 0,
  2179. .locked_mods = ctrl | alt,
  2180. .mods = ctrl | alt,
  2181. .base_group = 0,
  2182. .latched_group = 0,
  2183. .locked_group = 3,
  2184. .group = 3,
  2185. .leds = group2,
  2186. }
  2187. }
  2188. },
  2189. );
  2190. assert(xkb_machine_update_latched_locked(sm, events,
  2191. 0, 0, false, 0,
  2192. 0, 0, true, 0) == XKB_SUCCESS);
  2193. assert(xkb_machine_process_key(sm, KEY_Q + EVDEV_OFFSET,
  2194. XKB_KEY_DOWN, events) == 0);
  2195. check_events_(
  2196. events,
  2197. {
  2198. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2199. .components = {
  2200. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2201. | XKB_STATE_MODS_EFFECTIVE,
  2202. .components = {
  2203. .base_mods = level3,
  2204. .latched_mods = 0,
  2205. .locked_mods = 0,
  2206. .mods = level3,
  2207. .base_group = 0,
  2208. .latched_group = 0,
  2209. .locked_group = 0,
  2210. .group = 0,
  2211. .leds = 0,
  2212. }
  2213. }
  2214. },
  2215. {
  2216. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2217. .keycode = KEY_Q + EVDEV_OFFSET
  2218. },
  2219. {
  2220. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2221. .components = {
  2222. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2223. | XKB_STATE_MODS_EFFECTIVE,
  2224. .components = {
  2225. .base_mods = 0,
  2226. .latched_mods = 0,
  2227. .locked_mods = ctrl | alt,
  2228. .mods = ctrl | alt,
  2229. .base_group = 0,
  2230. .latched_group = 0,
  2231. .locked_group = 0,
  2232. .group = 0,
  2233. .leds = 0,
  2234. }
  2235. }
  2236. },
  2237. );
  2238. assert(xkb_machine_process_key(sm, KEY_C + EVDEV_OFFSET,
  2239. XKB_KEY_DOWN, events) == 0);
  2240. check_events_(
  2241. events,
  2242. {
  2243. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2244. .components = {
  2245. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  2246. .components = {
  2247. .latched_mods = 0,
  2248. .locked_mods = alt,
  2249. .mods = alt,
  2250. .base_group = 0,
  2251. .latched_group = 0,
  2252. .locked_group = 0,
  2253. .group = 0,
  2254. .leds = 0,
  2255. }
  2256. }
  2257. },
  2258. {
  2259. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2260. .keycode = KEY_COPY + EVDEV_OFFSET
  2261. },
  2262. {
  2263. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2264. .components = {
  2265. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  2266. .components = {
  2267. .latched_mods = 0,
  2268. .locked_mods = ctrl | alt,
  2269. .mods = ctrl | alt,
  2270. .base_group = 0,
  2271. .latched_group = 0,
  2272. .locked_group = 0,
  2273. .group = 0,
  2274. .leds = 0,
  2275. }
  2276. }
  2277. },
  2278. );
  2279. xkb_machine_unref(sm);
  2280. xkb_events_destroy(events);
  2281. xkb_machine_builder_destroy(builder);
  2282. xkb_keymap_unref(keymap);
  2283. }
  2284. static void
  2285. test_overlays(struct xkb_context *context)
  2286. {
  2287. /* Check controls → overlay mask conversion */
  2288. static const struct {
  2289. enum xkb_action_controls controls;
  2290. xkb_overlay_mask_t overlays;
  2291. } controls_tests[] = {
  2292. { 0, 0x0 },
  2293. { CONTROL_BELL, 0x0 },
  2294. { CONTROL_OVERLAY1, 0x1 },
  2295. { CONTROL_OVERLAY1 | CONTROL_OVERLAY2, 0x3 },
  2296. { CONTROL_OVERLAY3, (1u << 2) },
  2297. { CONTROL_OVERLAY8, (1u << 7) },
  2298. { CONTROL_ALL, 0xff },
  2299. { CONTROL_ALL_V1, 0x3 },
  2300. { CONTROL_ALL_BOOLEAN, 0xff },
  2301. { CONTROL_ALL_BOOLEAN_V1, 0x3 },
  2302. };
  2303. for (size_t t = 0; t < ARRAY_SIZE(controls_tests); t++) {
  2304. fprintf(stderr, "------\n*** %s: controls #%zu ***\n", __func__, t);
  2305. assert_eq("", controls_tests[t].overlays,
  2306. (uint8_t)OVERLAYS_FROM_CONTROLS(controls_tests[t].controls),
  2307. "0x%02x");
  2308. }
  2309. /* Check overlapping overlays */
  2310. struct xkb_keymap * const keymap = test_compile_file(
  2311. context, XKB_KEYMAP_FORMAT_TEXT_V2,
  2312. GOLDEN_TESTS_OUTPUTS "overlays-v2-2.xkb");
  2313. assert(keymap);
  2314. struct xkb_machine_builder *builder =
  2315. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  2316. assert(builder);
  2317. struct xkb_machine * const sm = xkb_machine_new(builder);
  2318. assert(sm);
  2319. xkb_machine_builder_destroy(builder);
  2320. struct xkb_events * events = xkb_events_new_batch(context,
  2321. XKB_EVENTS_NO_FLAGS);
  2322. assert(events);
  2323. static const struct {
  2324. enum xkb_keyboard_control_flags controls;
  2325. xkb_keycode_t kc;
  2326. enum xkb_key_direction direction;
  2327. } keycode_tests[] = {
  2328. /* No overlay */
  2329. { 0, KEY_J, XKB_KEY_DOWN },
  2330. { 0, KEY_J, XKB_KEY_UP },
  2331. { 0, KEY_J, XKB_KEY_DOWN },
  2332. /* Overlay enabled while key pressed: no effect */
  2333. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_J, XKB_KEY_UP },
  2334. /* Overlay enabled before and after key press: effectual */
  2335. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_KP1, XKB_KEY_DOWN },
  2336. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_KP1, XKB_KEY_UP },
  2337. /* Overlay enabled before key press and disable before release : effectual */
  2338. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_KP1, XKB_KEY_DOWN },
  2339. { 0, KEY_KP1, XKB_KEY_UP },
  2340. /* Key does not belong to overlay: not effect */
  2341. { XKB_KEYBOARD_CONTROL_OVERLAY8, KEY_J, XKB_KEY_DOWN },
  2342. { XKB_KEYBOARD_CONTROL_OVERLAY8, KEY_J, XKB_KEY_UP },
  2343. /* Overlay activation order matters */
  2344. { XKB_KEYBOARD_CONTROL_OVERLAY1, 0, 0 },
  2345. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_LEFT, XKB_KEY_DOWN },
  2346. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_LEFT, XKB_KEY_UP },
  2347. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_LEFT, XKB_KEY_DOWN },
  2348. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_LEFT, XKB_KEY_UP },
  2349. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_LEFT, XKB_KEY_DOWN },
  2350. { XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_LEFT, XKB_KEY_UP },
  2351. /* If multiple overlays are activated simultaneously, they are stacked
  2352. * in ascending order */
  2353. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2,
  2354. KEY_KP1, XKB_KEY_DOWN },
  2355. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2,
  2356. KEY_KP1, XKB_KEY_UP },
  2357. { XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_LEFT, XKB_KEY_DOWN },
  2358. { XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_LEFT, XKB_KEY_UP },
  2359. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2 |
  2360. XKB_KEYBOARD_CONTROL_OVERLAY3 | XKB_KEYBOARD_CONTROL_OVERLAY4 |
  2361. XKB_KEYBOARD_CONTROL_OVERLAY8,
  2362. KEY_F10, XKB_KEY_DOWN },
  2363. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2 |
  2364. XKB_KEYBOARD_CONTROL_OVERLAY3 | XKB_KEYBOARD_CONTROL_OVERLAY4 |
  2365. XKB_KEYBOARD_CONTROL_OVERLAY8,
  2366. KEY_F10, XKB_KEY_UP },
  2367. { XKB_KEYBOARD_CONTROL_OVERLAY2 | XKB_KEYBOARD_CONTROL_OVERLAY3 |
  2368. XKB_KEYBOARD_CONTROL_OVERLAY4 | XKB_KEYBOARD_CONTROL_OVERLAY8,
  2369. KEY_F10, XKB_KEY_DOWN },
  2370. { XKB_KEYBOARD_CONTROL_OVERLAY2 | XKB_KEYBOARD_CONTROL_OVERLAY3 |
  2371. XKB_KEYBOARD_CONTROL_OVERLAY4 | XKB_KEYBOARD_CONTROL_OVERLAY8,
  2372. KEY_F10, XKB_KEY_UP },
  2373. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2 |
  2374. XKB_KEYBOARD_CONTROL_OVERLAY3 | XKB_KEYBOARD_CONTROL_OVERLAY8,
  2375. KEY_KP1, XKB_KEY_DOWN },
  2376. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2 |
  2377. XKB_KEYBOARD_CONTROL_OVERLAY3 | XKB_KEYBOARD_CONTROL_OVERLAY8,
  2378. KEY_KP1, XKB_KEY_UP },
  2379. { XKB_KEYBOARD_CONTROL_OVERLAY2 | XKB_KEYBOARD_CONTROL_OVERLAY3,
  2380. KEY_F1, XKB_KEY_DOWN },
  2381. { XKB_KEYBOARD_CONTROL_OVERLAY2 | XKB_KEYBOARD_CONTROL_OVERLAY3,
  2382. KEY_F1, XKB_KEY_UP },
  2383. { XKB_KEYBOARD_CONTROL_OVERLAY2 | XKB_KEYBOARD_CONTROL_OVERLAY3 |
  2384. XKB_KEYBOARD_CONTROL_OVERLAY4, 0, 0},
  2385. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2 |
  2386. XKB_KEYBOARD_CONTROL_OVERLAY3 | XKB_KEYBOARD_CONTROL_OVERLAY4,
  2387. KEY_KP1, XKB_KEY_DOWN },
  2388. { XKB_KEYBOARD_CONTROL_OVERLAY1 | XKB_KEYBOARD_CONTROL_OVERLAY2 |
  2389. XKB_KEYBOARD_CONTROL_OVERLAY3 | XKB_KEYBOARD_CONTROL_OVERLAY4,
  2390. KEY_KP1, XKB_KEY_UP },
  2391. /* Multiple physical keys with same keycode */
  2392. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_KP1, XKB_KEY_DOWN },
  2393. { 0, KEY_KP1, XKB_KEY_DOWN }, /* key still uses overlay 1 */
  2394. { 0, KEY_KP1, XKB_KEY_UP }, /* key still uses overlay 1 */
  2395. { 0, KEY_KP1, XKB_KEY_UP }, /* key still uses overlay 1 */
  2396. { 0, KEY_J, XKB_KEY_DOWN },
  2397. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_J, XKB_KEY_DOWN }, /* No effect: key already down */
  2398. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_J, XKB_KEY_UP }, /* No effect: all keys must be depressed */
  2399. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_J, XKB_KEY_UP }, /* No effect: all keys must be depressed */
  2400. { XKB_KEYBOARD_CONTROL_OVERLAY1, KEY_KP1, XKB_KEY_DOWN },
  2401. { XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_KP1, XKB_KEY_DOWN }, /* key still uses overlay 1 */
  2402. { XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_KP1, XKB_KEY_UP }, /* key still uses overlay 1 */
  2403. { XKB_KEYBOARD_CONTROL_OVERLAY2, KEY_KP1, XKB_KEY_UP }, /* key still uses overlay 1 */
  2404. };
  2405. for (size_t t = 0; t < ARRAY_SIZE(keycode_tests); t++) {
  2406. fprintf(stderr, "------\n*** %s: keycodes #%zu ***\n", __func__, t);
  2407. assert(xkb_machine_update_enabled_controls(
  2408. sm, events, 0xffff, keycode_tests[t].controls
  2409. ) == XKB_SUCCESS);
  2410. if (!keycode_tests[t].kc)
  2411. continue;
  2412. assert(xkb_machine_process_key(
  2413. sm, EVDEV_OFFSET + KEY_J, keycode_tests[t].direction, events
  2414. ) == XKB_SUCCESS);
  2415. const struct xkb_event *event;
  2416. while ((event = xkb_events_next(events))) {
  2417. switch (xkb_event_get_type(event)) {
  2418. case XKB_EVENT_TYPE_KEY_DOWN:
  2419. case XKB_EVENT_TYPE_KEY_UP:
  2420. assert_eq("keycode", EVDEV_OFFSET + keycode_tests[t].kc,
  2421. xkb_event_get_keycode(event), "%"PRIu32);
  2422. break;
  2423. default:
  2424. ;
  2425. }
  2426. }
  2427. }
  2428. xkb_events_destroy(events);
  2429. xkb_machine_unref(sm);
  2430. xkb_keymap_unref(keymap);
  2431. }
  2432. static void
  2433. test_modifiers_tweak(struct xkb_context *context)
  2434. {
  2435. struct xkb_keymap * const keymap =
  2436. test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V2,
  2437. "evdev", "pc104", "us,de", ",T3",
  2438. "grp:menu_toggle,grp:alt_caps_toggle,"
  2439. "terminate:ctrl_alt_bksp,ctrl:copy");
  2440. assert(keymap);
  2441. const xkb_mod_mask_t shift = _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_SHIFT);
  2442. const xkb_mod_mask_t ctrl = _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_CTRL);
  2443. const xkb_mod_mask_t alt = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_ALT);
  2444. const xkb_mod_mask_t super = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_SUPER);
  2445. const xkb_mod_mask_t scroll = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_SCROLL);
  2446. const xkb_mod_mask_t level3 = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_LEVEL3);
  2447. const xkb_mod_mask_t level5 = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_LEVEL5);
  2448. const xkb_mod_mask_t num = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_NUM);
  2449. struct xkb_machine_builder *builder =
  2450. xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
  2451. assert(builder);
  2452. assert(xkb_machine_builder_remap_mods(builder, 0, 0) == XKB_SUCCESS);
  2453. assert(xkb_machine_builder_remap_mods(builder, 0, level3) ==
  2454. XKB_ERROR_UNSUPPORTED_MODIFIER_MASK);
  2455. assert(xkb_machine_builder_remap_mods(builder, scroll, alt) == XKB_SUCCESS);
  2456. assert(xkb_machine_builder_remap_mods(builder, super, level3) == XKB_SUCCESS);
  2457. assert(xkb_machine_builder_remap_mods(builder, alt, level5) == XKB_SUCCESS);
  2458. assert(xkb_machine_builder_remap_mods(builder, ctrl | alt, level3) == XKB_SUCCESS);
  2459. assert(xkb_machine_builder_remap_mods(builder, ctrl, shift) == XKB_SUCCESS);
  2460. assert(xkb_machine_builder_remap_mods(builder, ctrl, 0) == XKB_SUCCESS);
  2461. struct xkb_machine * const sm = xkb_machine_new(builder);
  2462. assert(sm);
  2463. xkb_machine_builder_destroy(builder);
  2464. struct xkb_events * const events = xkb_events_new_batch(context,
  2465. XKB_EVENTS_NO_FLAGS);
  2466. assert(events);
  2467. #define U(cp) (XKB_KEYSYM_UNICODE_OFFSET + (cp))
  2468. assert(test_key_seq2(
  2469. keymap, sm, events,
  2470. /* Layout: US */
  2471. KEY_Y , BOTH, XKB_KEY_y , NEXT,
  2472. KEY_C , BOTH, XKB_KEY_c , NEXT,
  2473. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  2474. KEY_Y , BOTH, XKB_KEY_y , NEXT,
  2475. KEY_C , BOTH, XKB_KEY_XF86Copy , NEXT,
  2476. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  2477. KEY_LEFTMETA, DOWN, XKB_KEY_Super_L , NEXT,
  2478. KEY_Y , BOTH, XKB_KEY_y , NEXT,
  2479. KEY_C , BOTH, XKB_KEY_c , NEXT,
  2480. KEY_LEFTMETA, UP , XKB_KEY_Super_L , NEXT,
  2481. KEY_LEFTALT , DOWN, XKB_KEY_Alt_L , NEXT,
  2482. KEY_Y , BOTH, XKB_KEY_y , NEXT,
  2483. KEY_LEFTMETA, DOWN, XKB_KEY_Super_L , NEXT,
  2484. KEY_Y , BOTH, XKB_KEY_y , NEXT,
  2485. KEY_LEFTMETA, UP , XKB_KEY_Super_L , NEXT,
  2486. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  2487. KEY_Y , BOTH, XKB_KEY_y , NEXT,
  2488. KEY_C , BOTH, XKB_KEY_XF86Copy , NEXT,
  2489. KEY_BACKSPACE,BOTH, XKB_KEY_Terminate_Server, NEXT, /* No remap */
  2490. KEY_LEFTALT , UP , XKB_KEY_Alt_L , NEXT,
  2491. KEY_Y , BOTH, XKB_KEY_y , NEXT,
  2492. KEY_C , BOTH, XKB_KEY_XF86Copy , NEXT,
  2493. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  2494. KEY_COMPOSE , BOTH, XKB_KEY_ISO_Next_Group, NEXT,
  2495. /* Layout: T3 */
  2496. KEY_Y , BOTH, XKB_KEY_z , NEXT,
  2497. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  2498. KEY_Y , BOTH, XKB_KEY_z , NEXT,
  2499. KEY_Y , DOWN, XKB_KEY_z , NEXT,
  2500. KEY_Y , REPEAT, XKB_KEY_z , NEXT,
  2501. KEY_Y , UP, XKB_KEY_z , NEXT,
  2502. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT,
  2503. KEY_LEFTMETA, DOWN, XKB_KEY_Super_L , NEXT,
  2504. KEY_Y , BOTH, XKB_KEY_dead_doubleacute, NEXT,
  2505. KEY_Y , DOWN, XKB_KEY_dead_doubleacute, NEXT,
  2506. KEY_Y , REPEAT, XKB_KEY_dead_doubleacute, NEXT,
  2507. KEY_Y , UP, XKB_KEY_dead_doubleacute, NEXT,
  2508. KEY_LEFTMETA, UP , XKB_KEY_Super_L , NEXT,
  2509. KEY_LEFTALT , DOWN, XKB_KEY_Alt_L , NEXT,
  2510. KEY_Y , BOTH, U(0x027C) , NEXT,
  2511. KEY_LEFTMETA, DOWN, XKB_KEY_Super_L , NEXT,
  2512. KEY_Y , BOTH, XKB_KEY_dead_invertedbreve, NEXT,
  2513. KEY_LEFTMETA, UP , XKB_KEY_Super_L , NEXT,
  2514. KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT,
  2515. KEY_Y , BOTH, XKB_KEY_dead_doubleacute, NEXT,
  2516. KEY_BACKSPACE,BOTH, XKB_KEY_Terminate_Server, NEXT, /* No remap */
  2517. KEY_LEFTALT , UP , XKB_KEY_Alt_L , NEXT,
  2518. KEY_Y , BOTH, XKB_KEY_z , NEXT,
  2519. KEY_LEFTCTRL, UP , XKB_KEY_Control_L , FINISH
  2520. ));
  2521. #undef U
  2522. const xkb_led_mask_t num_led =
  2523. UINT32_C(1) << xkb_keymap_led_get_index(keymap, XKB_LED_NAME_NUM);
  2524. const xkb_led_mask_t scroll_led =
  2525. UINT32_C(1) << xkb_keymap_led_get_index(keymap, XKB_LED_NAME_SCROLL);
  2526. const xkb_led_mask_t group2_led =
  2527. UINT32_C(1) << xkb_keymap_led_get_index(keymap, "Group 2");
  2528. assert(xkb_machine_process_key(sm, KEY_LEFTALT + EVDEV_OFFSET,
  2529. XKB_KEY_DOWN, events) == 0);
  2530. check_events_(
  2531. events,
  2532. {
  2533. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2534. .keycode = KEY_LEFTALT + EVDEV_OFFSET
  2535. },
  2536. {
  2537. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2538. .components = {
  2539. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  2540. .components = {
  2541. .base_mods = alt,
  2542. .mods = alt,
  2543. .locked_group = 1,
  2544. .group = 1,
  2545. .leds = group2_led,
  2546. }
  2547. }
  2548. }
  2549. );
  2550. assert(xkb_machine_process_key(sm, KEY_Y + EVDEV_OFFSET,
  2551. XKB_KEY_DOWN, events) == 0);
  2552. check_events_(
  2553. events,
  2554. {
  2555. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2556. .components = {
  2557. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  2558. .components = {
  2559. .base_mods = level5,
  2560. .mods = level5,
  2561. .locked_group = 1,
  2562. .group = 1,
  2563. .leds = group2_led,
  2564. }
  2565. }
  2566. },
  2567. {
  2568. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2569. .keycode = KEY_Y + EVDEV_OFFSET
  2570. },
  2571. {
  2572. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2573. .components = {
  2574. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  2575. .components = {
  2576. .base_mods = alt,
  2577. .mods = alt,
  2578. .locked_group = 1,
  2579. .group = 1,
  2580. .leds = group2_led,
  2581. }
  2582. }
  2583. },
  2584. );
  2585. assert(xkb_machine_process_key(sm, KEY_Y + EVDEV_OFFSET,
  2586. XKB_KEY_REPEATED, events) == 0);
  2587. check_events_(
  2588. events,
  2589. {
  2590. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2591. .components = {
  2592. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  2593. .components = {
  2594. .base_mods = level5,
  2595. .mods = level5,
  2596. .locked_group = 1,
  2597. .group = 1,
  2598. .leds = group2_led,
  2599. }
  2600. }
  2601. },
  2602. {
  2603. .type = XKB_EVENT_TYPE_KEY_REPEATED,
  2604. .keycode = KEY_Y + EVDEV_OFFSET
  2605. },
  2606. {
  2607. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2608. .components = {
  2609. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  2610. .components = {
  2611. .base_mods = alt,
  2612. .mods = alt,
  2613. .locked_group = 1,
  2614. .group = 1,
  2615. .leds = group2_led,
  2616. }
  2617. }
  2618. },
  2619. );
  2620. assert(xkb_machine_process_key(sm, KEY_Y + EVDEV_OFFSET,
  2621. XKB_KEY_UP, events) == 0);
  2622. check_events_(
  2623. events,
  2624. {
  2625. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2626. .components = {
  2627. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  2628. .components = {
  2629. .base_mods = level5,
  2630. .mods = level5,
  2631. .locked_group = 1,
  2632. .group = 1,
  2633. .leds = group2_led,
  2634. }
  2635. }
  2636. },
  2637. {
  2638. .type = XKB_EVENT_TYPE_KEY_UP,
  2639. .keycode = KEY_Y + EVDEV_OFFSET
  2640. },
  2641. {
  2642. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2643. .components = {
  2644. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  2645. .components = {
  2646. .base_mods = alt,
  2647. .mods = alt,
  2648. .locked_group = 1,
  2649. .group = 1,
  2650. .leds = group2_led,
  2651. }
  2652. }
  2653. },
  2654. );
  2655. assert(xkb_machine_update_latched_locked(sm, events,
  2656. 0, 0, false, 0,
  2657. ctrl | num, ctrl | num,
  2658. false, 0) == XKB_SUCCESS);
  2659. check_events_(
  2660. events,
  2661. {
  2662. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2663. .components = {
  2664. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
  2665. | XKB_STATE_LEDS,
  2666. .components = {
  2667. .base_mods = alt,
  2668. .locked_mods = ctrl | num,
  2669. .mods = ctrl | alt | num,
  2670. .locked_group = 1,
  2671. .group = 1,
  2672. .leds = group2_led | num_led,
  2673. }
  2674. }
  2675. }
  2676. );
  2677. assert(xkb_machine_process_key(sm, KEY_Y + EVDEV_OFFSET,
  2678. XKB_KEY_DOWN, events) == 0);
  2679. check_events_(
  2680. events,
  2681. {
  2682. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2683. .components = {
  2684. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2685. | XKB_STATE_MODS_EFFECTIVE,
  2686. .components = {
  2687. .base_mods = level3,
  2688. .locked_mods = num,
  2689. .mods = level3 | num,
  2690. .locked_group = 1,
  2691. .group = 1,
  2692. .leds = group2_led | num_led,
  2693. }
  2694. }
  2695. },
  2696. {
  2697. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2698. .keycode = KEY_Y + EVDEV_OFFSET
  2699. },
  2700. {
  2701. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2702. .components = {
  2703. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2704. | XKB_STATE_MODS_EFFECTIVE,
  2705. .components = {
  2706. .base_mods = alt,
  2707. .locked_mods = ctrl | num,
  2708. .mods = ctrl | alt | num,
  2709. .locked_group = 1,
  2710. .group = 1,
  2711. .leds = group2_led | num_led,
  2712. }
  2713. }
  2714. },
  2715. );
  2716. assert(xkb_machine_process_key(sm, KEY_Y + EVDEV_OFFSET,
  2717. XKB_KEY_UP, events) == 0);
  2718. check_events_(
  2719. events,
  2720. {
  2721. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2722. .components = {
  2723. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2724. | XKB_STATE_MODS_EFFECTIVE,
  2725. .components = {
  2726. .base_mods = level3,
  2727. .locked_mods = num,
  2728. .mods = level3 | num,
  2729. .locked_group = 1,
  2730. .group = 1,
  2731. .leds = group2_led | num_led,
  2732. }
  2733. }
  2734. },
  2735. {
  2736. .type = XKB_EVENT_TYPE_KEY_UP,
  2737. .keycode = KEY_Y + EVDEV_OFFSET
  2738. },
  2739. {
  2740. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2741. .components = {
  2742. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2743. | XKB_STATE_MODS_EFFECTIVE,
  2744. .components = {
  2745. .base_mods = alt,
  2746. .locked_mods = ctrl | num,
  2747. .mods = ctrl | alt | num,
  2748. .locked_group = 1,
  2749. .group = 1,
  2750. .leds = group2_led | num_led,
  2751. }
  2752. }
  2753. },
  2754. );
  2755. /* Key type `CTRL+ALT` partially matches the remapping source: no remap */
  2756. assert(xkb_machine_process_key(sm, KEY_BACKSPACE + EVDEV_OFFSET,
  2757. XKB_KEY_DOWN, events) == 0);
  2758. check_events_(
  2759. events,
  2760. {
  2761. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2762. .keycode = KEY_BACKSPACE + EVDEV_OFFSET
  2763. }
  2764. );
  2765. assert(xkb_machine_process_key(sm, KEY_LEFTALT + EVDEV_OFFSET,
  2766. XKB_KEY_UP, events) == 0);
  2767. check_events_(
  2768. events,
  2769. {
  2770. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2771. .components = {
  2772. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2773. | XKB_STATE_MODS_EFFECTIVE,
  2774. .components = {
  2775. .base_mods = level3,
  2776. .locked_mods = num,
  2777. .mods = level3 | num,
  2778. .locked_group = 1,
  2779. .group = 1,
  2780. .leds = group2_led | num_led,
  2781. }
  2782. }
  2783. },
  2784. {
  2785. .type = XKB_EVENT_TYPE_KEY_UP,
  2786. .keycode = KEY_LEFTALT + EVDEV_OFFSET
  2787. },
  2788. {
  2789. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2790. .components = {
  2791. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2792. | XKB_STATE_MODS_EFFECTIVE,
  2793. .components = {
  2794. .base_mods = alt,
  2795. .locked_mods = ctrl | num,
  2796. .mods = ctrl | alt | num,
  2797. .locked_group = 1,
  2798. .group = 1,
  2799. .leds = group2_led | num_led,
  2800. }
  2801. }
  2802. },
  2803. {
  2804. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2805. .components = {
  2806. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
  2807. .components = {
  2808. .base_mods = 0,
  2809. .locked_mods = ctrl | num,
  2810. .mods = ctrl | num,
  2811. .locked_group = 1,
  2812. .group = 1,
  2813. .leds = group2_led | num_led,
  2814. }
  2815. }
  2816. }
  2817. );
  2818. assert(xkb_machine_update_latched_locked(sm, events,
  2819. 0, 0, false, 0,
  2820. ctrl | scroll, scroll,
  2821. false, 0) == XKB_SUCCESS);
  2822. check_events_(
  2823. events,
  2824. {
  2825. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2826. .components = {
  2827. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
  2828. | XKB_STATE_LEDS,
  2829. .components = {
  2830. .base_mods = 0,
  2831. .locked_mods = num | scroll,
  2832. .mods = num | scroll,
  2833. .locked_group = 1,
  2834. .group = 1,
  2835. .leds = group2_led | num_led | scroll_led,
  2836. }
  2837. }
  2838. }
  2839. );
  2840. /* Ensure CAPS action is triggered */
  2841. assert(xkb_machine_process_key(sm, KEY_CAPSLOCK + EVDEV_OFFSET,
  2842. XKB_KEY_DOWN, events) == 0);
  2843. check_events_(
  2844. events,
  2845. {
  2846. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2847. .components = {
  2848. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2849. | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS,
  2850. .components = {
  2851. .base_mods = alt,
  2852. .locked_mods = num,
  2853. .mods = alt | num,
  2854. .locked_group = 1,
  2855. .group = 1,
  2856. .leds = group2_led | num_led,
  2857. }
  2858. }
  2859. },
  2860. {
  2861. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2862. .keycode = KEY_CAPSLOCK + EVDEV_OFFSET
  2863. },
  2864. {
  2865. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2866. .components = {
  2867. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2868. | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS,
  2869. .components = {
  2870. .base_mods = 0,
  2871. .locked_mods = num | scroll,
  2872. .mods = num | scroll,
  2873. .locked_group = 1,
  2874. .group = 1,
  2875. .leds = group2_led | num_led | scroll_led,
  2876. }
  2877. }
  2878. },
  2879. {
  2880. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2881. .components = {
  2882. .changed = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE
  2883. | XKB_STATE_LEDS,
  2884. .components = {
  2885. .base_mods = 0,
  2886. .locked_mods = num | scroll,
  2887. .mods = num | scroll,
  2888. .locked_group = 0,
  2889. .group = 0,
  2890. .leds = num_led | scroll_led,
  2891. }
  2892. }
  2893. },
  2894. );
  2895. assert(xkb_machine_update_latched_locked(sm, events,
  2896. 0, 0, false, 0,
  2897. ctrl | alt | scroll, ctrl | alt,
  2898. false, 0) == XKB_SUCCESS);
  2899. /* Key redirect */
  2900. assert(xkb_machine_process_key(sm, KEY_C + EVDEV_OFFSET, XKB_KEY_DOWN,
  2901. events) == 0);
  2902. check_events_(
  2903. events,
  2904. {
  2905. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2906. .components = {
  2907. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2908. | XKB_STATE_MODS_EFFECTIVE,
  2909. .components = {
  2910. .base_mods = level5,
  2911. .locked_mods = ctrl | num,
  2912. .mods = ctrl | level5 | num,
  2913. .locked_group = 0,
  2914. .group = 0,
  2915. .leds = num_led,
  2916. }
  2917. }
  2918. },
  2919. {
  2920. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2921. .components = {
  2922. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  2923. .components = {
  2924. .base_mods = level5,
  2925. .locked_mods = num,
  2926. .mods = level5 | num,
  2927. .locked_group = 0,
  2928. .group = 0,
  2929. .leds = num_led,
  2930. }
  2931. }
  2932. },
  2933. {
  2934. .type = XKB_EVENT_TYPE_KEY_DOWN,
  2935. .keycode = KEY_COPY + EVDEV_OFFSET
  2936. },
  2937. {
  2938. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2939. .components = {
  2940. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  2941. .components = {
  2942. .base_mods = level5,
  2943. .locked_mods = ctrl | num,
  2944. .mods = ctrl | level5 | num,
  2945. .locked_group = 0,
  2946. .group = 0,
  2947. .leds = num_led,
  2948. }
  2949. }
  2950. },
  2951. {
  2952. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2953. .components = {
  2954. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2955. | XKB_STATE_MODS_EFFECTIVE,
  2956. .components = {
  2957. .base_mods = 0,
  2958. .locked_mods = ctrl | alt | num,
  2959. .mods = ctrl | alt | num,
  2960. .locked_group = 0,
  2961. .group = 0,
  2962. .leds = num_led,
  2963. }
  2964. }
  2965. },
  2966. );
  2967. assert(xkb_machine_process_key(sm, KEY_C + EVDEV_OFFSET,
  2968. XKB_KEY_REPEATED, events) == 0);
  2969. check_events_(
  2970. events,
  2971. {
  2972. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2973. .components = {
  2974. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  2975. | XKB_STATE_MODS_EFFECTIVE,
  2976. .components = {
  2977. .base_mods = level5,
  2978. .locked_mods = ctrl | num,
  2979. .mods = ctrl | level5 | num,
  2980. .locked_group = 0,
  2981. .group = 0,
  2982. .leds = num_led,
  2983. }
  2984. }
  2985. },
  2986. {
  2987. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  2988. .components = {
  2989. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  2990. .components = {
  2991. .base_mods = level5,
  2992. .locked_mods = num,
  2993. .mods = level5 | num,
  2994. .locked_group = 0,
  2995. .group = 0,
  2996. .leds = num_led,
  2997. }
  2998. }
  2999. },
  3000. {
  3001. .type = XKB_EVENT_TYPE_KEY_REPEATED,
  3002. .keycode = KEY_COPY + EVDEV_OFFSET
  3003. },
  3004. {
  3005. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  3006. .components = {
  3007. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  3008. .components = {
  3009. .base_mods = level5,
  3010. .locked_mods = ctrl | num,
  3011. .mods = ctrl | level5 | num,
  3012. .locked_group = 0,
  3013. .group = 0,
  3014. .leds = num_led,
  3015. }
  3016. }
  3017. },
  3018. {
  3019. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  3020. .components = {
  3021. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  3022. | XKB_STATE_MODS_EFFECTIVE,
  3023. .components = {
  3024. .base_mods = 0,
  3025. .locked_mods = ctrl | alt | num,
  3026. .mods = ctrl | alt | num,
  3027. .locked_group = 0,
  3028. .group = 0,
  3029. .leds = num_led,
  3030. }
  3031. }
  3032. },
  3033. );
  3034. assert(xkb_machine_process_key(sm, KEY_C + EVDEV_OFFSET,
  3035. XKB_KEY_UP, events) == 0);
  3036. check_events_(
  3037. events,
  3038. {
  3039. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  3040. .components = {
  3041. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  3042. | XKB_STATE_MODS_EFFECTIVE,
  3043. .components = {
  3044. .base_mods = level5,
  3045. .locked_mods = ctrl | num,
  3046. .mods = ctrl | level5 | num,
  3047. .locked_group = 0,
  3048. .group = 0,
  3049. .leds = num_led,
  3050. }
  3051. }
  3052. },
  3053. {
  3054. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  3055. .components = {
  3056. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  3057. .components = {
  3058. .base_mods = level5,
  3059. .locked_mods = num,
  3060. .mods = level5 | num,
  3061. .locked_group = 0,
  3062. .group = 0,
  3063. .leds = num_led,
  3064. }
  3065. }
  3066. },
  3067. {
  3068. .type = XKB_EVENT_TYPE_KEY_UP,
  3069. .keycode = KEY_COPY + EVDEV_OFFSET
  3070. },
  3071. {
  3072. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  3073. .components = {
  3074. .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE,
  3075. .components = {
  3076. .base_mods = level5,
  3077. .locked_mods = ctrl | num,
  3078. .mods = ctrl | level5 | num,
  3079. .locked_group = 0,
  3080. .group = 0,
  3081. .leds = num_led,
  3082. }
  3083. }
  3084. },
  3085. {
  3086. .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
  3087. .components = {
  3088. .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
  3089. | XKB_STATE_MODS_EFFECTIVE,
  3090. .components = {
  3091. .base_mods = 0,
  3092. .locked_mods = ctrl | alt | num,
  3093. .mods = ctrl | alt | num,
  3094. .locked_group = 0,
  3095. .group = 0,
  3096. .leds = num_led,
  3097. }
  3098. }
  3099. },
  3100. );
  3101. xkb_events_destroy(events);
  3102. xkb_machine_unref(sm);
  3103. xkb_keymap_unref(keymap);
  3104. }
  3105. int
  3106. main(void)
  3107. {
  3108. test_init();
  3109. struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
  3110. assert(context);
  3111. /* Make sure these are allowed. */
  3112. xkb_context_unref(NULL);
  3113. xkb_keymap_unref(NULL);
  3114. xkb_state_unref(NULL);
  3115. xkb_machine_unref(NULL);
  3116. xkb_machine_builder_destroy(NULL);
  3117. xkb_events_destroy(NULL);
  3118. test_machine_builder(context);
  3119. test_initial_derived_values(context);
  3120. assert(!xkb_events_new_batch(context, -1));
  3121. test_state_update(context);
  3122. test_group_wrap(context);
  3123. test_sticky_keys(context);
  3124. test_redirect_key(context);
  3125. test_overlays(context);
  3126. test_modifiers_tweak(context);
  3127. test_shortcuts_tweak(context);
  3128. xkb_context_unref(context);
  3129. return EXIT_SUCCESS;
  3130. }