| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707 |
- /*
- * Copyright © 2012 Intel Corporation
- * SPDX-License-Identifier: MIT
- *
- * Author: Daniel Stone <daniel@fooishbar.org>
- */
- #include "config.h"
- #include "test-config.h"
- #include <assert.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include "xkbcommon/xkbcommon-errors.h"
- #include "xkbcommon/xkbcommon-keysyms.h"
- #include "xkbcommon/xkbcommon-names.h"
- #include "xkbcommon/xkbcommon.h"
- #include "context.h"
- #include "evdev-scancodes.h"
- #include "src/keysym.h"
- #include "src/keymap.h"
- #include "state.h"
- #include "test.h"
- #include "utils.h"
- /* Reference implementation from XkbAdjustGroup in Xorg xserver */
- static int32_t
- group_wrap_ref(int32_t g, int32_t num_groups)
- {
- assert(num_groups >= 0);
- if (num_groups == 0) {
- return 0;
- } else if (g < 0) {
- while (g < 0)
- g += num_groups;
- } else if (g >= num_groups) {
- g %= num_groups;
- }
- return g;
- }
- /* Function extracted from XkbWrapGroupIntoRange (current) */
- static int32_t
- group_wrap(int32_t g, int32_t num_groups)
- {
- assert(num_groups >= 0);
- if (num_groups == 0)
- return 0;
- if (g >= 0 && g < num_groups)
- return g;
- const int32_t remainder = g % num_groups;
- return (remainder < 0) ? num_groups + remainder : remainder;
- }
- /* Old bogus implementation */
- static int32_t
- group_wrap_old(int32_t g, int32_t num_groups)
- {
- assert(num_groups >= 0);
- if (num_groups == 0)
- return 0;
- if (g >= 0 && g < num_groups)
- return g;
- /* Invalid modulus arithmetic (see comment in XkbWrapGroupIntoRange) */
- const int32_t remainder = g % num_groups;
- return (g < 0) ? num_groups + remainder : remainder;
- }
- static bool
- is_valid_group(int32_t g, int32_t num_groups)
- {
- assert(num_groups >= 0);
- return (num_groups > 0 && g >= 0 && g < num_groups);
- }
- static void
- test_group_wrap(struct xkb_context *ctx)
- {
- /* Compare wrap function with reference implementation */
- for (int32_t G = 0; G <= XKB_MAX_GROUPS; G++) {
- for (int32_t g = - 3 * (G + 1); g <= 3 * (G + 1); g++) {
- /* Same as xserver */
- assert(group_wrap(g, G) == group_wrap_ref(g, G));
- /* Old implementation */
- const int32_t old = group_wrap_old(g, G);
- const int32_t new = group_wrap(g, G);
- assert((old == new) ^ (G > 0 && g < 0 && ((-g) % G == 0)));
- }
- }
- /* Check some special cases */
- assert(group_wrap(-2, 0) == 0);
- assert(group_wrap(-1, 0) == 0);
- assert(group_wrap(0, 0) == 0);
- assert(group_wrap(1, 0) == 0);
- assert(group_wrap(2, 0) == 0);
- assert(group_wrap(-2, 1) == 0);
- assert(group_wrap(-1, 1) == 0);
- assert(group_wrap(0, 1) == 0);
- assert(group_wrap(1, 1) == 0);
- assert(group_wrap(2, 1) == 0);
- assert(group_wrap(-6, 2) == 0);
- assert(group_wrap(-5, 2) == 1);
- assert(group_wrap(-4, 2) == 0);
- assert(group_wrap(-3, 2) == 1);
- assert(group_wrap(-2, 2) == 0);
- assert(group_wrap(-1, 2) == 1);
- assert(group_wrap(0, 2) == 0);
- assert(group_wrap(1, 2) == 1);
- assert(group_wrap(2, 2) == 0);
- assert(group_wrap(3, 2) == 1);
- assert(group_wrap(4, 2) == 0);
- assert(group_wrap(5, 2) == 1);
- assert(group_wrap(6, 2) == 0);
- assert(group_wrap(-7, 3) == 2);
- assert(group_wrap(-6, 3) == 0);
- assert(group_wrap(-5, 3) == 1);
- assert(group_wrap(-4, 3) == 2);
- assert(group_wrap(-3, 3) == 0);
- assert(group_wrap(-2, 3) == 1);
- assert(group_wrap(-1, 3) == 2);
- assert(group_wrap(0, 3) == 0);
- assert(group_wrap(1, 3) == 1);
- assert(group_wrap(2, 3) == 2);
- assert(group_wrap(3, 3) == 0);
- assert(group_wrap(4, 3) == 1);
- assert(group_wrap(5, 3) == 2);
- assert(group_wrap(6, 3) == 0);
- assert(group_wrap(7, 3) == 1);
- assert(group_wrap(-9, 4) == 3);
- assert(group_wrap(-8, 4) == 0);
- assert(group_wrap(-7, 4) == 1);
- assert(group_wrap(-6, 4) == 2);
- assert(group_wrap(-5, 4) == 3);
- assert(group_wrap(-4, 4) == 0);
- assert(group_wrap(-3, 4) == 1);
- assert(group_wrap(-2, 4) == 2);
- assert(group_wrap(-1, 4) == 3);
- assert(group_wrap(0, 4) == 0);
- assert(group_wrap(1, 4) == 1);
- assert(group_wrap(2, 4) == 2);
- assert(group_wrap(3, 4) == 3);
- assert(group_wrap(4, 4) == 0);
- assert(group_wrap(5, 4) == 1);
- assert(group_wrap(6, 4) == 2);
- assert(group_wrap(7, 4) == 3);
- assert(group_wrap(8, 4) == 0);
- assert(group_wrap(9, 4) == 1);
- assert(group_wrap(-11, 5) == 4);
- assert(group_wrap(-10, 5) == 0);
- assert(group_wrap(-9, 5) == 1);
- assert(group_wrap(-8, 5) == 2);
- assert(group_wrap(-7, 5) == 3);
- assert(group_wrap(-6, 5) == 4);
- assert(group_wrap(-5, 5) == 0);
- assert(group_wrap(-4, 5) == 1);
- assert(group_wrap(-3, 5) == 2);
- assert(group_wrap(-2, 5) == 3);
- assert(group_wrap(-1, 5) == 4);
- assert(group_wrap(0, 5) == 0);
- assert(group_wrap(1, 5) == 1);
- assert(group_wrap(2, 5) == 2);
- assert(group_wrap(3, 5) == 3);
- assert(group_wrap(4, 5) == 4);
- assert(group_wrap(5, 5) == 0);
- assert(group_wrap(6, 5) == 1);
- assert(group_wrap(7, 5) == 2);
- assert(group_wrap(8, 5) == 3);
- assert(group_wrap(9, 5) == 4);
- assert(group_wrap(10, 5) == 0);
- assert(group_wrap(11, 5) == 1);
- /* Check state group computation */
- const struct {
- const char* keymap;
- xkb_layout_index_t layout_count;
- } keymaps[] = {
- {
- .keymap =
- "default xkb_keymap {\n"
- " xkb_keycodes { <> = 1; };\n"
- " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n"
- "};",
- .layout_count = 0
- },
- {
- .keymap =
- "default xkb_keymap {\n"
- " xkb_keycodes { <> = 1; };\n"
- " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n"
- " xkb_symbols {\n"
- " key <> { [a] };\n"
- " };\n"
- "};",
- .layout_count = 1
- },
- {
- .keymap =
- "default xkb_keymap {\n"
- " xkb_keycodes { <> = 1; };\n"
- " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n"
- " xkb_symbols {\n"
- " key <> { [a], [b] };\n"
- " };\n"
- "};",
- .layout_count = 2
- },
- {
- .keymap =
- /* 3 groups */
- "default xkb_keymap {\n"
- " xkb_keycodes { <> = 1; };\n"
- " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n"
- " xkb_symbols {\n"
- " key <> { [a], [b], [c] };\n"
- " };\n"
- "};",
- .layout_count = 3
- },
- {
- .keymap =
- /* 4 groups */
- "default xkb_keymap {\n"
- " xkb_keycodes { <> = 1; };\n"
- " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n"
- " xkb_symbols {\n"
- " key <> { [a], [b], [c], [d] };\n"
- " };\n"
- "};",
- .layout_count = 4
- },
- {
- .keymap =
- "default xkb_keymap {\n"
- " xkb_keycodes { <> = 1; };\n"
- " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n"
- " xkb_symbols {\n"
- " key <> { [a], [b], [c], [d], [e] };\n"
- " };\n"
- "};",
- .layout_count = 5
- },
- {
- .keymap =
- "default xkb_keymap {\n"
- " xkb_keycodes { <> = 1; };\n"
- " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n"
- " xkb_symbols {\n"
- " key <> {\n"
- " [a], [b], [c], [d], [e], [f], [g], [h], [i], [j],\n"
- " [k], [l], [m], [n], [o], [p], [q], [r], [s], [t],\n"
- " [u], [v], [w], [x], [y], [z], [1], [2], [3], [4],\n"
- " [5], [6]\n"
- " };\n"
- " };\n"
- "};",
- .layout_count = XKB_MAX_GROUPS
- }
- };
- static_assert(ARRAY_SIZE(keymaps) > XKB_MAX_GROUPS_X11, "Not enough maps");
- for (int32_t k = 0; k < (int32_t)ARRAY_SIZE(keymaps); k++) {
- for (unsigned int f = (keymaps[k].layout_count < XKB_MAX_GROUPS_X11) ? 0 : 1;
- f < ARRAY_SIZE(keymap_formats); f++) {
- const enum xkb_keymap_format format = keymap_formats[f];
- const int32_t g = (int32_t) keymaps[k].layout_count;
- fprintf(stderr, "------\n*** %s: #%"PRId32" groups, format %d ***\n",
- __func__, g, format);
- struct xkb_keymap *keymap =
- test_compile_buffer(ctx, format,
- keymaps[k].keymap, strlen(keymaps[k].keymap));
- assert(keymap);
- assert(xkb_keymap_num_layouts(keymap) == keymaps[k].layout_count);
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- const xkb_keycode_t keycode = xkb_keymap_key_by_name(keymap, "");
- assert(keycode == 1);
- for (int32_t base = -2*(g + 1); base <= 2*(g + 1); base++) {
- for (int32_t latched = -2*(g + 1); latched <= 2*(g + 1); latched++) {
- for (int32_t locked = -2*(g + 1); locked <= 2*(g + 2); locked++) {
- xkb_state_update_mask(state, 0, 0, 0, base, latched, locked);
- xkb_layout_index_t got;
- xkb_layout_index_t expected;
- /* Base layout should be unchanged */
- got = xkb_state_serialize_layout(state,
- XKB_STATE_LAYOUT_DEPRESSED);
- expected = (xkb_layout_index_t) base;
- assert_printf(got == expected,
- "Base layout: expected %"PRIu32", "
- "got: %"PRIu32"\n",
- expected, got);
- /* Latched layout should be unchanged */
- got = xkb_state_serialize_layout(state,
- XKB_STATE_LAYOUT_LATCHED);
- expected = (xkb_layout_index_t) latched;
- assert_printf(got == expected,
- "Latched layout: expected %"PRIu32", "
- "got: %"PRIu32"\n",
- expected, got);
- /* Locked layout should be wrapped */
- got = xkb_state_serialize_layout(state,
- XKB_STATE_LAYOUT_LOCKED);
- const xkb_layout_index_t locked_expected =
- group_wrap(locked, g);
- expected = locked_expected;
- assert_printf(got == expected,
- "Locked layout: expected %"PRIu32", "
- "got: %"PRIu32"\n",
- expected, got);
- /* Effective layout should be wrapped */
- got = xkb_state_serialize_layout(state,
- XKB_STATE_LAYOUT_EFFECTIVE);
- const xkb_layout_index_t effective_expected =
- group_wrap(base + latched + (int32_t) locked_expected, g);
- expected = effective_expected;
- assert_printf(got == expected,
- "Effective layout: expected %"PRIu32", "
- "got: %"PRIu32"\n",
- expected, got);
- /*
- * Ensure all API using a layout index do not segfault
- */
- xkb_keymap_layout_get_name(keymap, base);
- const xkb_level_index_t num_levels =
- xkb_keymap_num_levels_for_key(keymap, keycode, base);
- const xkb_level_index_t num_levels_expected = (g > 0);
- assert_printf(num_levels == num_levels_expected,
- "Group=%"PRId32"/%"PRId32": "
- "Expected %"PRIu32", got: %"PRIu32"\n",
- base + 1, g, num_levels_expected, num_levels);
- xkb_mod_mask_t masks[1] = {0};
- const size_t size =
- xkb_keymap_key_get_mods_for_level(keymap, keycode, base, 0,
- masks, ARRAY_SIZE(masks));
- const size_t size_expected = (g > 0);
- assert(size == size_expected && masks[0] == 0);
- const xkb_keysym_t *keysyms = NULL;
- const int num_keysyms =
- xkb_keymap_key_get_syms_by_level(keymap, keycode, base,
- 0, &keysyms);
- const int num_keysyms_expected = (g > 0);
- assert(num_keysyms == num_keysyms_expected &&
- (g == 0 || keysyms[0] != XKB_KEY_NoSymbol));
- const xkb_level_index_t level =
- xkb_state_key_get_level(state, keycode, base);
- const xkb_level_index_t level_expected =
- is_valid_group(base, g) ? 0 : XKB_LEVEL_INVALID;
- assert_printf(level == level_expected,
- "Group=%"PRId32"/%"PRId32": "
- "Expected %"PRIu32", got: %"PRIu32"\n",
- base + 1, g, level_expected, level);
- int is_active, is_active_expected;
- is_active = xkb_state_layout_index_is_active(
- state, base, XKB_STATE_LAYOUT_DEPRESSED
- );
- is_active_expected = is_valid_group(base, g) ? 1 : -1;
- assert(is_active == is_active_expected);
- is_active = xkb_state_layout_index_is_active(
- state, latched, XKB_STATE_LAYOUT_LATCHED
- );
- is_active_expected = is_valid_group(latched, g) ? 1 : -1;
- assert(is_active == is_active_expected);
- is_active = xkb_state_layout_index_is_active(
- state, locked, XKB_STATE_LAYOUT_LOCKED
- );
- is_active_expected =
- is_valid_group(locked, g) ? 1 : -1;
- assert(is_active == is_active_expected);
- is_active = xkb_state_layout_index_is_active(
- state, locked_expected, XKB_STATE_LAYOUT_LOCKED
- );
- assert(
- is_valid_group((int32_t) locked_expected, g) == (g > 0)
- );
- is_active_expected =
- is_valid_group((int32_t) locked_expected, g) ? 1 : -1;
- assert(is_active == is_active_expected);
- is_active = xkb_state_layout_index_is_active(
- state, effective_expected, XKB_STATE_LAYOUT_EFFECTIVE
- );
- assert(
- is_valid_group((int32_t) effective_expected, g) == (g > 0)
- );
- is_active_expected =
- is_valid_group((int32_t) effective_expected, g) ? 1 : -1;
- assert(is_active == is_active_expected);
- }
- }
- }
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }}
- }
- static void
- test_state_modes(struct xkb_context *ctx)
- {
- struct xkb_keymap * const keymap = test_compile_rules(
- ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
- "pc104", "us", NULL, NULL
- );
- assert(keymap);
- enum { LEGACY_STATE_MODE = 0xff };
- const xkb_mod_mask_t shift =
- _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_SHIFT);
- const xkb_mod_mask_t caps =
- _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_CAPS);
- const xkb_mod_mask_t ctrl =
- _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_CTRL);
- const xkb_mod_mask_t num =
- _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_NUM);
- const struct {
- enum xkb_state_mode mode;
- struct components_entry {
- struct state_components components;
- enum xkb_state_component changed;
- enum xkb_error_code error;
- } update_mask;
- struct components_entry update_event;
- enum xkb_state_component update_key;
- struct components_entry update_latch_locked;
- struct components_entry update_synthetic;
- } tests[] = {
- {
- .mode = (enum xkb_state_mode)LEGACY_STATE_MODE,
- .update_mask = {
- .components = { .base_mods = shift },
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
- },
- .update_event = {
- .components = { .base_mods = ctrl, .mods = ctrl },
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
- },
- .update_key = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
- .update_latch_locked = {
- .components = { .locked_mods = caps },
- .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
- | XKB_STATE_LEDS,
- },
- .update_synthetic = {
- .components = { .locked_mods = num },
- .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
- | XKB_STATE_LEDS,
- .error = 0,
- },
- },
- {
- .mode = XKB_STATE_MODE_CLIENT,
- .update_mask = {
- .components = { .base_mods = shift },
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
- },
- .update_event = {
- .components = { .base_mods = ctrl, .mods = ctrl },
- .changed = 0, /* wrong mode */
- },
- .update_key = 0, /* wrong mode */
- .update_latch_locked = {
- .components = { .locked_mods = caps },
- .changed = 0, /* wrong mode */
- },
- .update_synthetic = {
- .components = { .locked_mods = num },
- /* wrong mode */
- .changed = 0,
- .error = XKB_ERROR_UNEXPECTED_STATE_MODE,
- },
- },
- {
- .mode = XKB_STATE_MODE_SERVER_QUERY,
- .update_mask = {
- .components = { .base_mods = shift },
- .changed = 0, /* wrong mode */
- },
- .update_event = {
- .components = { .base_mods = ctrl, .mods = ctrl },
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
- },
- .update_key = 0, /* wrong mode */
- .update_latch_locked = {
- .components = { .locked_mods = caps },
- .changed = 0, /* wrong mode */
- },
- .update_synthetic = {
- .components = { .locked_mods = num },
- /* wrong mode */
- .changed = 0,
- .error = XKB_ERROR_UNEXPECTED_STATE_MODE,
- },
- },
- {
- .mode = XKB_STATE_MODE_SERVER,
- .update_mask = {
- .components = { .base_mods = shift },
- .changed = 0, /* wrong mode */
- },
- .update_event = {
- .components = { .base_mods = ctrl, .mods = ctrl },
- .changed = 0, /* wrong mode */
- },
- .update_key = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE,
- .update_latch_locked = {
- .components = { .locked_mods = caps },
- .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
- | XKB_STATE_LEDS,
- },
- .update_synthetic = {
- .components = { .locked_mods = num },
- .changed = XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
- | XKB_STATE_LEDS,
- .error = 0,
- },
- },
- };
- for (size_t t = 0; t < ARRAY_SIZE(tests); t++) {
- fprintf(stderr, "------\n*** %s: #%zu (mode: %d) ***\n",
- __func__, t, tests[t].mode);
- struct xkb_state * const state =
- (tests[t].mode == (enum xkb_state_mode)LEGACY_STATE_MODE)
- ? xkb_state_new(keymap)
- : xkb_state_new_with_mode(keymap, tests[t].mode);
- assert(state);
- enum xkb_state_component changed = 0;
- int code = EXIT_SUCCESS;
- #define expected_code(x) ((x) ? EXIT_SUCCESS : TEST_ASSERT_FAILURE)
- RUN_ISOLATED(code, changed,
- changed = xkb_state_update_mask(
- state,
- tests[t].update_mask.components.base_mods,
- tests[t].update_mask.components.latched_mods,
- tests[t].update_mask.components.locked_mods,
- tests[t].update_mask.components.base_group,
- tests[t].update_mask.components.latched_group,
- tests[t].update_mask.components.locked_group
- );
- /* Avoid Valgrind false positive */
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- );
- if (code != SKIP_TEST) {
- assert_eq("update_mask: code",
- expected_code(tests[t].update_mask.changed), code, "%d");
- assert_eq("update_mask: changed",
- tests[t].update_mask.changed, changed, "%d");
- }
- #ifndef _WIN32
- const struct xkb_event event = {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = tests[t].update_event.changed,
- .components = tests[t].update_event.components,
- }
- };
- #endif
- RUN_ISOLATED(code, changed,
- changed = xkb_state_update_event(state, &event);
- /* Avoid Valgrind false positive */
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- );
- if (code != SKIP_TEST) {
- assert_eq("update_event: code",
- expected_code(tests[t].update_event.changed), code, "%d");
- assert_eq("update_event: changed",
- tests[t].update_event.changed, changed, "%d");
- }
- RUN_ISOLATED(code, changed,
- changed = xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET,
- XKB_KEY_DOWN);
- xkb_state_unref(state)
- );
- if (code != SKIP_TEST) {
- assert_eq("update_key: code",
- expected_code(tests[t].update_key), code, "%d");
- assert_eq("update_key: changed", tests[t].update_key, changed, "%d");
- }
- RUN_ISOLATED(code, changed,
- changed = xkb_state_update_latched_locked(
- state,
- tests[t].update_latch_locked.components.latched_mods,
- tests[t].update_latch_locked.components.latched_mods,
- false, 0,
- tests[t].update_latch_locked.components.locked_mods,
- tests[t].update_latch_locked.components.locked_mods,
- false, 0
- );
- /* Avoid Valgrind false positive */
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- );
- if (code != SKIP_TEST) {
- assert_eq("update_latched_locked: code",
- expected_code(tests[t].update_latch_locked.changed),
- code, "%d");
- assert_eq("update_latched_locked: changed",
- tests[t].update_latch_locked.changed, changed, "%d");
- }
- const struct xkb_state_components_update components_update = {
- .size = sizeof(components_update),
- .components = tests[t].update_synthetic.changed,
- .affect_latched_mods = tests[t].update_synthetic.components.latched_mods,
- .latched_mods = tests[t].update_synthetic.components.latched_mods,
- .affect_locked_mods = tests[t].update_synthetic.components.locked_mods,
- .locked_mods = tests[t].update_synthetic.components.locked_mods,
- };
- const struct xkb_state_update update = {
- .size = sizeof(update),
- .components = &components_update
- };
- struct result {
- enum xkb_state_component changed;
- enum xkb_error_code error;
- } r = { 0 };
- RUN_ISOLATED(code, r,
- r.error = xkb_state_update_synthetic(state, &update, &r.changed);
- /* Avoid Valgrind false positive */
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- );
- if (code != SKIP_TEST) {
- assert_eq("update_synthetic: code", EXIT_SUCCESS, code, "%d");
- assert_eq("update_synthetic: error",
- tests[t].update_synthetic.error, r.error, "%d");
- assert_eq("update_synthetic: changed",
- tests[t].update_synthetic.changed, r.changed, "%d");
- }
- xkb_state_unref(state);
- }
- #undef expected_code
- xkb_keymap_unref(keymap);
- }
- /* Check that derived state is correctly initialized */
- static void
- test_initial_derived_values(struct xkb_context *ctx)
- {
- struct xkb_keymap * const keymap = test_compile_rules(
- ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
- "pc104", "us", NULL, "grp1_led:scroll"
- );
- assert(keymap);
- struct xkb_state *const state = xkb_state_new(keymap);
- assert(state);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_SCROLL));
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }
- static inline bool
- check_serialize_layout(enum xkb_state_component components,
- struct xkb_state *expected, struct xkb_state *got)
- {
- return
- xkb_state_serialize_layout(expected, components) ==
- xkb_state_serialize_layout(got, components);
- }
- static inline bool
- check_serialize_mods(enum xkb_state_component components,
- struct xkb_state *expected, struct xkb_state *got)
- {
- return
- xkb_state_serialize_mods(expected, components) ==
- xkb_state_serialize_mods(got, components);
- }
- static bool
- check_state(struct xkb_state *expected, struct xkb_state *got)
- {
- bool ok = check_serialize_layout(XKB_STATE_LAYOUT_DEPRESSED, expected, got) &&
- check_serialize_layout(XKB_STATE_LAYOUT_LATCHED, expected, got) &&
- check_serialize_layout(XKB_STATE_LAYOUT_LOCKED, expected, got) &&
- check_serialize_layout(XKB_STATE_LAYOUT_EFFECTIVE, expected, got) &&
- check_serialize_mods(XKB_STATE_MODS_DEPRESSED, expected, got) &&
- check_serialize_mods(XKB_STATE_MODS_LATCHED, expected, got) &&
- check_serialize_mods(XKB_STATE_MODS_LOCKED, expected, got) &&
- check_serialize_mods(XKB_STATE_MODS_EFFECTIVE, expected, got);
- struct xkb_keymap *keymap = xkb_state_get_keymap(expected);
- for (xkb_led_index_t led = 0; led < xkb_keymap_num_leds(keymap); led++) {
- if (xkb_state_led_index_is_active(expected, led) !=
- xkb_state_led_index_is_active(got, led)) {
- ok = false;
- break;
- }
- }
- if (!ok) {
- fprintf(stderr, "Expected state:\n");
- print_state(expected);
- print_layout_serialization(expected);
- print_modifiers_serialization(expected);
- fprintf(stderr, "Got state:\n");
- print_state(got);
- print_layout_serialization(got);
- print_modifiers_serialization(got);
- }
- return ok;
- }
- /* Utils for checking modifier state */
- typedef bool (* is_active_t)(int);
- static inline bool
- is_active(int x)
- {
- return x > 0;
- }
- static inline bool
- is_not_active(int x)
- {
- return x == 0;
- }
- static void
- test_update_key(struct xkb_context *ctx, struct xkb_keymap *keymap,
- bool pure_vmods)
- {
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- struct xkb_machine_builder *builder =
- xkb_machine_builder_new(keymap, XKB_MACHINE_BUILDER_NO_FLAGS);
- assert(builder);
- struct xkb_machine *sm = xkb_machine_new(builder);
- assert(sm);
- xkb_machine_builder_destroy(builder);
- struct xkb_events *events = xkb_events_new_batch(ctx, XKB_EVENTS_NO_FLAGS);
- assert(events);
- const xkb_keysym_t *syms;
- xkb_keysym_t one_sym;
- int num_syms;
- is_active_t check_active = pure_vmods ? is_not_active : is_active;
- xkb_mod_index_t ctrl = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
- xkb_mod_index_t mod1 = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1);
- xkb_mod_index_t alt = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT);
- xkb_mod_index_t meta = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META);
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_EFFECTIVE, 0x4,
- XKB_MOD_NAME_CTRL) == -2);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, 0x4,
- ctrl) == -2);
- #define update_states(state1, sm, key, direction) do { \
- xkb_state_update_key((state1), (key), (direction)); \
- assert(xkb_machine_process_key((sm), (key), (direction), (events))\
- == 0); \
- } while (0)
- /* LCtrl down */
- update_states(state, sm, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN);
- fprintf(stderr, "dumping state for LCtrl down:\n");
- print_state(state);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_DOWN,
- .keycode = KEY_LEFTCTRL + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .components = {
- .base_mods = xkb_keymap_mod_get_mask2(keymap, ctrl),
- .mods = xkb_keymap_mod_get_mask2(keymap, ctrl),
- },
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE
- }
- }
- );
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL,
- XKB_STATE_MODS_DEPRESSED) > 0);
- /* Ensure it does not repeat */
- update_states(state, sm, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_REPEATED);
- check_events_(events, { .type = XKB_EVENT_TYPE_NONE });
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL,
- XKB_STATE_MODS_DEPRESSED) > 0);
- /* LCtrl + RAlt down */
- update_states(state, sm, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_DOWN);
- fprintf(stderr, "dumping state for LCtrl + RAlt down:\n");
- print_state(state);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_DOWN,
- .keycode = KEY_RIGHTALT + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .components = {
- .base_mods = xkb_keymap_mod_get_mask2(keymap, ctrl)
- | xkb_keymap_mod_get_mask2(keymap, alt),
- .mods = xkb_keymap_mod_get_mask2(keymap, ctrl)
- | xkb_keymap_mod_get_mask2(keymap, alt),
- },
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE
- }
- }
- );
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL,
- XKB_STATE_MODS_DEPRESSED) > 0);
- assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_ALT,
- XKB_STATE_MODS_DEPRESSED) > 0);
- assert(check_active(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_MOD1,
- XKB_STATE_MODS_DEPRESSED)));
- assert(check_active(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_META,
- XKB_STATE_MODS_DEPRESSED)));
- if (pure_vmods) {
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL,
- XKB_MOD_NAME_CTRL,
- XKB_VMOD_NAME_ALT,
- NULL) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL, ctrl, alt,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL,
- XKB_MOD_NAME_MOD1,
- XKB_VMOD_NAME_META,
- NULL) == 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL,
- mod1, meta,
- XKB_MOD_INVALID) == 0);
- } else {
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL,
- XKB_MOD_NAME_CTRL,
- XKB_MOD_NAME_MOD1,
- XKB_VMOD_NAME_ALT,
- XKB_VMOD_NAME_META,
- NULL) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL,
- ctrl, mod1, alt, meta,
- XKB_MOD_INVALID) > 0);
- }
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL,
- XKB_MOD_NAME_MOD1,
- NULL) == 0);
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL,
- XKB_VMOD_NAME_ALT,
- NULL) == 0);
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL,
- XKB_VMOD_NAME_META,
- NULL) == 0);
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL |
- XKB_STATE_MATCH_NON_EXCLUSIVE,
- XKB_VMOD_NAME_ALT,
- NULL) > 0);
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- (XKB_STATE_MATCH_ANY |
- XKB_STATE_MATCH_NON_EXCLUSIVE),
- XKB_VMOD_NAME_ALT,
- NULL) > 0);
- assert(check_active(xkb_state_mod_names_are_active(
- state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE,
- XKB_MOD_NAME_MOD1,
- NULL)));
- assert(check_active(xkb_state_mod_names_are_active(
- state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE,
- XKB_VMOD_NAME_META,
- NULL)));
- assert(check_active(xkb_state_mod_names_are_active(
- state, XKB_STATE_MODS_DEPRESSED,
- (XKB_STATE_MATCH_ANY | XKB_STATE_MATCH_NON_EXCLUSIVE),
- XKB_MOD_NAME_MOD1,
- NULL)));
- assert(check_active(xkb_state_mod_names_are_active(
- state, XKB_STATE_MODS_DEPRESSED,
- (XKB_STATE_MATCH_ANY | XKB_STATE_MATCH_NON_EXCLUSIVE),
- XKB_VMOD_NAME_META,
- NULL)));
- /* Ensure it does not repeat */
- update_states(state, sm, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_REPEATED);
- check_events_(events, { .type = XKB_EVENT_TYPE_NONE });
- /* RAlt down */
- update_states(state, sm, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP);
- fprintf(stderr, "dumping state for RAlt down:\n");
- print_state(state);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_UP,
- .keycode = KEY_LEFTCTRL + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .components = {
- .base_mods = xkb_keymap_mod_get_mask2(keymap, alt),
- .mods = xkb_keymap_mod_get_mask2(keymap, alt),
- },
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE
- }
- }
- );
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL,
- XKB_STATE_MODS_EFFECTIVE) == 0);
- assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_ALT,
- XKB_STATE_MODS_DEPRESSED) > 0);
- assert(check_active(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_MOD1,
- XKB_STATE_MODS_DEPRESSED)));
- assert(check_active(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_META,
- XKB_STATE_MODS_DEPRESSED)));
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED,
- XKB_STATE_MATCH_ANY,
- XKB_MOD_NAME_CTRL,
- XKB_MOD_NAME_MOD1,
- XKB_VMOD_NAME_ALT,
- XKB_VMOD_NAME_META,
- NULL) > 0);
- assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_LATCHED,
- XKB_STATE_MATCH_ANY,
- XKB_MOD_NAME_CTRL,
- XKB_MOD_NAME_MOD1,
- XKB_VMOD_NAME_ALT,
- XKB_VMOD_NAME_META,
- NULL) == 0);
- /* none down */
- update_states(state, sm, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_UP);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_UP,
- .keycode = KEY_RIGHTALT + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .components = { .base_mods = 0, .mods = 0, },
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE
- }
- }
- );
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_MOD1,
- XKB_STATE_MODS_EFFECTIVE) == 0);
- assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_ALT,
- XKB_STATE_MODS_EFFECTIVE) == 0);
- assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_META,
- XKB_STATE_MODS_EFFECTIVE) == 0);
- /* Caps locked */
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_EFFECTIVE) == 0);
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_DEPRESSED) > 0);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_LOCKED) > 0);
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_REPEATED);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_DEPRESSED) > 0);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_LOCKED) > 0);
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- fprintf(stderr, "dumping state for Caps Lock:\n");
- print_state(state);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_DEPRESSED) == 0);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_LOCKED) > 0);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_CAPS) > 0);
- num_syms = xkb_state_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms);
- assert(num_syms == 1 && syms[0] == XKB_KEY_Q);
- /* Num Lock locked */
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- fprintf(stderr, "dumping state for Caps Lock + Num Lock:\n");
- print_state(state);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_LOCKED) > 0);
- assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_NUM,
- XKB_STATE_MODS_LOCKED) > 0);
- assert(check_active(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_MOD2,
- XKB_STATE_MODS_LOCKED)));
- num_syms = xkb_state_key_get_syms(state, KEY_KP1 + EVDEV_OFFSET, &syms);
- assert(num_syms == 1 && syms[0] == XKB_KEY_KP_1);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) > 0);
- /* Num Lock unlocked */
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- /* Switch to group 2 */
- update_states(state, sm, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN);
- update_states(state, sm, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_led_name_is_active(state, "Group 2") > 0);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) == 0);
- /* Switch back to group 1. */
- update_states(state, sm, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN);
- update_states(state, sm, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP);
- /* Caps unlocked */
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_EFFECTIVE) == 0);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_CAPS) == 0);
- num_syms = xkb_state_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms);
- assert(num_syms == 1 && syms[0] == XKB_KEY_q);
- /* Repeat CapsLock does nothing: non-repeating key */
- const xkb_mod_mask_t caps = _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_CAPS);
- const xkb_led_mask_t caps_led =
- UINT32_C(1) << _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_CAPS);
- assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_EFFECTIVE) == 0);
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_DOWN,
- .keycode = KEY_CAPSLOCK + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
- | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS,
- .components = {
- .base_mods = caps,
- .locked_mods = caps,
- .mods = caps,
- .leds = caps_led
- }
- }
- }
- );
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_REPEATED);
- check_events_(events, { .type = XKB_EVENT_TYPE_NONE });
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_UP,
- .keycode = KEY_CAPSLOCK + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = XKB_STATE_MODS_DEPRESSED,
- .components = {
- .base_mods = 0,
- .locked_mods = caps,
- .mods = caps,
- .leds = caps_led
- }
- }
- }
- );
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_DOWN,
- .keycode = KEY_CAPSLOCK + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = XKB_STATE_MODS_DEPRESSED,
- .components = {
- .base_mods = caps,
- .locked_mods = caps,
- .mods = caps,
- .leds = caps_led
- }
- }
- }
- );
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_REPEATED);
- check_events_(events, { .type = XKB_EVENT_TYPE_NONE });
- update_states(state, sm, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_UP,
- .keycode = KEY_CAPSLOCK + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
- | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS,
- .components = {
- .base_mods = 0,
- .locked_mods = 0,
- .mods = 0,
- .leds = 0,
- }
- }
- }
- );
- /* Repeat NumLock does nothing: repeating key */
- const xkb_mod_mask_t num = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_NUM);
- const xkb_led_mask_t num_led =
- UINT32_C(1) << _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_NUM);
- assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_NUM,
- XKB_STATE_MODS_EFFECTIVE) == 0);
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_DOWN,
- .keycode = KEY_NUMLOCK + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
- | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS,
- .components = {
- .base_mods = num,
- .locked_mods = num,
- .mods = num,
- .leds = num_led
- }
- }
- }
- );
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_REPEATED);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_REPEATED,
- .keycode = KEY_NUMLOCK + EVDEV_OFFSET
- }
- );
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_UP,
- .keycode = KEY_NUMLOCK + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = XKB_STATE_MODS_DEPRESSED,
- .components = {
- .base_mods = 0,
- .locked_mods = num,
- .mods = num,
- .leds = num_led
- }
- }
- }
- );
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_DOWN,
- .keycode = KEY_NUMLOCK + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = XKB_STATE_MODS_DEPRESSED,
- .components = {
- .base_mods = num,
- .locked_mods = num,
- .mods = num,
- .leds = num_led
- }
- }
- }
- );
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_REPEATED);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_REPEATED,
- .keycode = KEY_NUMLOCK + EVDEV_OFFSET
- }
- );
- update_states(state, sm, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_UP,
- .keycode = KEY_NUMLOCK + EVDEV_OFFSET
- },
- {
- .type = XKB_EVENT_TYPE_COMPONENTS_CHANGE,
- .components = {
- .changed = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED
- | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS,
- .components = {
- .base_mods = 0,
- .locked_mods = 0,
- .mods = 0,
- .leds = 0,
- }
- }
- }
- );
- /* One symbol */
- num_syms = xkb_state_key_get_syms(state, KEY_5 + EVDEV_OFFSET, &syms);
- assert(num_syms == 1 && syms[0] == XKB_KEY_5);
- one_sym = xkb_state_key_get_one_sym(state, KEY_5 + EVDEV_OFFSET);
- assert(one_sym == XKB_KEY_5);
- update_states(state, sm, KEY_5 + EVDEV_OFFSET, XKB_KEY_DOWN);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_DOWN,
- .keycode = KEY_5 + EVDEV_OFFSET
- }
- );
- /* Ensure it does repeat */
- update_states(state, sm, KEY_5 + EVDEV_OFFSET, XKB_KEY_REPEATED);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_REPEATED,
- .keycode = KEY_5 + EVDEV_OFFSET
- }
- );
- update_states(state, sm, KEY_5 + EVDEV_OFFSET, XKB_KEY_UP);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_UP,
- .keycode = KEY_5 + EVDEV_OFFSET
- }
- );
- /* Multiple symbols */
- num_syms = xkb_state_key_get_syms(state, KEY_6 + EVDEV_OFFSET, &syms);
- assert(num_syms == 5 &&
- syms[0] == XKB_KEY_H && syms[1] == XKB_KEY_E &&
- syms[2] == XKB_KEY_L && syms[3] == XKB_KEY_L &&
- syms[4] == XKB_KEY_O);
- one_sym = xkb_state_key_get_one_sym(state, KEY_6 + EVDEV_OFFSET);
- assert(one_sym == XKB_KEY_NoSymbol);
- update_states(state, sm, KEY_6 + EVDEV_OFFSET, XKB_KEY_DOWN);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_DOWN,
- .keycode = KEY_6 + EVDEV_OFFSET
- }
- );
- /* Ensure it does repeat */
- update_states(state, sm, KEY_6 + EVDEV_OFFSET, XKB_KEY_REPEATED);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_REPEATED,
- .keycode = KEY_6 + EVDEV_OFFSET
- }
- );
- update_states(state, sm, KEY_6 + EVDEV_OFFSET, XKB_KEY_UP);
- check_events_(
- events,
- {
- .type = XKB_EVENT_TYPE_KEY_UP,
- .keycode = KEY_6 + EVDEV_OFFSET
- }
- );
- xkb_events_destroy(events);
- xkb_machine_unref(sm);
- xkb_state_unref(state);
- #undef update_states
- }
- enum test_entry_input_type {
- INPUT_TYPE_RESET = 0,
- INPUT_TYPE_COMPONENTS,
- INPUT_TYPE_KEY,
- };
- struct test_state_components {
- enum test_entry_input_type input_type;
- union {
- struct {
- bool affect_latched_group;
- int32_t latched_group;
- bool affect_locked_group;
- int32_t locked_group;
- xkb_mod_mask_t affect_latched_mods;
- xkb_mod_mask_t latched_mods;
- xkb_mod_mask_t affect_locked_mods;
- xkb_mod_mask_t locked_mods;
- } input;
- struct {
- xkb_keycode_t keycode;
- enum key_seq_state direction;
- xkb_keysym_t keysym;
- } key;
- };
- /* Same as state_components, but it is not public */
- int32_t base_group; /**< depressed */
- int32_t latched_group;
- int32_t locked_group;
- xkb_layout_index_t group; /**< effective */
- xkb_mod_mask_t base_mods; /**< depressed */
- xkb_mod_mask_t latched_mods;
- xkb_mod_mask_t locked_mods;
- xkb_mod_mask_t mods; /**< effective */
- xkb_led_mask_t leds;
- enum xkb_state_component changes;
- };
- #define COMPONENTS_ENTRY(...) \
- .input_type = INPUT_TYPE_COMPONENTS, .input = { __VA_ARGS__ }
- #define KEY_ENTRY(_keycode, _direction, _keysym) \
- .input_type = INPUT_TYPE_KEY, \
- .key = { .keycode=(_keycode) + EVDEV_OFFSET, \
- .direction=(_direction), \
- .keysym=(_keysym) }
- #define RESET_STATE { .input_type = INPUT_TYPE_RESET }
- static bool
- check_update_state(struct xkb_keymap *keymap,
- const struct test_state_components *components,
- struct xkb_state *expected, struct xkb_state *got,
- xkb_keysym_t keysym, enum xkb_state_component changes)
- {
- xkb_state_update_mask(expected,
- mod_mask_get_effective(keymap, components->base_mods),
- mod_mask_get_effective(keymap, components->latched_mods),
- mod_mask_get_effective(keymap, components->locked_mods),
- components->base_group,
- components->latched_group,
- components->locked_group);
- if (changes != components->changes) {
- fprintf(stderr, "Expected state change: %u, but got: %u\n",
- components->changes, changes);
- fprintf(stderr, "Expected state:\n");
- print_state(expected);
- fprintf(stderr, "Got state:\n");
- print_state(got);
- return false;
- } else if (components->input_type == INPUT_TYPE_KEY) {
- if (keysym != components->key.keysym) {
- char buf[XKB_KEYSYM_NAME_MAX_SIZE];
- xkb_keysym_get_name(components->key.keysym, buf, sizeof(buf));
- fprintf(stderr, "Expected keysym: %s, ", buf);
- xkb_keysym_get_name(keysym, buf, sizeof(buf));
- fprintf(stderr, "but got: %s\n", buf);
- return false;
- }
- } else if (keysym != XKB_KEY_NoSymbol) {
- return false;
- }
- return check_state(expected, got);
- }
- static bool
- run_state_update(struct xkb_keymap *keymap,
- const struct test_state_components *components,
- struct xkb_state **expected, struct xkb_state **got)
- {
- xkb_keysym_t keysym = XKB_KEY_NoSymbol;
- enum xkb_state_component changes = 0;
- switch (components->input_type) {
- case INPUT_TYPE_COMPONENTS:
- changes = xkb_state_update_latched_locked(
- *got,
- components->input.affect_latched_mods,
- components->input.latched_mods,
- components->input.affect_latched_group,
- components->input.latched_group,
- components->input.affect_locked_mods,
- components->input.locked_mods,
- components->input.affect_locked_group,
- components->input.locked_group
- );
- break;
- case INPUT_TYPE_KEY:
- keysym =
- xkb_state_key_get_one_sym(*got, components->key.keycode);
- if (components->key.direction == DOWN ||
- components->key.direction == BOTH)
- changes = xkb_state_update_key(
- *got, components->key.keycode, XKB_KEY_DOWN
- );
- if (components->key.direction == UP ||
- components->key.direction == BOTH)
- changes = xkb_state_update_key(
- *got, components->key.keycode, XKB_KEY_UP
- );
- break;
- case INPUT_TYPE_RESET:
- xkb_state_unref(*got);
- xkb_state_unref(*expected);
- *got = xkb_state_new(keymap);
- *expected = xkb_state_new(keymap);
- assert(*got);
- assert(*expected);
- return true;
- default:
- assert_printf(false, "Unsupported input type: %d\n",
- components->input_type);
- }
- return check_update_state(
- keymap, components, *expected, *got, keysym, changes
- );
- }
- static void
- test_update_latched_locked(struct xkb_keymap *keymap)
- {
- struct xkb_state *state = xkb_state_new(keymap);
- struct xkb_state *expected = xkb_state_new(keymap);
- assert(state);
- assert(expected);
- xkb_mod_mask_t shift = _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_SHIFT);
- xkb_mod_mask_t capslock = _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_CAPS);
- xkb_mod_mask_t control = _xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_CTRL);
- xkb_mod_mask_t level3 = _xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_LEVEL3);
- xkb_led_index_t capslock_led_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_CAPS);
- xkb_led_index_t group2_led_idx = _xkb_keymap_led_get_index(keymap, "Group 2");
- xkb_led_mask_t capslock_led = UINT32_C(1) << capslock_led_idx;
- xkb_led_mask_t group2_led = UINT32_C(1) << group2_led_idx;
- const struct test_state_components test_data[] = {
- { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 },
- /*
- * Groups: lock
- */
- #define GROUP_LOCK_ENTRY(group) \
- COMPONENTS_ENTRY(.affect_locked_group = true, .locked_group = (group))
- #define GROUP_LOCK_CHANGES \
- (XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS)
- {
- GROUP_LOCK_ENTRY(1),
- .locked_group=1, .group=1,
- .leds=group2_led,
- .changes=GROUP_LOCK_CHANGES
- },
- {
- KEY_ENTRY(KEY_A, BOTH, XKB_KEY_Cyrillic_ef),
- .locked_group=1, .group=1,
- .leds = group2_led,
- .changes = 0
- },
- {
- GROUP_LOCK_ENTRY(0),
- .locked_group=0, .group=0,
- .leds=0,
- .changes=GROUP_LOCK_CHANGES
- },
- {
- GROUP_LOCK_ENTRY(0),
- .locked_group=0, .group=0,
- .leds=0,
- .changes=0
- },
- {
- GROUP_LOCK_ENTRY(-2),
- .locked_group=0, .group=0, /* Wrapped */
- .leds=0,
- .changes=0
- },
- {
- GROUP_LOCK_ENTRY(-2),
- .locked_group=0, .group=0, /* Wrapped */
- .leds=0,
- .changes=0
- },
- {
- GROUP_LOCK_ENTRY(-1),
- .locked_group=1, .group=1, /* Wrapped */
- .leds=group2_led,
- .changes=GROUP_LOCK_CHANGES
- },
- {
- GROUP_LOCK_ENTRY(-1),
- .locked_group=1, .group=1, /* Wrapped */
- .leds=group2_led,
- .changes=0
- },
- {
- GROUP_LOCK_ENTRY(0),
- .locked_group=0, .group=0,
- .leds=0,
- .changes=GROUP_LOCK_CHANGES
- },
- {
- GROUP_LOCK_ENTRY(1),
- .locked_group=1, .group=1,
- .leds=group2_led,
- .changes=GROUP_LOCK_CHANGES
- },
- {
- GROUP_LOCK_ENTRY(1),
- .locked_group=1, .group=1,
- .leds=group2_led,
- .changes=0
- },
- {
- GROUP_LOCK_ENTRY(2),
- .locked_group=0, .group=0, /* Wrapped */
- .leds=0,
- .changes=GROUP_LOCK_CHANGES
- },
- {
- GROUP_LOCK_ENTRY(2),
- .locked_group=0, .group=0, /* Wrapped */
- .leds=0,
- .changes=0
- },
- /* Invalid group */
- {
- GROUP_LOCK_ENTRY(XKB_MAX_GROUPS),
- .locked_group=0, .group=0,
- .leds=0,
- .changes=0
- },
- /* Previous lock */
- {
- KEY_ENTRY(KEY_COMPOSE, DOWN, XKB_KEY_ISO_Next_Group),
- .locked_group = 1, .group = 1,
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_COMPOSE, UP, XKB_KEY_ISO_Next_Group),
- .locked_group = 1, .group = 1,
- .leds = group2_led,
- .changes = 0
- },
- {
- KEY_ENTRY(KEY_A, BOTH, XKB_KEY_Cyrillic_ef),
- .locked_group=1, .group=1,
- .leds = group2_led,
- .changes = 0
- },
- {
- GROUP_LOCK_ENTRY(0),
- .locked_group=0, .group=0,
- .leds=group2_led,
- .changes=XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 },
- {
- KEY_ENTRY(KEY_COMPOSE, DOWN, XKB_KEY_ISO_Next_Group),
- .locked_group = 1, .group = 1,
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_COMPOSE, UP, XKB_KEY_ISO_Next_Group),
- .locked_group = 1, .group = 1,
- .leds = group2_led,
- .changes = 0
- },
- /*
- * Groups: latch
- */
- #define GROUP_LATCH_ENTRY(group) \
- COMPONENTS_ENTRY(.affect_latched_group = true, .latched_group = (group))
- RESET_STATE,
- {
- KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a),
- .base_group = 0, .latched_group = 0, .locked_group = 0, .group = 0,
- .base_mods = 0, .latched_mods = 0, .locked_mods = 0, .mods = 0,
- .leds = 0,
- .changes = 0
- },
- {
- GROUP_LATCH_ENTRY(1),
- .latched_group=1, .group=1,
- .leds=group2_led,
- .changes=XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_ef),
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 },
- { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .changes = 0 },
- { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 },
- {
- GROUP_LATCH_ENTRY(1),
- .latched_group=1, .group=1,
- .leds=group2_led,
- .changes=XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- GROUP_LATCH_ENTRY(1),
- .latched_group=1, .group=1,
- .leds=group2_led,
- .changes=0
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_ef),
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 },
- { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .changes = 0 },
- { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 },
- /* Invalid group */
- {
- GROUP_LATCH_ENTRY(XKB_MAX_GROUPS),
- .latched_group=XKB_MAX_GROUPS, .group=0,
- .leds=0,
- .changes=XKB_STATE_LAYOUT_LATCHED
- },
- /* Pending latch is cancelled */
- RESET_STATE,
- {
- KEY_ENTRY(KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Group_Latch),
- .latched_group = 1, .group = 1,
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED
- },
- {
- GROUP_LATCH_ENTRY(2),
- .latched_group=2, .group=0,
- .leds = 0,
- .changes=XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .changes = XKB_STATE_LAYOUT_LATCHED },
- /* Pending latch to lock is cancelled */
- RESET_STATE,
- {
- KEY_ENTRY(KEY_RIGHTMETA, BOTH, XKB_KEY_ISO_Group_Latch),
- .latched_group = 1, .group = 1,
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED
- },
- {
- GROUP_LATCH_ENTRY(2),
- .latched_group=2, .group=0,
- .leds = 0,
- .changes=XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a),
- .changes = XKB_STATE_LAYOUT_LATCHED
- },
- /* Broken latch does not unlock if clearLocks is not set */
- RESET_STATE,
- {
- GROUP_LOCK_ENTRY(1),
- .locked_group=1, .group=1,
- .leds=group2_led,
- .changes=XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_SCROLLLOCK, DOWN, XKB_KEY_ISO_Group_Latch),
- .base_group=1, .latched_group=0, .locked_group=1, .group=0,
- .leds=0,
- .changes=XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- /* Breaks latch */
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a),
- .base_group=1, .latched_group=0, .locked_group=1, .group=0,
- .leds=0,
- .changes=0
- },
- {
- KEY_ENTRY(KEY_SCROLLLOCK, UP, XKB_KEY_ISO_Group_Latch),
- .base_group=0, .latched_group=0, .locked_group=1, .group=1,
- .leds=group2_led,
- .changes=XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- /*
- * Groups: latch + lock
- */
- RESET_STATE,
- /* Empty state */
- {
- COMPONENTS_ENTRY(.affect_latched_group = true, .latched_group = 1,
- .affect_locked_group = true, .locked_group = 1),
- .latched_group = 1, .locked_group = 1, .group = 0,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_LOCKED
- },
- /* Pending latch */
- RESET_STATE,
- {
- KEY_ENTRY(KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Group_Latch),
- .latched_group = 1, .group = 1,
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED
- },
- {
- COMPONENTS_ENTRY(.affect_locked_group = true, .locked_group = 1),
- .latched_group = 1, .locked_group = 1, .group = 0,
- .changes = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a),
- .locked_group=1, .group=1,
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS
- },
- /*
- * Modifiers: lock
- */
- #define MOD_LOCK_ENTRY(mask, mods) \
- COMPONENTS_ENTRY(.affect_locked_mods = (mask), .locked_mods = (mods))
- #define UNDEFINED_MODMASK (UINT32_C(1) << (XKB_MAX_MODS - 1))
- RESET_STATE,
- /* Invalid: mod not in the mask */
- { MOD_LOCK_ENTRY(0, capslock), .changes=0 },
- { MOD_LOCK_ENTRY(0, UNDEFINED_MODMASK), .changes=0 },
- /* Set Caps */
- {
- MOD_LOCK_ENTRY(capslock, capslock),
- .locked_mods=capslock, .mods=capslock,
- .leds=capslock_led,
- .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- MOD_LOCK_ENTRY(capslock, capslock),
- .locked_mods=capslock, .mods=capslock, .leds=capslock_led,
- .changes=0
- },
- {
- KEY_ENTRY(KEY_A, BOTH, XKB_KEY_A),
- .locked_mods=capslock, .mods=capslock,
- .leds=capslock_led,
- .changes = 0
- },
- /* Add Control and keep Caps */
- {
- MOD_LOCK_ENTRY(control, control),
- .locked_mods=control | capslock, .mods=control | capslock,
- .leds=capslock_led,
- .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- KEY_ENTRY(KEY_A, BOTH, XKB_KEY_A),
- .locked_mods=control | capslock, .mods=control | capslock,
- .leds=capslock_led,
- .changes = 0
- },
- /* Remove Caps and keep Control */
- {
- MOD_LOCK_ENTRY(capslock, 0),
- .locked_mods=control, .mods=control,
- .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a),
- .locked_mods=control, .mods=control,
- .leds=0,
- .changes = 0
- },
- /* Add Level3 and remove Control */
- {
- MOD_LOCK_ENTRY(level3 | control, level3),
- .locked_mods=level3, .mods=level3,
- .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
- },
- /* Change undefined modifier */
- {
- MOD_LOCK_ENTRY(level3, level3 | UNDEFINED_MODMASK),
- .locked_mods=level3, .mods=level3,
- .changes=0
- },
- {
- MOD_LOCK_ENTRY(level3 | UNDEFINED_MODMASK, level3 | UNDEFINED_MODMASK),
- .locked_mods=level3, .mods=level3,
- .changes=0
- },
- {
- MOD_LOCK_ENTRY(level3 | UNDEFINED_MODMASK, level3),
- .locked_mods=level3, .mods=level3,
- .changes=0
- },
- /* Previous lock */
- RESET_STATE,
- {
- KEY_ENTRY(KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock),
- .locked_mods=capslock, .mods=capslock,
- .leds=capslock_led,
- .changes = XKB_STATE_MODS_DEPRESSED
- },
- {
- MOD_LOCK_ENTRY(level3 | control, level3),
- .locked_mods=capslock | level3, .mods=capslock | level3,
- .leds=capslock_led,
- .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE },
- {
- MOD_LOCK_ENTRY(capslock, 0),
- .locked_mods=level3, .mods=level3,
- .leds=0,
- .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS
- },
- /*
- * Modifiers: latch
- */
- #define MODS_LATCH_ENTRY(mask, mods) \
- COMPONENTS_ENTRY(.affect_latched_mods = (mask), .latched_mods = (mods))
- RESET_STATE,
- { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 },
- /* Invalid: mod not in the mask */
- { MODS_LATCH_ENTRY(0, shift), .changes=0 },
- { MODS_LATCH_ENTRY(0, UNDEFINED_MODMASK), .changes=0 },
- /* Latch Shift */
- {
- MODS_LATCH_ENTRY(shift, shift),
- .latched_mods=shift, .mods=shift,
- .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_A),
- .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 },
- { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 },
- {
- MODS_LATCH_ENTRY(shift, shift),
- .latched_mods=shift, .mods=shift,
- .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- MODS_LATCH_ENTRY(shift, shift),
- .latched_mods=shift, .mods=shift,
- .changes=0
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_A),
- .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 },
- { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 },
- /* Latch Shift, then Caps: latched shift is cancelled */
- {
- MODS_LATCH_ENTRY(shift, shift),
- .latched_mods=shift, .mods=shift,
- .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- MODS_LATCH_ENTRY(capslock, capslock),
- .latched_mods=shift | capslock, .mods=shift | capslock,
- .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a),
- .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 },
- /* Change undefined modifier */
- {
- MODS_LATCH_ENTRY(level3, level3 | UNDEFINED_MODMASK),
- .latched_mods=level3, .mods=level3,
- .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- MODS_LATCH_ENTRY(level3 | UNDEFINED_MODMASK, level3 | UNDEFINED_MODMASK),
- .latched_mods=level3, .mods=level3,
- .changes=0
- },
- {
- MODS_LATCH_ENTRY(level3 | UNDEFINED_MODMASK, level3),
- .latched_mods=level3, .mods=level3,
- .changes=0
- },
- /* Pending latch is *not* cancelled if not in affected mods */
- RESET_STATE,
- {
- KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch),
- .latched_mods=level3, .mods=level3,
- .changes = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED
- },
- {
- MODS_LATCH_ENTRY(shift, shift),
- .latched_mods=shift | level3, .mods=shift | level3,
- .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_A),
- .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- /* Pending latch *is* cancelled if in affected mods */
- RESET_STATE,
- {
- KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch),
- .latched_mods=level3, .mods=level3,
- .changes = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED
- },
- {
- MODS_LATCH_ENTRY(shift | level3, shift),
- .latched_mods=shift, .mods=shift,
- .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_A),
- .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- /* Latch-to-lock */
- RESET_STATE,
- {
- /* Set capslock, to ensure that when *mutating* the latch to a lock,
- * the `priv` field and refcnt fields are set accordingly. */
- MOD_LOCK_ENTRY(capslock, capslock),
- .locked_mods=capslock, .mods=capslock,
- .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch),
- /* Pending latch */
- .base_mods=0, .latched_mods=level3, .locked_mods=capslock, .mods=capslock | level3,
- .changes = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED
- },
- {
- KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch),
- /* Mutate to a lock */
- .base_mods=0, .latched_mods=0, .locked_mods=capslock | level3, .mods=capslock | level3,
- .changes = XKB_STATE_MODS_DEPRESSED
- },
- {
- KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch),
- /* Unlock via latch’s ACTION_LOCK_CLEAR */
- .base_mods=0, .latched_mods=0, .locked_mods=capslock, .mods=capslock,
- .changes = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
- },
- /* Broken latch does not unlock if clearLocks is not set */
- RESET_STATE,
- {
- /* Set capslock, to ensure that when *mutating* the latch to a lock,
- * the `priv` field and refcnt fields are set accordingly. */
- MOD_LOCK_ENTRY(level3, level3),
- .locked_mods=level3, .mods=level3,
- .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- KEY_ENTRY(KEY_BACKSLASH, DOWN, XKB_KEY_ISO_Level3_Latch),
- .base_mods=level3, .latched_mods=0, .locked_mods=level3, .mods=level3,
- .changes = XKB_STATE_MODS_DEPRESSED
- },
- {
- /* Breaks latch */
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a),
- .base_mods=level3, .latched_mods=0, .locked_mods=level3, .mods=level3,
- .changes = 0
- },
- {
- KEY_ENTRY(KEY_BACKSLASH, UP, XKB_KEY_ISO_Level3_Latch),
- .base_mods=0, .latched_mods=0, .locked_mods=level3, .mods=level3,
- .changes = XKB_STATE_MODS_DEPRESSED
- },
- // TODO
- /*
- * Modifiers: latched + locked
- */
- RESET_STATE,
- {
- COMPONENTS_ENTRY(.affect_latched_mods = shift, .latched_mods = shift,
- .affect_locked_mods = level3, .locked_mods = level3),
- .latched_mods = shift, .locked_mods = level3, .mods = shift | level3,
- .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED |
- XKB_STATE_MODS_EFFECTIVE
- },
- // TODO
- /*
- * Mix
- */
- /* Lock mods & groups */
- RESET_STATE,
- {
- COMPONENTS_ENTRY(.affect_locked_group=true, .locked_group=1,
- .affect_locked_mods=control, .locked_mods=control),
- .locked_group=1, .group=1,
- .locked_mods=control, .mods=control,
- .leds=group2_led,
- .changes = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE |
- XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS
- },
- /* When updating latches, mod/group changes should not affect each other */
- RESET_STATE,
- {
- COMPONENTS_ENTRY(.affect_latched_group=true, .latched_group=1,
- .affect_latched_mods=control, .latched_mods=control),
- .latched_group=1, .group=1,
- .latched_mods=control, .mods=control,
- .leds=group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE |
- XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_ef),
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS |
- XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- RESET_STATE,
- {
- KEY_ENTRY(KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Group_Latch),
- .latched_group = 1, .group = 1,
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED
- },
- /* Pending group latch */
- { COMPONENTS_ENTRY(.affect_latched_mods=shift, .latched_mods=shift),
- .latched_group=1, .group=1,
- .latched_mods=shift, .mods=shift,
- .leds = group2_led,
- .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_EF),
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE |
- XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS
- },
- {
- KEY_ENTRY(KEY_RIGHTMETA, BOTH, XKB_KEY_ISO_Group_Latch),
- .latched_group = 1, .group = 1,
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED
- },
- /* Pending group latch (with latch to lock + clear) */
- {
- COMPONENTS_ENTRY(.affect_latched_mods=shift, .latched_mods=shift),
- .latched_group=1, .group=1,
- .latched_mods=shift, .mods=shift,
- .leds = group2_led,
- .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE
- },
- {
- KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_EF),
- .leds = group2_led,
- .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE |
- XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS
- },
- // TODO
- };
- for (size_t k = 0; k < ARRAY_SIZE(test_data); k++) {
- assert_printf(
- run_state_update(keymap, &test_data[k], &expected, &state),
- "%s #%zu: type: %d\n",
- __func__, k, test_data[k].input_type
- );
- }
- xkb_state_unref(expected);
- xkb_state_unref(state);
- #undef COMPONENTS_ENTRY
- }
- struct test_active_mods_entry {
- xkb_mod_mask_t state;
- xkb_mod_mask_t active;
- };
- static void
- test_serialisation(struct xkb_keymap *keymap, bool pure_vmods)
- {
- struct xkb_state *state = xkb_state_new(keymap);
- xkb_mod_mask_t base_mods;
- xkb_mod_mask_t latched_mods;
- xkb_mod_mask_t locked_mods;
- xkb_mod_mask_t effective_mods;
- xkb_layout_index_t base_group = 0;
- xkb_layout_index_t latched_group = 0;
- xkb_layout_index_t locked_group = 0;
- assert(state);
- xkb_mod_index_t shiftIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
- xkb_mod_index_t capsIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
- xkb_mod_index_t ctrlIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
- xkb_mod_index_t mod1Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1);
- xkb_mod_index_t mod2Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD2);
- xkb_mod_index_t mod3Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD3);
- xkb_mod_index_t mod4Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD4);
- xkb_mod_index_t mod5Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD5);
- xkb_mod_index_t altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT);
- xkb_mod_index_t metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META);
- xkb_mod_index_t superIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SUPER);
- xkb_mod_index_t hyperIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_HYPER);
- xkb_mod_index_t numIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_NUM);
- xkb_mod_index_t level3Idx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_LEVEL3);
- xkb_mod_index_t altGrIdx = _xkb_keymap_mod_get_index(keymap, "AltGr");
- xkb_mod_mask_t shift = (UINT32_C(1) << shiftIdx);
- xkb_mod_mask_t caps = (UINT32_C(1) << capsIdx);
- xkb_mod_mask_t ctrl = (UINT32_C(1) << ctrlIdx);
- xkb_mod_mask_t mod1 = (UINT32_C(1) << mod1Idx);
- xkb_mod_mask_t mod2 = (UINT32_C(1) << mod2Idx);
- xkb_mod_mask_t mod3 = (UINT32_C(1) << mod3Idx);
- xkb_mod_mask_t mod4 = (UINT32_C(1) << mod4Idx);
- xkb_mod_mask_t mod5 = (UINT32_C(1) << mod5Idx);
- xkb_mod_mask_t alt = (UINT32_C(1) << altIdx);
- xkb_mod_mask_t meta = (UINT32_C(1) << metaIdx);
- xkb_mod_mask_t super = (UINT32_C(1) << superIdx);
- xkb_mod_mask_t hyper = (UINT32_C(1) << hyperIdx);
- xkb_mod_mask_t num = (UINT32_C(1) << numIdx);
- xkb_mod_mask_t level3 = (UINT32_C(1) << level3Idx);
- xkb_mod_mask_t altGr = (UINT32_C(1) << altGrIdx);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
- assert(base_mods == 0);
- latched_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
- assert(latched_mods == 0);
- locked_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED);
- assert(locked_mods == caps);
- effective_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
- assert(effective_mods == locked_mods);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
- assert(base_mods == shift);
- latched_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
- assert(latched_mods == 0);
- locked_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED);
- assert(locked_mods == caps);
- effective_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
- assert(effective_mods == (base_mods | locked_mods));
- base_mods |= ctrl;
- xkb_state_update_mask(state, base_mods, latched_mods, locked_mods,
- base_group, latched_group, locked_group);
- assert(xkb_state_mod_index_is_active(state, ctrlIdx, XKB_STATE_MODS_DEPRESSED) > 0);
- assert(xkb_state_mod_index_is_active(state, ctrlIdx, XKB_STATE_MODS_EFFECTIVE) > 0);
- const struct test_active_mods_entry test_data_real[] = {
- { .state = 0, .active = 0 },
- { .state = shift, .active = shift },
- { .state = caps, .active = caps },
- { .state = ctrl, .active = ctrl },
- { .state = mod1, .active = mod1 | alt | meta },
- { .state = mod2, .active = mod2 | num },
- { .state = mod3, .active = mod3 },
- { .state = mod4, .active = mod4 | super | hyper },
- { .state = mod5, .active = mod5 | level3 | altGr },
- { .state = shift | mod1, .active = shift | mod1 | alt | meta },
- { .state = shift | mod2, .active = shift | mod2 | num },
- };
- const struct test_active_mods_entry test_data_virtual[] = {
- { .state = 0, .active = 0 },
- { .state = shift, .active = shift },
- { .state = caps, .active = caps },
- { .state = ctrl, .active = ctrl },
- { .state = mod1, .active = mod1 },
- { .state = mod2, .active = mod2 },
- { .state = mod3, .active = mod3 },
- { .state = mod4, .active = mod4 },
- { .state = mod5, .active = mod5 },
- { .state = alt, .active = alt },
- { .state = meta, .active = meta },
- { .state = super, .active = super },
- { .state = hyper, .active = hyper },
- { .state = num, .active = num },
- { .state = level3, .active = level3 },
- { .state = shift | mod1, .active = shift | mod1 },
- { .state = mod1 | alt, .active = mod1 | alt },
- { .state = alt | meta, .active = alt | meta },
- { .state = alt | level3, .active = alt | level3 },
- };
- const struct test_active_mods_entry *test_data = pure_vmods
- ? test_data_virtual
- : test_data_real;
- unsigned int k_max = pure_vmods
- ? ARRAY_SIZE(test_data_virtual)
- : ARRAY_SIZE(test_data_real);
- for (unsigned int k = 0; k < k_max; k++) {
- const struct test_active_mods_entry *entry = &test_data[k];
- #define check_mods(keymap, state_, entry, type) \
- for (xkb_mod_index_t idx = 0; idx < xkb_keymap_num_mods(keymap); idx++) { \
- xkb_mod_mask_t mask = UINT32_C(1) << idx; \
- fprintf(stderr, "#%u State %#"PRIx32", mod: %s (%"PRIu32")\n", \
- k, (entry)->state, xkb_keymap_mod_get_name(keymap, idx), idx); \
- { \
- xkb_mod_mask_t expected = mod_mask_get_effective(keymap, \
- (entry)->state); \
- xkb_mod_mask_t got = xkb_state_serialize_mods(state, type); \
- assert_printf(got == expected, \
- "xkb_state_serialize_mods, " STRINGIFY2(type) \
- ", expected %#"PRIx32", got %#"PRIx32"\n", \
- expected, got); \
- } \
- bool expected = !!(mask & (entry)->active); \
- bool got = !!xkb_state_mod_index_is_active(state_, idx, type); \
- assert_printf(got == expected, \
- "xkb_state_mod_index_is_active, " STRINGIFY2(type) "\n"); \
- got = !!xkb_state_mod_index_is_active(state_, idx, \
- XKB_STATE_MODS_EFFECTIVE); \
- assert_printf(got == expected, "xkb_state_mod_index_is_active, " \
- STRINGIFY2(XKB_STATE_MODS_EFFECTIVE) "\n"); \
- got = !!xkb_state_mod_indices_are_active( \
- state_, type, \
- XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE, \
- idx, XKB_MOD_INVALID); \
- assert_printf(got == expected, "xkb_state_mod_indices_are_active, " \
- STRINGIFY2(type) "\n"); \
- got = !!xkb_state_mod_indices_are_active( \
- state_, XKB_STATE_MODS_EFFECTIVE, \
- XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE, \
- idx, XKB_MOD_INVALID); \
- assert_printf(got == expected, "xkb_state_mod_indices_are_active, " \
- STRINGIFY2(XKB_STATE_MODS_EFFECTIVE) "\n"); \
- }
- xkb_state_update_mask(state, entry->state, 0, 0, 0, 0, 0);
- check_mods(keymap, state, entry, XKB_STATE_MODS_DEPRESSED);
- xkb_state_update_mask(state, 0, entry->state, 0, 0, 0, 0);
- check_mods(keymap, state, entry, XKB_STATE_MODS_LATCHED);
- xkb_state_update_mask(state, 0, 0, entry->state, 0, 0, 0);
- check_mods(keymap, state, entry, XKB_STATE_MODS_LOCKED);
- }
- xkb_state_unref(state);
- }
- static inline xkb_mod_mask_t
- canonical_mask(bool is_pure, xkb_mod_mask_t virtual, xkb_mod_mask_t real)
- {
- return is_pure ? virtual : real;
- }
- static void
- test_update_mask_mods(struct xkb_keymap *keymap, bool pure_vmods)
- {
- enum xkb_state_component changed;
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- xkb_mod_index_t capsIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
- xkb_mod_index_t shiftIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
- xkb_mod_index_t mod1Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1);
- xkb_mod_index_t mod2Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD2);
- xkb_mod_index_t altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT);
- xkb_mod_index_t metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META);
- xkb_mod_index_t numIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_NUM);
- xkb_mod_mask_t caps = (UINT32_C(1) << capsIdx);
- xkb_mod_mask_t shift = (UINT32_C(1) << shiftIdx);
- xkb_mod_mask_t mod1 = (UINT32_C(1) << mod1Idx);
- xkb_mod_mask_t mod2 = (UINT32_C(1) << mod2Idx);
- xkb_mod_mask_t alt = (UINT32_C(1) << altIdx);
- xkb_mod_mask_t meta = (UINT32_C(1) << metaIdx);
- xkb_mod_mask_t num = (UINT32_C(1) << numIdx);
- changed = xkb_state_update_mask(state, caps, 0, 0, 0, 0, 0);
- assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == caps);
- changed = xkb_state_update_mask(state, caps, 0, shift, 0, 0, 0);
- assert(changed == (XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE |
- XKB_STATE_LEDS));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) ==
- (caps | shift));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED) == caps);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == shift);
- changed = xkb_state_update_mask(state, 0, 0, 0, 0, 0, 0);
- assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED |
- XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0);
- changed = xkb_state_update_mask(state, alt, 0, 0, 0, 0, 0);
- assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) ==
- canonical_mask(pure_vmods, alt, mod1));
- changed = xkb_state_update_mask(state, meta, 0, 0, 0, 0, 0);
- assert(changed == (pure_vmods
- ? (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE)
- : 0 /* Same canonical modifier state */));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) ==
- canonical_mask(pure_vmods, meta, mod1));
- changed = xkb_state_update_mask(state, 0, 0, num, 0, 0, 0);
- assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED |
- XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) ==
- canonical_mask(pure_vmods, num, mod2));
- xkb_state_update_mask(state, 0, 0, 0, 0, 0, 0);
- changed = xkb_state_update_mask(state, mod2, 0, num, 0, 0, 0);
- assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED |
- XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) ==
- canonical_mask(pure_vmods, mod2 | num, mod2));
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED) == mod2);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) ==
- canonical_mask(pure_vmods, num, mod2));
- xkb_state_unref(state);
- }
- static void
- test_repeat(struct xkb_keymap *keymap)
- {
- assert(!xkb_keymap_key_repeats(keymap, KEY_LEFTSHIFT + EVDEV_OFFSET));
- assert(xkb_keymap_key_repeats(keymap, KEY_A + EVDEV_OFFSET));
- assert(xkb_keymap_key_repeats(keymap, KEY_8 + EVDEV_OFFSET));
- assert(xkb_keymap_key_repeats(keymap, KEY_DOWN + EVDEV_OFFSET));
- assert(xkb_keymap_key_repeats(keymap, KEY_KBDILLUMDOWN + EVDEV_OFFSET));
- }
- static void
- test_consume(struct xkb_keymap *keymap, bool pure_vmods)
- {
- xkb_mod_mask_t mask;
- xkb_mod_index_t shiftIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
- xkb_mod_index_t capsIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
- xkb_mod_index_t ctrlIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
- xkb_mod_index_t mod1Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1);
- xkb_mod_index_t mod2Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD2);
- xkb_mod_index_t mod5Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD5);
- xkb_mod_index_t altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT);
- xkb_mod_index_t metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META);
- xkb_mod_index_t numIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_NUM);
- xkb_mod_index_t level3Idx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_LEVEL3);
- xkb_mod_mask_t caps = (UINT32_C(1) << capsIdx);
- xkb_mod_mask_t shift = (UINT32_C(1) << shiftIdx);
- xkb_mod_mask_t ctrl = (UINT32_C(1) << ctrlIdx);
- xkb_mod_mask_t mod1 = (UINT32_C(1) << mod1Idx);
- xkb_mod_mask_t mod2 = (UINT32_C(1) << mod2Idx);
- xkb_mod_mask_t mod5 = (UINT32_C(1) << mod5Idx);
- xkb_mod_mask_t alt = (UINT32_C(1) << altIdx);
- xkb_mod_mask_t meta = (UINT32_C(1) << metaIdx);
- xkb_mod_mask_t num = (UINT32_C(1) << numIdx);
- xkb_mod_mask_t level3 = (UINT32_C(1) << level3Idx);
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- /* Test remove_consumed() */
- xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_EQUAL + EVDEV_OFFSET, XKB_KEY_DOWN);
- fprintf(stderr, "dumping state for Alt-Shift-+\n");
- print_state(state);
- mask = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
- assert(mask == (canonical_mask(pure_vmods, alt, mod1) | shift));
- mask = xkb_state_mod_mask_remove_consumed(state, KEY_EQUAL + EVDEV_OFFSET,
- mask);
- assert(mask == canonical_mask(pure_vmods, alt, mod1));
- /* Test get_consumed_mods() */
- mask = xkb_state_key_get_consumed_mods(state, KEY_EQUAL + EVDEV_OFFSET);
- assert(mask == shift);
- mask = xkb_state_key_get_consumed_mods(state, KEY_ESC + EVDEV_OFFSET);
- assert(mask == 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_EQUAL + EVDEV_OFFSET, shiftIdx) > 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_EQUAL + EVDEV_OFFSET, mod1Idx) == 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_EQUAL + EVDEV_OFFSET, altIdx) == 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_EQUAL + EVDEV_OFFSET, metaIdx) == 0);
- xkb_state_unref(state);
- /* Test is_consumed() - simple ALPHABETIC type. */
- state = xkb_state_new(keymap);
- assert(state);
- mask = xkb_state_key_get_consumed_mods(state, KEY_A + EVDEV_OFFSET);
- assert(mask == (shift | caps));
- assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, capsIdx) > 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shiftIdx) > 0);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, capsIdx) > 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shiftIdx) > 0);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, capsIdx) > 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shiftIdx) > 0);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, capsIdx) > 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shiftIdx) > 0);
- xkb_state_unref(state);
- /* More complicated - CTRL+ALT */
- state = xkb_state_new(keymap);
- assert(state);
- mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET);
- assert(mask == (shift | canonical_mask(pure_vmods, alt, mod1) |
- ctrl | canonical_mask(pure_vmods, level3, mod5)));
- /* Shift is preserved. */
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET);
- assert(mask == (canonical_mask(pure_vmods, alt, mod1) | ctrl |
- canonical_mask(pure_vmods, level3, mod5)));
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET);
- assert(mask == (shift | canonical_mask(pure_vmods, alt, mod1) |
- ctrl | canonical_mask(pure_vmods, level3, mod5)));
- xkb_state_unref(state);
- /* Test XKB_CONSUMED_MODE_GTK, CTRL+ALT */
- state = xkb_state_new(keymap);
- assert(state);
- mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET,
- XKB_CONSUMED_MODE_GTK);
- assert(mask == 0);
- xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN);
- mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET,
- XKB_CONSUMED_MODE_GTK);
- assert(mask == 0);
- xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN);
- mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET,
- XKB_CONSUMED_MODE_GTK);
- assert(mask == (canonical_mask(pure_vmods, alt, mod1) | ctrl));
- assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, shiftIdx) > 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, ctrlIdx) > 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, altIdx) > 0);
- if (pure_vmods) {
- assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, mod1Idx) == 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, metaIdx) == 0);
- } else {
- assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, mod1Idx) > 0);
- assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, metaIdx) > 0);
- }
- mask = ctrl | canonical_mask(pure_vmods, alt, mod1) |
- canonical_mask(pure_vmods, num, mod2);
- mask = xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, mask);
- assert(mask == canonical_mask(pure_vmods, num, mod2));
- mask = ctrl | alt | canonical_mask(pure_vmods, alt, meta) |
- canonical_mask(pure_vmods, num, mod2);
- mask = xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, mask);
- assert(mask == canonical_mask(pure_vmods, num, mod2));
- xkb_state_unref(state);
- /* Test XKB_CONSUMED_MODE_GTK, Simple Shift */
- state = xkb_state_new(keymap);
- assert(state);
- mask = xkb_state_key_get_consumed_mods2(state, KEY_A + EVDEV_OFFSET,
- XKB_CONSUMED_MODE_GTK);
- assert(mask == (shift | caps));
- xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN);
- mask = xkb_state_key_get_consumed_mods2(state, KEY_A + EVDEV_OFFSET,
- XKB_CONSUMED_MODE_GTK);
- assert(mask == (shift | caps));
- xkb_state_unref(state);
- }
- static void
- test_overlapping_mods(struct xkb_context *context)
- {
- struct xkb_keymap *keymap;
- struct xkb_state *state;
- /* Super and Hyper are overlapping (full overlap) */
- keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
- NULL, "us", NULL,
- "overlapping_modifiers:super_hyper,"
- "grp:win_space_toggle");
- assert(keymap);
- xkb_mod_index_t shiftIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
- xkb_mod_index_t capsIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
- xkb_mod_index_t ctrlIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
- xkb_mod_index_t mod1Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1);
- xkb_mod_index_t mod3Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD3);
- xkb_mod_index_t mod4Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD4);
- xkb_mod_index_t mod5Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD5);
- xkb_mod_index_t altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT);
- xkb_mod_index_t metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META);
- xkb_mod_index_t superIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SUPER);
- xkb_mod_index_t hyperIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_HYPER);
- /* Note: not mapped */
- xkb_mod_index_t scrollIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SCROLL);
- xkb_mod_mask_t shift = (UINT32_C(1) << shiftIdx);
- xkb_mod_mask_t ctrl = (UINT32_C(1) << ctrlIdx);
- xkb_mod_mask_t mod1 = (UINT32_C(1) << mod1Idx);
- xkb_mod_mask_t mod3 = (UINT32_C(1) << mod3Idx);
- xkb_mod_mask_t mod4 = (UINT32_C(1) << mod4Idx);
- xkb_mod_mask_t mod5 = (UINT32_C(1) << mod5Idx);
- xkb_mod_mask_t alt = (UINT32_C(1) << altIdx);
- xkb_mod_mask_t meta = (UINT32_C(1) << metaIdx);
- xkb_mod_mask_t super = (UINT32_C(1) << superIdx);
- xkb_mod_mask_t hyper = (UINT32_C(1) << hyperIdx);
- state = xkb_state_new(keymap);
- assert(state);
- const struct test_active_mods_entry test_data1[] = {
- { .state = 0, .active = 0 },
- { .state = mod1, .active = mod1 | alt | meta },
- { .state = mod3, .active = mod3 },
- { .state = mod4, .active = mod4 },
- { .state = alt, .active = mod1 | alt | meta },
- { .state = meta, .active = mod1 | alt | meta },
- { .state = super, .active = mod3 | mod4 | super | hyper },
- { .state = hyper, .active = mod3 | mod4 | super | hyper },
- { .state = mod3 | mod4, .active = mod3 | mod4 | super | hyper },
- };
- for (unsigned int k = 0; k < ARRAY_SIZE(test_data1); k++) {
- const struct test_active_mods_entry *entry = &test_data1[k];
- xkb_state_update_mask(state, entry->state, 0, 0, 0, 0, 0);
- check_mods(keymap, state, entry, XKB_STATE_MODS_DEPRESSED);
- }
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == (mod3 | mod4));
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ANY,
- mod3Idx, mod4Idx, superIdx, hyperIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ALL,
- mod3Idx, mod4Idx, superIdx, hyperIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) ==
- (shift | ctrl | mod1 | mod5));
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (mod1 | mod4 | mod5)) == mod4);
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (alt | super)) == (mod3 | mod4));
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, scrollIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_key_get_consumed_mods2(state, KEY_SPACE + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) == mod4);
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_SPACE + EVDEV_OFFSET, (mod3 | mod4)) == mod3);
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_SPACE + EVDEV_OFFSET, (super | hyper)) == mod3);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, scrollIdx, XKB_CONSUMED_MODE_XKB) == 0);
- xkb_state_update_mask(state, mod4, 0, 0, 0, 0, 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, scrollIdx, XKB_CONSUMED_MODE_XKB) == 0);
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- /* Super and Hyper are overlapping (full overlap).
- * Alt overlaps with Meta (incomplete overlap) */
- keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
- NULL, "us", NULL,
- "overlapping_modifiers:meta,"
- "grp:win_space_toggle");
- assert(keymap);
- altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT);
- metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META);
- superIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SUPER);
- hyperIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_HYPER);
- alt = (UINT32_C(1) << altIdx);
- meta = (UINT32_C(1) << metaIdx);
- super = (UINT32_C(1) << superIdx);
- hyper = (UINT32_C(1) << hyperIdx);
- state = xkb_state_new(keymap);
- assert(state);
- const struct test_active_mods_entry test_data2[] = {
- { .state = 0, .active = 0 },
- { .state = mod1, .active = mod1 | alt },
- { .state = mod3, .active = mod3 },
- { .state = mod4, .active = mod4 | hyper | super },
- { .state = alt, .active = mod1 | alt },
- { .state = meta, .active = mod1 | mod3 | alt | meta },
- { .state = super, .active = mod4 | hyper | super },
- { .state = hyper, .active = mod4 | hyper | super },
- { .state = mod1 | mod3, .active = mod1 | mod3 | alt | meta },
- { .state = mod1 | mod4, .active = mod1 | mod4 | alt | super | hyper },
- { .state = mod3 | mod4, .active = mod3 | mod4 | super | hyper },
- { .state = mod1 | mod3 | mod4, .active = mod1 | mod3 | mod4 | alt | meta | super | hyper },
- };
- for (unsigned int k = 0; k < ARRAY_SIZE(test_data2); k++) {
- const struct test_active_mods_entry *entry = &test_data2[k];
- xkb_state_update_mask(state, entry->state, 0, 0, 0, 0, 0);
- check_mods(keymap, state, entry, XKB_STATE_MODS_DEPRESSED);
- }
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ANY,
- mod1Idx, mod3Idx, mod4Idx, altIdx,
- metaIdx, superIdx, hyperIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ALL,
- mod1Idx, mod3Idx, mod4Idx, altIdx,
- metaIdx, superIdx, hyperIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) ==
- (shift | ctrl | mod1 | mod5));
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (mod1 | mod4 | mod5)) == mod4);
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (alt | super)) == mod4);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_key_get_consumed_mods2(state, KEY_SPACE + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) ==
- mod4);
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_SPACE + EVDEV_OFFSET, (mod3 | mod4)) == mod3);
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_SPACE + EVDEV_OFFSET, (super | hyper)) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) > 0);
- xkb_state_update_mask(state, mod1, 0, 0, 0, 0, 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ANY,
- mod1Idx, altIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ALL,
- mod1Idx, altIdx,
- XKB_MOD_INVALID) > 0);
- xkb_state_update_mask(state, mod1 | mod3, 0, 0, 0, 0, 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ANY,
- mod1Idx, mod3Idx, altIdx, metaIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ALL,
- mod1Idx, mod3Idx, altIdx, metaIdx,
- XKB_MOD_INVALID) > 0);
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- /* Super and Hyper overlaps with Meta; Alt overlaps with Meta */
- keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev",
- NULL, "us", NULL,
- "overlapping_modifiers:super_hyper,"
- "overlapping_modifiers:meta");
- assert(keymap);
- altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT);
- metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META);
- superIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SUPER);
- hyperIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_HYPER);
- alt = (UINT32_C(1) << altIdx);
- meta = (UINT32_C(1) << metaIdx);
- super = (UINT32_C(1) << superIdx);
- hyper = (UINT32_C(1) << hyperIdx);
- state = xkb_state_new(keymap);
- assert(state);
- const struct test_active_mods_entry test_data3[] = {
- { .state = 0, .active = 0 },
- { .state = mod1, .active = mod1 | alt },
- { .state = mod3, .active = mod3 },
- { .state = mod4, .active = mod4 },
- { .state = alt, .active = mod1 | alt },
- { .state = meta, .active = mod1 | mod3 | alt | meta },
- { .state = super, .active = mod3 | mod4 | super | hyper },
- { .state = hyper, .active = mod3 | mod4 | super | hyper },
- { .state = mod1 | mod3, .active = mod1 | mod3 | alt | meta },
- { .state = mod1 | mod3, .active = mod1 | mod3 | alt | meta },
- { .state = mod1 | mod4, .active = mod1 | mod4 | alt },
- { .state = mod3 | mod4, .active = mod3 | mod4 | super | hyper },
- { .state = mod1 | mod3 | mod4, .active = mod1 | mod3 | mod4 | alt | meta | super | hyper },
- };
- for (unsigned int k = 0; k < ARRAY_SIZE(test_data3); k++) {
- const struct test_active_mods_entry *entry = &test_data3[k];
- xkb_state_update_mask(state, entry->state, 0, 0, 0, 0, 0);
- check_mods(keymap, state, entry, XKB_STATE_MODS_DEPRESSED);
- }
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ANY,
- mod1Idx, mod3Idx, mod4Idx, altIdx,
- metaIdx, superIdx, hyperIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ALL,
- mod1Idx, mod3Idx, mod4Idx, altIdx,
- metaIdx, superIdx, hyperIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) ==
- (shift | ctrl | mod1 | mod5));
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (mod1 | mod4 | mod5)) == mod4);
- assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (alt | super)) == (mod3 | mod4));
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) > 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0);
- assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0);
- xkb_state_update_mask(state, mod1 | mod3, 0, 0, 0, 0, 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ANY,
- mod1Idx, mod3Idx, altIdx, metaIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ALL,
- mod1Idx, mod3Idx, altIdx, metaIdx,
- XKB_MOD_INVALID) > 0);
- xkb_state_update_mask(state, mod1 | mod4, 0, 0, 0, 0, 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ANY,
- mod1Idx, mod4Idx, altIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ALL,
- mod1Idx, mod4Idx, altIdx,
- XKB_MOD_INVALID) > 0);
- xkb_state_update_mask(state, mod3 | mod4, 0, 0, 0, 0, 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ANY,
- mod3Idx, mod4Idx, superIdx, hyperIdx,
- XKB_MOD_INVALID) > 0);
- assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE,
- XKB_STATE_MATCH_ALL,
- mod3Idx, mod4Idx, superIdx, hyperIdx,
- XKB_MOD_INVALID) > 0);
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }
- static void
- test_inactive_key_type_entry(struct xkb_context *context)
- {
- const char keymap_str[] =
- "xkb_keymap {\n"
- " xkb_keycodes {\n"
- " <a> = 38;\n"
- " <leftshift> = 50;\n"
- " };\n"
- " xkb_types {\n"
- " virtual_modifiers Bound = Shift, Unbound;\n"
- " type \"X\" {\n"
- " modifiers = Bound+Unbound;\n"
- /* This entry should be ignored because it has an unbound modifier */
- " map[Bound+Unbound] = Level1;\n"
- " map[Bound] = Level2;\n"
- " };\n"
- " };\n"
- " xkb_symbols {\n"
- " key <a> { [ a, A ], type = \"X\" };\n"
- " key <leftshift> { [ SetMods(mods = Shift) ] };\n"
- " };\n"
- "};";
- struct xkb_keymap *keymap =
- test_compile_buffer(context, XKB_KEYMAP_FORMAT_TEXT_V1,
- keymap_str, sizeof(keymap_str));
- assert(keymap);
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- const xkb_mod_mask_t shift = (UINT32_C(1) << XKB_MOD_INDEX_SHIFT);
- assert(xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET) == XKB_KEY_a);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == shift);
- assert(xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET) == XKB_KEY_A);
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }
- static void
- key_iter(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
- {
- xkb_keycode_t *counter = data;
- assert(*counter == key);
- (*counter)++;
- }
- static void
- test_keycode_range(struct xkb_keymap *keymap)
- {
- xkb_keycode_t counter;
- assert(xkb_keymap_min_keycode(keymap) == 9);
- assert(xkb_keymap_max_keycode(keymap) == 569);
- counter = xkb_keymap_min_keycode(keymap);
- xkb_keymap_key_for_each(keymap, key_iter, &counter);
- assert(counter == xkb_keymap_max_keycode(keymap) + 1);
- }
- static void
- test_caps_keysym_transformation(struct xkb_context *context)
- {
- int nsyms;
- xkb_keysym_t sym;
- const xkb_keysym_t *syms;
- const char keymap_str[] =
- "xkb_keymap {\n"
- " xkb_keycodes { include \"evdev\" };\n"
- " xkb_compat { include \"basic\" };\n"
- " xkb_types { include \"complete\" };\n"
- " xkb_symbols {\n"
- " include \"pc+ch(fr)\"\n"
- " key <AE13> { [{oe, ssharp}, {ae, s, s}] };"
- " key <AB11> { [{3, ntilde}] };"
- " replace key <RCTL> { [{Control_R, ISO_Next_Group}] };"
- " };"
- "};";
- struct xkb_keymap* const keymap =
- test_compile_buffer(context, XKB_KEYMAP_FORMAT_TEXT_V1,
- keymap_str, sizeof(keymap_str));
- assert(keymap);
- xkb_mod_index_t shift = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
- xkb_mod_index_t caps = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- /* See xkb_state_key_get_one_sym() for what's this all about. */
- assert(xkb_state_key_get_layout(state, KEY_A + EVDEV_OFFSET) == 0);
- assert(xkb_state_key_get_layout(state, KEY_SEMICOLON + EVDEV_OFFSET) == 0);
- /* Without caps, no transformation. */
- assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) == 0);
- assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0);
- assert(xkb_state_key_get_level(state, KEY_A + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET);
- assert(sym == XKB_KEY_a);
- assert(xkb_state_key_get_level(state, KEY_SEMICOLON + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + EVDEV_OFFSET);
- assert(sym == XKB_KEY_eacute);
- nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + EVDEV_OFFSET, &syms);
- assert(nsyms == 1 && syms[0] == XKB_KEY_eacute);
- assert(xkb_state_key_get_level(state, KEY_YEN + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_YEN + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_YEN + EVDEV_OFFSET, &syms);
- assert(nsyms == 2 && syms[0] == XKB_KEY_oe && syms[1] == XKB_KEY_ssharp);
- assert(xkb_state_key_get_level(state, KEY_RO + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_RO + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_RO + EVDEV_OFFSET, &syms);
- assert(nsyms == 2 && syms[0] == XKB_KEY_3 && syms[1] == XKB_KEY_ntilde);
- assert(xkb_state_key_get_level(state, KEY_RIGHTCTRL + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_RIGHTCTRL + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_RIGHTCTRL + EVDEV_OFFSET, &syms);
- assert(nsyms == 2 && syms[0] == XKB_KEY_Control_R && syms[1] == XKB_KEY_ISO_Next_Group);
- /* With shift, no transformation (only different level). */
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) == 0);
- assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) > 0);
- assert(xkb_state_key_get_level(state, KEY_A + EVDEV_OFFSET, 0) == 1);
- sym = xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET);
- assert(sym == XKB_KEY_A);
- sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + EVDEV_OFFSET);
- assert(sym == XKB_KEY_odiaeresis);
- nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + EVDEV_OFFSET, &syms);
- assert(nsyms == 1 && syms[0] == XKB_KEY_odiaeresis);
- assert(xkb_state_key_get_level(state, KEY_YEN + EVDEV_OFFSET, 0) == 1);
- sym = xkb_state_key_get_one_sym(state, KEY_YEN + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_YEN + EVDEV_OFFSET, &syms);
- assert(nsyms == 3 && syms[0] == XKB_KEY_ae && syms[1] == XKB_KEY_s && syms[2] == XKB_KEY_s);
- assert(xkb_state_key_get_level(state, KEY_RO + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_RO + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_RO + EVDEV_OFFSET, &syms);
- assert(nsyms == 2 && syms[0] == XKB_KEY_3 && syms[1] == XKB_KEY_ntilde);
- assert(xkb_state_key_get_level(state, KEY_RIGHTCTRL + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_RIGHTCTRL + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_RIGHTCTRL + EVDEV_OFFSET, &syms);
- assert(nsyms == 2 && syms[0] == XKB_KEY_Control_R && syms[1] == XKB_KEY_ISO_Next_Group);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0);
- /* With caps, transform in same level. */
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0);
- assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0);
- assert(xkb_state_key_get_level(state, KEY_A + EVDEV_OFFSET, 0) == 1);
- sym = xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET);
- assert(sym == XKB_KEY_A);
- assert(xkb_state_key_get_level(state, KEY_SEMICOLON + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + EVDEV_OFFSET);
- assert(sym == XKB_KEY_Eacute);
- nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + EVDEV_OFFSET, &syms);
- assert(nsyms == 1 && syms[0] == XKB_KEY_Eacute);
- assert(xkb_state_key_get_level(state, KEY_YEN + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_YEN + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_YEN + EVDEV_OFFSET, &syms);
- assert(nsyms == 2 && syms[0] == XKB_KEY_OE && syms[1] == XKB_KEY_SSHARP);
- assert(xkb_state_key_get_level(state, KEY_RO + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_RO + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_RO + EVDEV_OFFSET, &syms);
- assert(nsyms == 2 && syms[0] == XKB_KEY_3 && syms[1] == XKB_KEY_Ntilde);
- assert(xkb_state_key_get_level(state, KEY_RIGHTCTRL + EVDEV_OFFSET, 0) == 0);
- sym = xkb_state_key_get_one_sym(state, KEY_RIGHTCTRL + EVDEV_OFFSET);
- assert(sym == XKB_KEY_NoSymbol);
- nsyms = xkb_state_key_get_syms(state, KEY_RIGHTCTRL + EVDEV_OFFSET, &syms);
- assert(nsyms == 2 && syms[0] == XKB_KEY_Control_R && syms[1] == XKB_KEY_ISO_Next_Group);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }
- static void
- test_get_utf8_utf32(struct xkb_keymap *keymap)
- {
- char buf[256];
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- #define TEST_KEY(key, expected_utf8, expected_utf32) do { \
- assert(xkb_state_key_get_utf8(state, (key) + EVDEV_OFFSET, NULL, 0) == (int) strlen(expected_utf8)); \
- assert(xkb_state_key_get_utf8(state, (key) + EVDEV_OFFSET, buf, sizeof(buf)) == (int) strlen(expected_utf8)); \
- assert(memcmp(buf, expected_utf8, sizeof(expected_utf8)) == 0); \
- assert(xkb_state_key_get_utf32(state, (key) + EVDEV_OFFSET) == (expected_utf32)); \
- } while (0)
- /* Simple ASCII. */
- TEST_KEY(KEY_A, "a", 0x61);
- TEST_KEY(KEY_ESC, "\x1B", 0x1B);
- TEST_KEY(KEY_1, "1", 0x31);
- /* Invalid. */
- TEST_KEY(XKB_KEYCODE_INVALID - 8, "", 0);
- TEST_KEY(300, "", 0);
- /* No string. */
- TEST_KEY(KEY_LEFTCTRL, "", 0);
- TEST_KEY(KEY_NUMLOCK, "", 0);
- /* Multiple keysyms. */
- TEST_KEY(KEY_6, "HELLO", 0);
- TEST_KEY(KEY_7, "YES THIS IS DOG", 0);
- /* Check truncation. */
- memset(buf, 'X', sizeof(buf));
- assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 0) == (int) strlen("HELLO"));
- assert(memcmp(buf, "X", 1) == 0);
- assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 1) == (int) strlen("HELLO"));
- assert(memcmp(buf, "", 1) == 0);
- assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 2) == (int) strlen("HELLO"));
- assert(memcmp(buf, "H", 2) == 0);
- assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 3) == (int) strlen("HELLO"));
- assert(memcmp(buf, "HE", 3) == 0);
- assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 5) == (int) strlen("HELLO"));
- assert(memcmp(buf, "HELL", 5) == 0);
- assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 6) == (int) strlen("HELLO"));
- assert(memcmp(buf, "HELLO", 6) == 0);
- assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 7) == (int) strlen("HELLO"));
- assert(memcmp(buf, "HELLO\0X", 7) == 0);
- /* Switch to ru layout */
- xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_key_get_layout(state, KEY_A + EVDEV_OFFSET) == 1);
- /* Non ASCII. */
- TEST_KEY(KEY_ESC, "\x1B", 0x1B);
- TEST_KEY(KEY_A, "ф", 0x0444);
- TEST_KEY(KEY_Z, "я", 0x044F);
- /* Switch back to us layout */
- xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_key_get_layout(state, KEY_A + EVDEV_OFFSET) == 0);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- TEST_KEY(KEY_A, "A", 0x41);
- TEST_KEY(KEY_ESC, "\x1B", 0x1B);
- TEST_KEY(KEY_1, "!", 0x21);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- TEST_KEY(KEY_6, "HELLO", 0);
- TEST_KEY(KEY_7, "YES THIS IS DOG", 0);
- xkb_state_unref(state);
- }
- static void
- test_ctrl_string_transformation(struct xkb_keymap *keymap)
- {
- char buf[256];
- xkb_mod_index_t ctrl = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- /* See xkb_state_key_get_utf8() for what's this all about. */
- /* First without. */
- TEST_KEY(KEY_A, "a", 0x61);
- TEST_KEY(KEY_B, "b", 0x62);
- TEST_KEY(KEY_C, "c", 0x63);
- TEST_KEY(KEY_ESC, "\x1B", 0x1B);
- TEST_KEY(KEY_1, "1", 0x31);
- /* And with. */
- xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0);
- TEST_KEY(KEY_A, "\x01", 0x01);
- TEST_KEY(KEY_B, "\x02", 0x02);
- TEST_KEY(KEY_C, "\x03", 0x03);
- TEST_KEY(KEY_ESC, "\x1B", 0x1B);
- TEST_KEY(KEY_1, "1", 0x31);
- xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_UP);
- /* Switch to ru layout */
- xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_key_get_layout(state, KEY_A + EVDEV_OFFSET) == 1);
- /* Non ASCII. */
- xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0);
- TEST_KEY(KEY_A, "\x01", 0x01);
- TEST_KEY(KEY_B, "\x02", 0x02);
- xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_UP);
- xkb_state_unref(state);
- }
- static bool
- test_active_leds(struct xkb_state *state, xkb_led_mask_t leds_expected)
- {
- struct xkb_keymap *keymap = xkb_state_get_keymap(state);
- bool ret = true;
- xkb_led_mask_t leds_got = 0;
- for (xkb_led_index_t led = 0; led < xkb_keymap_num_leds(keymap); led++) {
- const int status = xkb_state_led_index_is_active(state, led);
- if (status < 0)
- continue;
- const xkb_led_mask_t mask = (UINT32_C(1) << led);
- const bool expected = !!(leds_expected & mask);
- if (status)
- leds_got |= mask;
- if (!!status ^ expected) {
- fprintf(stderr, "ERROR: LED \"%s\" status: expected %d, got %d\n",
- xkb_keymap_led_get_name(keymap, led), expected, !!status);
- ret = false;
- }
- }
- if (!ret) {
- fprintf(stderr, "ERROR: LEDs: expected 0x%"PRIx32", got 0x%"PRIx32"\n",
- leds_expected, leds_got);
- }
- return ret;
- }
- static void
- test_leds(struct xkb_context *ctx)
- {
- const char buf[] =
- "xkb_keymap {\n"
- " xkb_keycodes { include \"evdev\" };\n"
- " xkb_types { include \"basic\" };\n"
- " xkb_compat {\n"
- " include \"leds(groups)\"\n"
- " interpret ISO_Group_Shift { action= SetGroup(group=+1); };\n"
- " interpret ISO_Group_Latch { action= LatchGroup(group=+1); };\n"
- " interpret ISO_Group_Lock { action= LockGroup(group=+1); };\n"
- " };\n"
- " xkb_symbols {\n"
- " key <AD01> { [ q, Q ], [w, W], [e, E] };\n"
- " key <LFSH> { [ ISO_Group_Shift ] };\n"
- " key <MENU> { [ ISO_Group_Latch ] };\n"
- " key <CAPS> { [ ISO_Group_Lock ] };\n"
- " };\n"
- "};";
- struct xkb_keymap *keymap =
- test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1,
- buf, ARRAY_SIZE(buf));
- assert(keymap);
- const xkb_led_index_t caps_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_CAPS);
- const xkb_led_index_t num_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_NUM);
- const xkb_led_index_t scroll_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_SCROLL);
- const xkb_led_index_t compose_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_COMPOSE);
- const xkb_led_index_t sleep_idx = _xkb_keymap_led_get_index(keymap, "Sleep");
- const xkb_led_index_t mute_idx = _xkb_keymap_led_get_index(keymap, "Mute");
- const xkb_led_index_t misc_idx = _xkb_keymap_led_get_index(keymap, "Misc");
- const xkb_led_index_t mail_idx = _xkb_keymap_led_get_index(keymap, "Mail");
- const xkb_led_index_t charging_idx = _xkb_keymap_led_get_index(keymap, "Charging");
- const xkb_led_mask_t caps = UINT32_C(1) << caps_idx;
- const xkb_led_mask_t num = UINT32_C(1) << num_idx;
- const xkb_led_mask_t scroll = UINT32_C(1) << scroll_idx;
- const xkb_led_mask_t compose = UINT32_C(1) << compose_idx;
- const xkb_led_mask_t sleep = UINT32_C(1) << sleep_idx;
- const xkb_led_mask_t mute = UINT32_C(1) << mute_idx;
- const xkb_led_mask_t misc = UINT32_C(1) << misc_idx;
- const xkb_led_mask_t mail = UINT32_C(1) << mail_idx;
- const xkb_led_mask_t charging = UINT32_C(1) << charging_idx;
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- xkb_state_update_key(state, KEY_Q + EVDEV_OFFSET, XKB_KEY_UP);
- assert(test_active_leds(state, (caps | scroll)));
- /* SetGroup */
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x1);
- assert(test_active_leds(state, (num | scroll | mute | misc)));
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- /* LatchGroup */
- xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x1);
- assert(test_active_leds(state, (caps | compose | mute | misc | charging)));
- xkb_state_update_key(state, KEY_Q + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_Q + EVDEV_OFFSET, XKB_KEY_UP);
- /* LockGroup 2 */
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x1);
- assert(test_active_leds(state, (caps | scroll | sleep | mute | mail)));
- /* LockGroup 2 + SetGroup */
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x2);
- assert(test_active_leds(state, (num | scroll | sleep | mute | misc | mail | charging)));
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- /* LockGroup 3 */
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x2);
- assert(test_active_leds(state, (caps | scroll | sleep | mute | charging)));
- /* LockGroup 3 + SetGroup */
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x0);
- assert(test_active_leds(state, (num | scroll | sleep | misc | charging)));
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }
- static void
- test_multiple_actions(struct xkb_context *ctx)
- {
- /* Check that we can trigger 2 actions on the same levels, with both
- * explicit (defined via the key statement) and explicit (defined via
- * interpret). The actions set the Control modifier and may change the
- * group. The idea is to enable keyboard shortcuts to always target the
- * same layout. Because SetGroup() does not work well with absolute values,
- * we define the modifiers on each 2 groups. */
- const char keymap_str[] =
- "xkb_keymap {\n"
- " xkb_keycodes {\n"
- " <AD01> = 24;\n"
- " <LCTL> = 37;\n"
- " <RCTL> = 105;\n"
- " };\n"
- " xkb_compat {\n"
- /* Right Control has its actions set implicitly via interpret */
- " interpret 1 {\n"
- " action = {SetMods(modifiers=Control)};\n"
- " };\n"
- " interpret 2 {\n"
- " action = {SetMods(modifiers=Control), SetGroup(group=-1)};\n"
- " };\n"
- " interpret 3 {\n"
- " action = {SetMods(modifiers=Control), SetGroup(group=-2)};\n"
- " };\n"
- " interpret 4 {\n"
- " action = {SetMods(modifiers=Control), SetGroup(group=-3)};\n"
- " };\n"
- " };\n"
- " xkb_symbols {\n"
- " key <AD01> { [q], [Arabic_dad], [c_h], [Thai_maiyamok] };\n"
- /* Left Control has its actions set explicitly */
- " key <LCTL> {\n"
- " symbols[1] = [Control_L],\n"
- " actions[1] = [{SetMods(modifiers=Control)}],\n"
- " actions[2] = [{SetMods(modifiers=Control), SetGroup(group=-1)}],\n"
- " actions[3] = [{SetMods(modifiers=Control), SetGroup(group=-2)}],\n"
- " actions[4] = [{SetMods(modifiers=Control), SetGroup(group=-3)}]\n"
- " };\n"
- " key <RCTL> { [1], [2], [3], [4] };\n"
- " };\n"
- "};";
- struct xkb_keymap *keymap =
- test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1,
- keymap_str, sizeof(keymap_str));
- assert(keymap);
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- const xkb_mod_index_t ctrl_idx =
- _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
- const xkb_mod_mask_t ctrl = UINT32_C(1) << ctrl_idx;
- const xkb_keycode_t lcontrol = KEY_LEFTCTRL + EVDEV_OFFSET;
- const xkb_keycode_t rcontrol = KEY_RIGHTCTRL + EVDEV_OFFSET;
- const xkb_keycode_t q = KEY_Q + EVDEV_OFFSET;
- xkb_mod_mask_t mods;
- const xkb_keycode_t mod_keys[] = {lcontrol, rcontrol};
- const xkb_keysym_t ad01[] = {
- XKB_KEY_q,
- XKB_KEY_Arabic_dad,
- XKB_KEY_c_h,
- XKB_KEY_Thai_maiyamok
- };
- for (xkb_layout_index_t layout = 0; layout < ARRAY_SIZE(ad01); layout++) {
- /* Lock layout */
- xkb_state_update_mask(state, 0, 0, 0, 0, 0, layout);
- assert(xkb_state_key_get_layout(state, q) == layout);
- assert(xkb_state_key_get_one_sym(state, q) == ad01[layout]);
- for (unsigned int k = 0; k < ARRAY_SIZE(mod_keys); k++) {
- /* Temporarily switch to first layout + set Control modifier */
- xkb_state_update_key(state, mod_keys[k], XKB_KEY_DOWN);
- assert(xkb_state_key_get_layout(state, q) == 0);
- mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
- assert(mods == ctrl);
- assert(xkb_state_key_get_one_sym(state, q) == XKB_KEY_q);
- /* Restore layout, unset Control */
- xkb_state_update_key(state, mod_keys[k], XKB_KEY_UP);
- assert(xkb_state_key_get_layout(state, q) == layout);
- mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
- assert(mods == 0);
- assert(xkb_state_key_get_one_sym(state, q) == ad01[layout]);
- }
- }
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }
- static void
- test_void_action(struct xkb_context *ctx)
- {
- const char keymap_str[] =
- "xkb_keymap {\n"
- " xkb_keycodes { <> = 1; };\n"
- " xkb_symbols { key <> { [VoidAction()], [VoidAction()] }; };\n"
- "};";
- struct xkb_keymap *keymap =
- test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1,
- keymap_str, sizeof(keymap_str));
- assert(keymap);
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- xkb_state_update_latched_locked(state, 0x1, 0x1, true, 1, 0, 0, false, 0);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 1);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0x1);
- xkb_state_update_key(state, 1, XKB_KEY_DOWN);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0);
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }
- static void
- test_extended_layout_indices(struct xkb_context *ctx)
- {
- const char keymap_str[] =
- "xkb_keymap \"extended-layout-indices\" {\n"
- " xkb_keycodes {\n"
- " <> = 1;\n"
- " <set-1> = 10;\n"
- " <set+1> = 11;\n"
- " <set32> = 12;\n"
- " <latch-1> = 20;\n"
- " <latch+1> = 21;\n"
- " <latch32> = 22;\n"
- " <lock-1> = 30;\n"
- " <lock+1> = 31;\n"
- " <lock32> = 32;\n"
- " };\n"
- " xkb_types { type \"ONE_LEVEL\" {}; };\n"
- " xkb_symbols {\n"
- " key <> {\n"
- " [a], [b], [c], [d], [e], [f], [g], [h], [i], [j],\n"
- " [k], [l], [m], [n], [o], [p], [q], [r], [s], [t],\n"
- " [u], [v], [w], [x], [y], [z], [1], [2], [3], [4],\n"
- " [5], [6]\n"
- " };\n"
- " key <set-1> { [ISO_Group_Shift], [SetGroup(group=-1)] };\n"
- " key <set+1> { [ISO_Group_Shift], [SetGroup(group=+1)] };\n"
- " key <set32> { [ISO_Group_Shift], [SetGroup(group=32)] };\n"
- " key <latch-1> { [ISO_Group_Latch], [LatchGroup(group=-1)] };\n"
- " key <latch+1> { [ISO_Group_Latch], [LatchGroup(group=+1)] };\n"
- " key <latch32> { [ISO_Group_Latch], [LatchGroup(group=32)] };\n"
- " key <lock-1> { [ISO_Group_Lock], [LockGroup(group=-1)] };\n"
- " key <lock+1> { [ISO_Group_Lock], [LockGroup(group=+1)] };\n"
- " key <lock32> { [ISO_Group_Lock], [LockGroup(group=32)] };\n"
- " };\n"
- "};";
- struct xkb_keymap *keymap = test_compile_buffer(
- ctx, XKB_KEYMAP_FORMAT_TEXT_V2, keymap_str, sizeof(keymap_str)
- );
- assert(keymap);
- const int32_t num_layouts = (int32_t) xkb_keymap_num_layouts(keymap);
- assert(num_layouts == XKB_MAX_GROUPS);
- struct xkb_state *state = xkb_state_new(keymap);
- assert(state);
- for (int32_t l = -num_layouts - 1; l < num_layouts + 1; l++) {
- const xkb_layout_index_t expected_layout = (xkb_layout_index_t)
- group_wrap(l, num_layouts);
- /* Out-of-band latches update */
- enum xkb_state_component expected_changes =
- (XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE) |
- ((l == 0) ? 0 : XKB_STATE_LAYOUT_LATCHED) |
- ((expected_layout == 0) ? 0 : XKB_STATE_LAYOUT_EFFECTIVE);
- enum xkb_state_component got_changes = xkb_state_update_latched_locked(
- state, 0x1, 0x1, true, l, 0, 0, false, 0
- );
- assert(got_changes == expected_changes);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED) ==
- (xkb_layout_index_t) l);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) ==
- expected_layout);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0x1);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0x1);
- /* Break latches by key press */
- got_changes = xkb_state_update_key(state, 1, XKB_KEY_DOWN);
- assert(got_changes == expected_changes);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED) == 0);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0);
- /* Check key release changes nothing */
- assert(xkb_state_update_key(state, 1, XKB_KEY_UP) == 0);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED) == 0);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0);
- /* Out-of-band locks update */
- got_changes = xkb_state_update_latched_locked(
- state, 0, 0, false, 0, 0x2, 0x2, true, l
- );
- expected_changes =
- (XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE) |
- ((expected_layout == 0)
- ? 0
- : (XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE));
- assert(got_changes == expected_changes);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED) ==
- expected_layout);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) ==
- expected_layout);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == 0x2);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0x2);
- /* Out-of-band locks reset */
- assert(got_changes == xkb_state_update_latched_locked(
- state, 0, 0, false, 0, 0x2, 0, true, 0
- ));
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED) == 0);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == 0);
- assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0);
- }
- const xkb_layout_index_t last_layout = (xkb_layout_index_t) num_layouts - 1;
- const struct test_state_components tests[] = {
- /*
- * Set
- */
- {
- KEY_ENTRY(10 - EVDEV_OFFSET, DOWN, XKB_KEY_ISO_Group_Shift),
- .base_group=-1, .group=last_layout,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
- },
- {
- KEY_ENTRY(1 - EVDEV_OFFSET, BOTH, XKB_KEY_6),
- .base_group=-1, .group=last_layout,
- .changes = 0
- },
- {
- KEY_ENTRY(10 - EVDEV_OFFSET, UP, XKB_KEY_ISO_Group_Shift),
- .base_group=0, .group=0,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
- },
- {
- KEY_ENTRY(12 - EVDEV_OFFSET, DOWN, XKB_KEY_ISO_Group_Shift),
- .base_group=num_layouts - 1, .group=last_layout,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
- },
- {
- KEY_ENTRY(11 - EVDEV_OFFSET, DOWN, XKB_KEY_ISO_Group_Shift),
- .base_group=num_layouts, .group=0,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
- },
- {
- KEY_ENTRY(11 - EVDEV_OFFSET, UP, XKB_KEY_ISO_Group_Shift),
- .base_group=num_layouts - 1, .group=last_layout,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
- },
- {
- KEY_ENTRY(12 - EVDEV_OFFSET, UP, XKB_KEY_ISO_Group_Shift),
- .base_group=0, .group=0,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE
- },
- /*
- * Lock
- */
- {
- KEY_ENTRY(30 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Lock),
- .locked_group=num_layouts - 1, .group=last_layout,
- .changes = 0
- },
- {
- KEY_ENTRY(31 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Lock),
- .locked_group=0, .group=0,
- .changes = 0
- },
- {
- KEY_ENTRY(32 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Lock),
- .locked_group=num_layouts-1, .group=last_layout,
- .changes = 0
- },
- /*
- * Latch
- */
- {
- KEY_ENTRY(21 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Latch),
- .latched_group=1, .locked_group=num_layouts-1, .group=0,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED
- },
- {
- KEY_ENTRY(1 - EVDEV_OFFSET, BOTH, XKB_KEY_a),
- .latched_group=0, .locked_group=num_layouts-1, .group=0,
- .changes = 0
- },
- {
- KEY_ENTRY(31 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Lock),
- .locked_group=0, .group=0,
- .changes = 0
- },
- {
- KEY_ENTRY(20 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Latch),
- .latched_group=-1, .group=last_layout,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED
- },
- {
- KEY_ENTRY(1 - EVDEV_OFFSET, BOTH, XKB_KEY_6),
- .latched_group=0, .group=0,
- .changes = 0
- },
- {
- KEY_ENTRY(22 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Latch),
- .latched_group=num_layouts-1, .group=last_layout,
- .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED
- },
- {
- KEY_ENTRY(1 - EVDEV_OFFSET, BOTH, XKB_KEY_6),
- .latched_group=0, .group=0,
- .changes = 0
- },
- };
- struct xkb_state *expected_state = xkb_state_new(keymap);
- assert(expected_state);
- for (size_t k = 0; k < ARRAY_SIZE(tests); k++) {
- assert_printf(
- run_state_update(keymap, &tests[k], &expected_state, &state),
- "%s #%zu: type: %d\n",
- __func__, k, tests[k].input_type
- );
- }
- xkb_state_unref(state);
- xkb_state_unref(expected_state);
- xkb_keymap_unref(keymap);
- }
- static void
- test_layout_index_named_bounds(struct xkb_context *ctx)
- {
- struct xkb_keymap * keymap = test_compile_rules(
- ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev-modern", "pc104",
- "us,in,ch,cz,de", NULL, "grp:shift_caps_switch,grp:group_bounds"
- );
- assert(keymap);
- struct xkb_state * state = xkb_state_new(keymap);
- assert(state);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_SCROLL));
- /* Last layout */
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 4);
- assert(!xkb_state_led_name_is_active(state, XKB_LED_NAME_SCROLL));
- xkb_state_update_latched_locked(state, 0, 0, false, 0, 0, 0, true, 2);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_SCROLL));
- /* First layout */
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_SCROLL));
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- /*
- * Ensure that the limitation of one group per key in a section holds when
- * using the RMLVO API and is consistent with the `Last` group constant value.
- */
- keymap = test_compile_rules(
- ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev-modern", "pc104",
- "multiple-groups,de,cz", NULL, "grp:shift_caps_switch,grp:group_bounds"
- );
- assert(keymap);
- state = xkb_state_new(keymap);
- assert(state);
- assert(xkb_keymap_num_layouts_for_key(keymap, KEY_RIGHTALT + EVDEV_OFFSET) == 3);
- assert(xkb_keymap_num_layouts(keymap) == 3);
- assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_SCROLL));
- /* Last layout */
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN);
- xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP);
- xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP);
- assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 2);
- assert(!xkb_state_led_name_is_active(state, XKB_LED_NAME_SCROLL));
- xkb_state_unref(state);
- xkb_keymap_unref(keymap);
- }
- int
- main(void)
- {
- test_init();
- struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG);
- assert(context);
- /* Make sure these are allowed. */
- xkb_context_unref(NULL);
- xkb_keymap_unref(NULL);
- xkb_state_unref(NULL);
- test_group_wrap(context);
- test_state_modes(context);
- test_initial_derived_values(context);
- const char* rules[] = {"evdev", "evdev-pure-virtual-mods"};
- struct xkb_keymap *keymap;
- for (size_t r = 0; r < ARRAY_SIZE(rules); r++) {
- fprintf(stderr, "=== Rules set: %s ===\n", rules[r]);
- keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, rules[r],
- "pc104", "us,ru", NULL,
- "grp:menu_toggle,grp:lwin_latch,"
- "grp:rwin_latch_lock_clear,"
- "grp:sclk_latch_no_lock,"
- "lv3:lsgt_latch,lv3:bksl_latch_no_lock,"
- "keypad:nmlk_repeats");
- assert(keymap);
- const bool pure_vmods = !!r;
- test_update_key(context, keymap, pure_vmods);
- test_update_latched_locked(keymap);
- test_serialisation(keymap, pure_vmods);
- test_update_mask_mods(keymap, pure_vmods);
- test_repeat(keymap);
- test_consume(keymap, pure_vmods);
- test_keycode_range(keymap);
- test_get_utf8_utf32(keymap);
- test_ctrl_string_transformation(keymap);
- xkb_keymap_unref(keymap);
- }
- test_inactive_key_type_entry(context);
- test_overlapping_mods(context);
- test_caps_keysym_transformation(context);
- test_leds(context);
- test_multiple_actions(context);
- test_void_action(context);
- test_extended_layout_indices(context);
- test_layout_index_named_bounds(context);
- xkb_context_unref(context);
- return EXIT_SUCCESS;
- }
|