1
0

test-tablet.c 251 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337
  1. /*
  2. * Copyright © 2014-2015 Red Hat, Inc.
  3. * Copyright © 2014 Lyude Paul
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice (including the next
  13. * paragraph) shall be included in all copies or substantial portions of the
  14. * Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. */
  24. #include <config.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <libinput.h>
  28. #include <stdarg.h>
  29. #include <stdbool.h>
  30. #include <unistd.h>
  31. #ifdef HAVE_LIBWACOM
  32. #include <libwacom/libwacom.h>
  33. #endif
  34. #include "util-input-event.h"
  35. #include "evdev-tablet.h"
  36. #include "libinput-util.h"
  37. #include "litest.h"
  38. enum {
  39. TILT_MINIMUM,
  40. TILT_CENTER,
  41. TILT_MAXIMUM,
  42. };
  43. static inline unsigned int
  44. pick_stylus_or_btn0(struct litest_device *dev)
  45. {
  46. if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_STYLUS))
  47. return BTN_STYLUS;
  48. if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_0))
  49. return BTN_0; /* totem */
  50. litest_abort_msg("Device has neither BTN_STYLUS nor BTN_0");
  51. }
  52. START_TEST(button_down_up)
  53. {
  54. struct litest_device *dev = litest_current_device();
  55. struct libinput *li = dev->libinput;
  56. struct libinput_event *event;
  57. struct libinput_event_tablet_tool *tev;
  58. struct axis_replacement axes[] = {
  59. { ABS_DISTANCE, 10 },
  60. { ABS_PRESSURE, 0 },
  61. { -1, -1 },
  62. };
  63. unsigned int button = pick_stylus_or_btn0(dev);
  64. litest_tablet_proximity_in(dev, 10, 10, axes);
  65. litest_drain_events(li);
  66. litest_button_click(dev, button, true);
  67. litest_dispatch(li);
  68. event = libinput_get_event(li);
  69. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  70. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
  71. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tev),
  72. LIBINPUT_BUTTON_STATE_PRESSED);
  73. libinput_event_destroy(event);
  74. litest_assert_empty_queue(li);
  75. litest_button_click(dev, button, false);
  76. litest_dispatch(li);
  77. event = libinput_get_event(li);
  78. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  79. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
  80. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tev),
  81. LIBINPUT_BUTTON_STATE_RELEASED);
  82. libinput_event_destroy(event);
  83. litest_assert_empty_queue(li);
  84. }
  85. END_TEST
  86. START_TEST(button_seat_count)
  87. {
  88. struct litest_device *dev = litest_current_device();
  89. struct libinput *li = dev->libinput;
  90. struct libinput_event *event;
  91. struct libinput_event_tablet_tool *tev;
  92. struct litest_device *dev2 = NULL;
  93. struct axis_replacement axes[] = {
  94. { ABS_DISTANCE, 10 },
  95. { ABS_PRESSURE, 0 },
  96. { -1, -1 },
  97. };
  98. unsigned int button = pick_stylus_or_btn0(dev);
  99. switch (button) {
  100. case BTN_STYLUS:
  101. dev2 = litest_add_device(li, LITEST_WACOM_CINTIQ_13HDT_PEN);
  102. break;
  103. case BTN_0:
  104. dev2 = litest_add_device(li, LITEST_DELL_CANVAS_TOTEM);
  105. break;
  106. default:
  107. litest_abort_msg("Invalid button code");
  108. }
  109. litest_tablet_proximity_in(dev, 10, 10, axes);
  110. litest_tablet_proximity_in(dev2, 10, 10, axes);
  111. litest_drain_events(li);
  112. litest_button_click(dev, button, true);
  113. litest_button_click(dev2, button, true);
  114. litest_dispatch(li);
  115. event = libinput_get_event(li);
  116. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  117. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
  118. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tev),
  119. LIBINPUT_BUTTON_STATE_PRESSED);
  120. litest_assert_int_eq(libinput_event_tablet_tool_get_seat_button_count(tev), 1U);
  121. libinput_event_destroy(event);
  122. event = libinput_get_event(li);
  123. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  124. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
  125. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tev),
  126. LIBINPUT_BUTTON_STATE_PRESSED);
  127. litest_assert_int_eq(libinput_event_tablet_tool_get_seat_button_count(tev), 2U);
  128. libinput_event_destroy(event);
  129. litest_assert_empty_queue(li);
  130. litest_button_click(dev2, button, false);
  131. litest_button_click(dev, button, false);
  132. litest_dispatch(li);
  133. event = libinput_get_event(li);
  134. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  135. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tev),
  136. LIBINPUT_BUTTON_STATE_RELEASED);
  137. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
  138. litest_assert_int_eq(libinput_event_tablet_tool_get_seat_button_count(tev), 1U);
  139. libinput_event_destroy(event);
  140. event = libinput_get_event(li);
  141. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  142. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tev),
  143. LIBINPUT_BUTTON_STATE_RELEASED);
  144. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
  145. litest_assert_int_eq(libinput_event_tablet_tool_get_seat_button_count(tev), 0U);
  146. libinput_event_destroy(event);
  147. litest_assert_empty_queue(li);
  148. litest_device_destroy(dev2);
  149. }
  150. END_TEST
  151. START_TEST(button_up_on_delete)
  152. {
  153. _litest_context_destroy_ struct libinput *li = litest_create_context();
  154. struct litest_device *dev = litest_add_device(li, LITEST_WACOM_INTUOS5_PEN);
  155. struct libevdev *evdev = libevdev_new();
  156. unsigned int code;
  157. litest_tablet_proximity_in(dev, 10, 10, NULL);
  158. litest_drain_events(li);
  159. for (code = BTN_LEFT; code <= BTN_TASK; code++) {
  160. if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
  161. continue;
  162. libevdev_enable_event_code(evdev, EV_KEY, code, NULL);
  163. litest_event(dev, EV_KEY, code, 1);
  164. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  165. litest_dispatch(li);
  166. }
  167. litest_drain_events(li);
  168. litest_device_destroy(dev);
  169. litest_dispatch(li);
  170. for (code = BTN_LEFT; code <= BTN_TASK; code++) {
  171. if (!libevdev_has_event_code(evdev, EV_KEY, code))
  172. continue;
  173. litest_assert_tablet_button_event(li,
  174. code,
  175. LIBINPUT_BUTTON_STATE_RELEASED);
  176. }
  177. litest_assert_tablet_proximity_event(li,
  178. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  179. libevdev_free(evdev);
  180. }
  181. END_TEST
  182. START_TEST(tip_down_up)
  183. {
  184. struct litest_device *dev = litest_current_device();
  185. struct libinput *li = dev->libinput;
  186. struct libinput_event *event;
  187. struct libinput_event_tablet_tool *tablet_event;
  188. struct axis_replacement axes[] = {
  189. { ABS_DISTANCE, 10 },
  190. { ABS_PRESSURE, 0 },
  191. { -1, -1 },
  192. };
  193. litest_tablet_proximity_in(dev, 10, 10, axes);
  194. litest_drain_events(li);
  195. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  196. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  197. litest_tablet_tip_down(dev, 10, 10, axes);
  198. litest_dispatch(li);
  199. event = libinput_get_event(li);
  200. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  201. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  202. LIBINPUT_TABLET_TOOL_TIP_DOWN);
  203. libinput_event_destroy(event);
  204. litest_assert_empty_queue(li);
  205. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  206. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  207. litest_tablet_tip_up(dev, 10, 10, axes);
  208. litest_dispatch(li);
  209. event = libinput_get_event(li);
  210. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  211. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  212. LIBINPUT_TABLET_TOOL_TIP_UP);
  213. libinput_event_destroy(event);
  214. litest_assert_empty_queue(li);
  215. }
  216. END_TEST
  217. START_TEST(tip_down_up_eraser)
  218. {
  219. struct litest_device *dev = litest_current_device();
  220. struct libinput *li = dev->libinput;
  221. struct libinput_event *event;
  222. struct libinput_event_tablet_tool *tablet_event;
  223. struct libinput_tablet_tool *tool;
  224. struct axis_replacement axes[] = {
  225. { ABS_DISTANCE, 10 },
  226. { ABS_PRESSURE, 0 },
  227. { -1, -1 },
  228. };
  229. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
  230. return LITEST_NOT_APPLICABLE;
  231. litest_tablet_set_tool_type(dev, BTN_TOOL_RUBBER);
  232. litest_tablet_proximity_in(dev, 10, 10, axes);
  233. litest_drain_events(li);
  234. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  235. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  236. litest_tablet_tip_down(dev, 10, 10, axes);
  237. litest_dispatch(li);
  238. event = libinput_get_event(li);
  239. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  240. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  241. LIBINPUT_TABLET_TOOL_TIP_DOWN);
  242. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  243. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  244. LIBINPUT_TABLET_TOOL_TYPE_ERASER);
  245. libinput_event_destroy(event);
  246. litest_assert_empty_queue(li);
  247. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  248. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  249. litest_tablet_tip_up(dev, 10, 10, axes);
  250. litest_dispatch(li);
  251. event = libinput_get_event(li);
  252. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  253. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  254. LIBINPUT_TABLET_TOOL_TIP_UP);
  255. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  256. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  257. LIBINPUT_TABLET_TOOL_TYPE_ERASER);
  258. libinput_event_destroy(event);
  259. litest_assert_empty_queue(li);
  260. }
  261. END_TEST
  262. START_TEST(tip_down_prox_in)
  263. {
  264. struct litest_device *dev = litest_current_device();
  265. struct libinput *li = dev->libinput;
  266. struct libinput_event *event;
  267. struct libinput_event_tablet_tool *tablet_event;
  268. struct axis_replacement axes[] = {
  269. { ABS_DISTANCE, 0 },
  270. { ABS_PRESSURE, 30 },
  271. { -1, -1 },
  272. };
  273. litest_drain_events(li);
  274. litest_with_event_frame(dev) {
  275. litest_tablet_proximity_in(dev, 10, 10, axes);
  276. litest_tablet_tip_down(dev, 10, 10, axes);
  277. }
  278. litest_dispatch(li);
  279. event = libinput_get_event(li);
  280. tablet_event =
  281. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  282. litest_assert_enum_eq(
  283. libinput_event_tablet_tool_get_proximity_state(tablet_event),
  284. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  285. libinput_event_destroy(event);
  286. event = libinput_get_event(li);
  287. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  288. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  289. LIBINPUT_TABLET_TOOL_TIP_DOWN);
  290. libinput_event_destroy(event);
  291. litest_assert_empty_queue(li);
  292. }
  293. END_TEST
  294. START_TEST(tip_up_prox_out)
  295. {
  296. struct litest_device *dev = litest_current_device();
  297. struct libinput *li = dev->libinput;
  298. struct libinput_event *event;
  299. struct libinput_event_tablet_tool *tablet_event;
  300. struct axis_replacement axes[] = {
  301. { ABS_DISTANCE, 0 },
  302. { ABS_PRESSURE, 30 },
  303. { -1, -1 },
  304. };
  305. litest_tablet_proximity_in(dev, 10, 10, axes);
  306. litest_tablet_tip_down(dev, 10, 10, axes);
  307. litest_drain_events(li);
  308. litest_axis_set_value(axes, ABS_DISTANCE, 30);
  309. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  310. litest_with_event_frame(dev) {
  311. litest_tablet_tip_up(dev, 10, 10, axes);
  312. litest_tablet_proximity_out(dev);
  313. }
  314. litest_dispatch(li);
  315. event = libinput_get_event(li);
  316. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  317. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  318. LIBINPUT_TABLET_TOOL_TIP_UP);
  319. libinput_event_destroy(event);
  320. litest_timeout_tablet_proxout(li);
  321. event = libinput_get_event(li);
  322. tablet_event =
  323. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  324. litest_assert_enum_eq(
  325. libinput_event_tablet_tool_get_proximity_state(tablet_event),
  326. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  327. libinput_event_destroy(event);
  328. litest_assert_empty_queue(li);
  329. }
  330. END_TEST
  331. START_TEST(tip_up_btn_change)
  332. {
  333. struct litest_device *dev = litest_current_device();
  334. struct libinput *li = dev->libinput;
  335. struct libinput_event *event;
  336. struct libinput_event_tablet_tool *tablet_event;
  337. struct axis_replacement axes[] = {
  338. { ABS_DISTANCE, 0 },
  339. { ABS_PRESSURE, 30 },
  340. { -1, -1 },
  341. };
  342. litest_tablet_proximity_in(dev, 10, 10, axes);
  343. litest_tablet_tip_down(dev, 10, 10, axes);
  344. litest_drain_events(li);
  345. litest_axis_set_value(axes, ABS_DISTANCE, 30);
  346. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  347. litest_with_event_frame(dev) {
  348. litest_tablet_tip_up(dev, 10, 20, axes);
  349. litest_event(dev, EV_KEY, BTN_STYLUS, 1);
  350. }
  351. litest_dispatch(li);
  352. event = libinput_get_event(li);
  353. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  354. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  355. LIBINPUT_TABLET_TOOL_TIP_UP);
  356. libinput_event_destroy(event);
  357. event = libinput_get_event(li);
  358. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  359. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tablet_event),
  360. (unsigned int)BTN_STYLUS);
  361. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tablet_event),
  362. LIBINPUT_BUTTON_STATE_PRESSED);
  363. libinput_event_destroy(event);
  364. litest_assert_empty_queue(li);
  365. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  366. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  367. litest_tablet_tip_down(dev, 10, 10, axes);
  368. litest_drain_events(li);
  369. /* same thing with a release at tip-up */
  370. litest_axis_set_value(axes, ABS_DISTANCE, 30);
  371. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  372. litest_with_event_frame(dev) {
  373. litest_tablet_tip_up(dev, 10, 10, axes);
  374. litest_event(dev, EV_KEY, BTN_STYLUS, 0);
  375. }
  376. litest_dispatch(li);
  377. event = libinput_get_event(li);
  378. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  379. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  380. LIBINPUT_TABLET_TOOL_TIP_UP);
  381. libinput_event_destroy(event);
  382. event = libinput_get_event(li);
  383. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  384. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tablet_event),
  385. (unsigned int)BTN_STYLUS);
  386. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tablet_event),
  387. LIBINPUT_BUTTON_STATE_RELEASED);
  388. libinput_event_destroy(event);
  389. litest_assert_empty_queue(li);
  390. }
  391. END_TEST
  392. START_TEST(tip_down_btn_change)
  393. {
  394. struct litest_device *dev = litest_current_device();
  395. struct libinput *li = dev->libinput;
  396. struct libinput_event *event;
  397. struct libinput_event_tablet_tool *tablet_event;
  398. struct axis_replacement axes[] = {
  399. { ABS_DISTANCE, 10 },
  400. { ABS_PRESSURE, 0 },
  401. { -1, -1 },
  402. };
  403. litest_tablet_proximity_in(dev, 10, 10, axes);
  404. litest_drain_events(li);
  405. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  406. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  407. litest_with_event_frame(dev) {
  408. litest_tablet_tip_down(dev, 10, 20, axes);
  409. litest_event(dev, EV_KEY, BTN_STYLUS, 1);
  410. }
  411. litest_dispatch(li);
  412. event = libinput_get_event(li);
  413. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  414. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  415. LIBINPUT_TABLET_TOOL_TIP_DOWN);
  416. libinput_event_destroy(event);
  417. litest_dispatch(li);
  418. event = libinput_get_event(li);
  419. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  420. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tablet_event),
  421. (unsigned int)BTN_STYLUS);
  422. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tablet_event),
  423. LIBINPUT_BUTTON_STATE_PRESSED);
  424. libinput_event_destroy(event);
  425. litest_assert_empty_queue(li);
  426. litest_axis_set_value(axes, ABS_DISTANCE, 30);
  427. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  428. litest_tablet_tip_up(dev, 10, 20, axes);
  429. litest_drain_events(li);
  430. /* same thing with a release at tip-down */
  431. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  432. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  433. litest_with_event_frame(dev) {
  434. litest_tablet_tip_down(dev, 10, 20, axes);
  435. litest_event(dev, EV_KEY, BTN_STYLUS, 0);
  436. }
  437. litest_dispatch(li);
  438. event = libinput_get_event(li);
  439. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  440. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  441. LIBINPUT_TABLET_TOOL_TIP_DOWN);
  442. libinput_event_destroy(event);
  443. litest_dispatch(li);
  444. event = libinput_get_event(li);
  445. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  446. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tablet_event),
  447. (unsigned int)BTN_STYLUS);
  448. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tablet_event),
  449. LIBINPUT_BUTTON_STATE_RELEASED);
  450. libinput_event_destroy(event);
  451. litest_assert_empty_queue(li);
  452. }
  453. END_TEST
  454. START_TEST(tip_down_motion)
  455. {
  456. struct litest_device *dev = litest_current_device();
  457. struct libinput *li = dev->libinput;
  458. struct libinput_event *event;
  459. struct libinput_event_tablet_tool *tablet_event;
  460. struct axis_replacement axes[] = {
  461. { ABS_DISTANCE, 10 },
  462. { ABS_PRESSURE, 0 },
  463. { -1, -1 },
  464. };
  465. double x, y, last_x, last_y;
  466. litest_drain_events(li);
  467. litest_tablet_proximity_in(dev, 10, 10, axes);
  468. litest_dispatch(li);
  469. event = libinput_get_event(li);
  470. tablet_event =
  471. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  472. last_x = libinput_event_tablet_tool_get_x(tablet_event);
  473. last_y = libinput_event_tablet_tool_get_y(tablet_event);
  474. libinput_event_destroy(event);
  475. /* move x/y on tip down, make sure x/y changed */
  476. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  477. litest_axis_set_value(axes, ABS_PRESSURE, 20);
  478. litest_tablet_tip_down(dev, 70, 70, axes);
  479. litest_dispatch(li);
  480. event = libinput_get_event(li);
  481. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  482. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  483. LIBINPUT_TABLET_TOOL_TIP_DOWN);
  484. litest_assert(libinput_event_tablet_tool_x_has_changed(tablet_event));
  485. litest_assert(libinput_event_tablet_tool_y_has_changed(tablet_event));
  486. x = libinput_event_tablet_tool_get_x(tablet_event);
  487. y = libinput_event_tablet_tool_get_y(tablet_event);
  488. litest_assert_double_lt(last_x, x);
  489. litest_assert_double_lt(last_y, y);
  490. libinput_event_destroy(event);
  491. litest_assert_empty_queue(li);
  492. }
  493. END_TEST
  494. START_TEST(tip_up_motion)
  495. {
  496. struct litest_device *dev = litest_current_device();
  497. struct libinput *li = dev->libinput;
  498. struct libinput_event *event;
  499. struct libinput_event_tablet_tool *tablet_event;
  500. struct axis_replacement axes[] = {
  501. { ABS_DISTANCE, 0 },
  502. { ABS_PRESSURE, 0 },
  503. { -1, -1 },
  504. };
  505. double x, y, last_x, last_y;
  506. litest_tablet_proximity_in(dev, 10, 10, axes);
  507. litest_drain_events(li);
  508. litest_axis_set_value(axes, ABS_PRESSURE, 20);
  509. litest_tablet_tip_down(dev, 70, 70, axes);
  510. litest_dispatch(li);
  511. event = libinput_get_event(li);
  512. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  513. last_x = libinput_event_tablet_tool_get_x(tablet_event);
  514. last_y = libinput_event_tablet_tool_get_y(tablet_event);
  515. libinput_event_destroy(event);
  516. /* move x/y on tip up, make sure x/y changed */
  517. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  518. litest_tablet_tip_up(dev, 40, 40, axes);
  519. litest_dispatch(li);
  520. event = libinput_get_event(li);
  521. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  522. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  523. LIBINPUT_TABLET_TOOL_TIP_UP);
  524. litest_assert(libinput_event_tablet_tool_x_has_changed(tablet_event));
  525. litest_assert(libinput_event_tablet_tool_y_has_changed(tablet_event));
  526. x = libinput_event_tablet_tool_get_x(tablet_event);
  527. y = libinput_event_tablet_tool_get_y(tablet_event);
  528. litest_assert_double_ne(last_x, x);
  529. litest_assert_double_ne(last_y, y);
  530. libinput_event_destroy(event);
  531. litest_assert_empty_queue(li);
  532. }
  533. END_TEST
  534. START_TEST(tip_up_motion_one_axis)
  535. {
  536. struct litest_device *dev = litest_current_device();
  537. struct libinput *li = dev->libinput;
  538. struct libinput_event *event;
  539. struct libinput_event_tablet_tool *tablet_event;
  540. struct axis_replacement axes[] = {
  541. { ABS_DISTANCE, 0 },
  542. { ABS_PRESSURE, 0 },
  543. { -1, -1 },
  544. };
  545. double x, y, last_x, last_y;
  546. double start_x = 20, start_y = 20;
  547. int axis = litest_test_param_get_i32(test_env->params, "axis");
  548. switch (axis) {
  549. case ABS_X:
  550. start_x = 15;
  551. start_y = 20;
  552. break;
  553. case ABS_Y:
  554. start_x = 20;
  555. start_y = 15;
  556. break;
  557. default:
  558. litest_assert_not_reached();
  559. }
  560. /* generate enough events to fill the history and move alonge the
  561. * current axis to avoid axis smoothing interference */
  562. litest_tablet_proximity_in(dev, start_x, start_y, axes);
  563. litest_axis_set_value(axes, ABS_PRESSURE, 20);
  564. for (int i = 0; i < 5; i++) {
  565. litest_tablet_tip_down(dev, start_x, start_y, axes);
  566. switch (axis) {
  567. case ABS_X:
  568. start_x++;
  569. break;
  570. case ABS_Y:
  571. start_y++;
  572. break;
  573. }
  574. }
  575. litest_drain_events(li);
  576. litest_tablet_motion(dev, 20, 20, axes);
  577. litest_dispatch(li);
  578. event = libinput_get_event(li);
  579. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  580. last_x = libinput_event_tablet_tool_get_x(tablet_event);
  581. last_y = libinput_event_tablet_tool_get_y(tablet_event);
  582. libinput_event_destroy(event);
  583. /* move x on tip up, make sure x/y changed */
  584. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  585. switch (axis) {
  586. case ABS_X:
  587. litest_tablet_tip_up(dev, 40, 20, axes);
  588. break;
  589. case ABS_Y:
  590. litest_tablet_tip_up(dev, 20, 40, axes);
  591. break;
  592. }
  593. litest_dispatch(li);
  594. event = libinput_get_event(li);
  595. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  596. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  597. LIBINPUT_TABLET_TOOL_TIP_UP);
  598. x = libinput_event_tablet_tool_get_x(tablet_event);
  599. y = libinput_event_tablet_tool_get_y(tablet_event);
  600. switch (axis) {
  601. case ABS_X:
  602. litest_assert(libinput_event_tablet_tool_x_has_changed(tablet_event));
  603. litest_assert(!libinput_event_tablet_tool_y_has_changed(tablet_event));
  604. litest_assert_double_ne(last_x, x);
  605. litest_assert_double_eq(last_y, y);
  606. break;
  607. case ABS_Y:
  608. litest_assert(!libinput_event_tablet_tool_x_has_changed(tablet_event));
  609. litest_assert(libinput_event_tablet_tool_y_has_changed(tablet_event));
  610. litest_assert_double_eq(last_x, x);
  611. litest_assert_double_ne(last_y, y);
  612. break;
  613. }
  614. libinput_event_destroy(event);
  615. litest_assert_empty_queue(li);
  616. }
  617. END_TEST
  618. START_TEST(tip_state_proximity)
  619. {
  620. struct litest_device *dev = litest_current_device();
  621. struct libinput *li = dev->libinput;
  622. struct libinput_event *event;
  623. struct libinput_event_tablet_tool *tablet_event;
  624. struct axis_replacement axes[] = {
  625. { ABS_DISTANCE, 10 },
  626. { ABS_PRESSURE, 0 },
  627. { -1, -1 },
  628. };
  629. litest_drain_events(li);
  630. litest_tablet_proximity_in(dev, 10, 10, axes);
  631. litest_dispatch(li);
  632. event = libinput_get_event(li);
  633. tablet_event =
  634. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  635. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  636. LIBINPUT_TABLET_TOOL_TIP_UP);
  637. libinput_event_destroy(event);
  638. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  639. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  640. litest_tablet_tip_down(dev, 10, 10, axes);
  641. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  642. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  643. litest_tablet_tip_up(dev, 10, 10, axes);
  644. litest_drain_events(li);
  645. litest_tablet_proximity_out(dev);
  646. litest_timeout_tablet_proxout(li);
  647. event = libinput_get_event(li);
  648. tablet_event =
  649. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  650. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  651. LIBINPUT_TABLET_TOOL_TIP_UP);
  652. libinput_event_destroy(event);
  653. }
  654. END_TEST
  655. START_TEST(tip_state_axis)
  656. {
  657. struct litest_device *dev = litest_current_device();
  658. struct libinput *li = dev->libinput;
  659. struct libinput_event *event;
  660. struct libinput_event_tablet_tool *tablet_event;
  661. struct axis_replacement axes[] = {
  662. { ABS_DISTANCE, 10 },
  663. { ABS_PRESSURE, 0 },
  664. { -1, -1 },
  665. };
  666. litest_tablet_proximity_in(dev, 10, 10, axes);
  667. litest_drain_events(li);
  668. litest_tablet_motion(dev, 70, 70, axes);
  669. litest_dispatch(li);
  670. event = libinput_get_event(li);
  671. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  672. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  673. LIBINPUT_TABLET_TOOL_TIP_UP);
  674. libinput_event_destroy(event);
  675. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  676. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  677. litest_tablet_tip_down(dev, 40, 40, axes);
  678. litest_drain_events(li);
  679. litest_tablet_motion(dev, 30, 30, axes);
  680. litest_dispatch(li);
  681. event = libinput_get_event(li);
  682. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  683. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  684. LIBINPUT_TABLET_TOOL_TIP_DOWN);
  685. libinput_event_destroy(event);
  686. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  687. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  688. litest_tablet_tip_up(dev, 40, 40, axes);
  689. litest_drain_events(li);
  690. litest_tablet_motion(dev, 40, 80, axes);
  691. litest_dispatch(li);
  692. event = libinput_get_event(li);
  693. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  694. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  695. LIBINPUT_TABLET_TOOL_TIP_UP);
  696. libinput_event_destroy(event);
  697. litest_assert_empty_queue(li);
  698. }
  699. END_TEST
  700. START_TEST(tip_state_button)
  701. {
  702. struct litest_device *dev = litest_current_device();
  703. struct libinput *li = dev->libinput;
  704. struct libinput_event *event;
  705. struct libinput_event_tablet_tool *tablet_event;
  706. struct axis_replacement axes[] = {
  707. { ABS_DISTANCE, 10 },
  708. { ABS_PRESSURE, 0 },
  709. { -1, -1 },
  710. };
  711. unsigned int button = pick_stylus_or_btn0(dev);
  712. litest_tablet_proximity_in(dev, 10, 10, axes);
  713. litest_drain_events(li);
  714. litest_button_click(dev, button, true);
  715. litest_dispatch(li);
  716. event = libinput_get_event(li);
  717. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  718. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  719. LIBINPUT_TABLET_TOOL_TIP_UP);
  720. libinput_event_destroy(event);
  721. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  722. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  723. litest_tablet_tip_down(dev, 40, 40, axes);
  724. litest_drain_events(li);
  725. litest_button_click(dev, button, false);
  726. litest_dispatch(li);
  727. event = libinput_get_event(li);
  728. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  729. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  730. LIBINPUT_TABLET_TOOL_TIP_DOWN);
  731. libinput_event_destroy(event);
  732. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  733. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  734. litest_tablet_tip_up(dev, 40, 40, axes);
  735. litest_drain_events(li);
  736. litest_button_click(dev, button, true);
  737. litest_dispatch(li);
  738. event = libinput_get_event(li);
  739. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  740. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  741. LIBINPUT_TABLET_TOOL_TIP_UP);
  742. libinput_event_destroy(event);
  743. litest_button_click(dev, button, false);
  744. litest_dispatch(li);
  745. event = libinput_get_event(li);
  746. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  747. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  748. LIBINPUT_TABLET_TOOL_TIP_UP);
  749. libinput_event_destroy(event);
  750. litest_assert_empty_queue(li);
  751. }
  752. END_TEST
  753. START_TEST(tip_up_on_delete)
  754. {
  755. _litest_context_destroy_ struct libinput *li = litest_create_context();
  756. struct litest_device *dev = litest_add_device(li, LITEST_WACOM_INTUOS5_PEN);
  757. struct libinput_event *event;
  758. struct libinput_event_tablet_tool *tablet_event;
  759. struct axis_replacement axes[] = {
  760. { ABS_DISTANCE, 10 },
  761. { ABS_PRESSURE, 0 },
  762. { -1, -1 },
  763. };
  764. litest_tablet_proximity_in(dev, 10, 10, axes);
  765. litest_drain_events(li);
  766. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  767. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  768. litest_tablet_tip_down(dev, 10, 10, axes);
  769. litest_drain_events(li);
  770. litest_device_destroy(dev);
  771. litest_dispatch(li);
  772. event = libinput_get_event(li);
  773. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  774. litest_assert_enum_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
  775. LIBINPUT_TABLET_TOOL_TIP_UP);
  776. libinput_event_destroy(event);
  777. }
  778. END_TEST
  779. START_TEST(proximity_in_out)
  780. {
  781. struct litest_device *dev = litest_current_device();
  782. struct libinput *li = dev->libinput;
  783. struct libinput_event_tablet_tool *tablet_event;
  784. struct libinput_event *event;
  785. enum libinput_tablet_tool_type type;
  786. bool have_tool_update = false, have_proximity_out = false;
  787. struct axis_replacement axes[] = {
  788. { ABS_DISTANCE, 10 },
  789. { ABS_PRESSURE, 0 },
  790. { -1, -1 },
  791. };
  792. litest_drain_events(li);
  793. switch (dev->which) {
  794. case LITEST_DELL_CANVAS_TOTEM:
  795. type = LIBINPUT_TABLET_TOOL_TYPE_TOTEM;
  796. break;
  797. default:
  798. type = LIBINPUT_TABLET_TOOL_TYPE_PEN;
  799. break;
  800. }
  801. litest_tablet_proximity_in(dev, 10, 10, axes);
  802. litest_dispatch(li);
  803. while ((event = libinput_get_event(li))) {
  804. if (libinput_event_get_type(event) ==
  805. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY) {
  806. struct libinput_tablet_tool *tool;
  807. litest_assert(!have_tool_update);
  808. have_tool_update = true;
  809. tablet_event = libinput_event_get_tablet_tool_event(event);
  810. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  811. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  812. type);
  813. }
  814. libinput_event_destroy(event);
  815. }
  816. litest_assert(have_tool_update);
  817. litest_tablet_proximity_out(dev);
  818. litest_timeout_tablet_proxout(li);
  819. while ((event = libinput_get_event(li))) {
  820. if (libinput_event_get_type(event) ==
  821. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY) {
  822. struct libinput_event_tablet_tool *t =
  823. libinput_event_get_tablet_tool_event(event);
  824. if (libinput_event_tablet_tool_get_proximity_state(t) ==
  825. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT)
  826. have_proximity_out = true;
  827. }
  828. libinput_event_destroy(event);
  829. }
  830. litest_assert(have_proximity_out);
  831. /* Proximity out must not emit axis events */
  832. litest_assert_empty_queue(li);
  833. }
  834. END_TEST
  835. START_TEST(proximity_in_button_down)
  836. {
  837. struct litest_device *dev = litest_current_device();
  838. struct libinput *li = dev->libinput;
  839. struct axis_replacement axes[] = {
  840. { ABS_DISTANCE, 10 },
  841. { ABS_PRESSURE, 0 },
  842. { -1, -1 },
  843. };
  844. unsigned int button = pick_stylus_or_btn0(dev);
  845. litest_drain_events(li);
  846. litest_with_event_frame(dev) {
  847. litest_tablet_proximity_in(dev, 10, 10, axes);
  848. litest_event(dev, EV_KEY, button, 1);
  849. }
  850. litest_dispatch(li);
  851. litest_assert_tablet_proximity_event(li,
  852. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  853. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  854. litest_assert_tablet_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED);
  855. litest_assert_empty_queue(li);
  856. }
  857. END_TEST
  858. START_TEST(proximity_out_button_up)
  859. {
  860. struct litest_device *dev = litest_current_device();
  861. struct libinput *li = dev->libinput;
  862. struct axis_replacement axes[] = {
  863. { ABS_DISTANCE, 10 },
  864. { ABS_PRESSURE, 0 },
  865. { -1, -1 },
  866. };
  867. unsigned int button = pick_stylus_or_btn0(dev);
  868. litest_tablet_proximity_in(dev, 10, 10, axes);
  869. litest_button_click(dev, button, true);
  870. litest_drain_events(li);
  871. litest_with_event_frame(dev) {
  872. litest_tablet_proximity_out(dev);
  873. litest_event(dev, EV_KEY, button, 0);
  874. }
  875. litest_timeout_tablet_proxout(li);
  876. litest_assert_tablet_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED);
  877. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  878. litest_assert_tablet_proximity_event(li,
  879. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  880. litest_assert_empty_queue(li);
  881. }
  882. END_TEST
  883. START_TEST(proximity_out_clear_buttons)
  884. {
  885. struct litest_device *dev = litest_current_device();
  886. struct libinput *li = dev->libinput;
  887. struct libinput_event_tablet_tool *tablet_event;
  888. struct libinput_event *event;
  889. struct axis_replacement axes[] = {
  890. { ABS_DISTANCE, 10 },
  891. { ABS_PRESSURE, 0 },
  892. { -1, -1 },
  893. };
  894. uint32_t stylus_buttons[] = { BTN_STYLUS, BTN_STYLUS2, BTN_STYLUS3 };
  895. bool have_proximity = false;
  896. double x = 50, y = 50;
  897. litest_drain_events(li);
  898. /* Test that proximity out events send button releases for any currently
  899. * pressed stylus buttons
  900. */
  901. ARRAY_FOR_EACH(stylus_buttons, button) {
  902. bool button_released = false;
  903. uint32_t event_button = 0;
  904. enum libinput_button_state state;
  905. if (!libevdev_has_event_code(dev->evdev, EV_KEY, *button))
  906. continue;
  907. litest_tablet_proximity_in(dev, x++, y++, axes);
  908. litest_drain_events(li);
  909. litest_event(dev, EV_KEY, *button, 1);
  910. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  911. litest_tablet_proximity_out(dev);
  912. litest_timeout_tablet_proxout(li);
  913. event = libinput_get_event(li);
  914. litest_assert_notnull(event);
  915. do {
  916. tablet_event = libinput_event_get_tablet_tool_event(event);
  917. if (libinput_event_get_type(event) ==
  918. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY) {
  919. have_proximity = true;
  920. libinput_event_destroy(event);
  921. break;
  922. }
  923. if (libinput_event_get_type(event) ==
  924. LIBINPUT_EVENT_TABLET_TOOL_BUTTON) {
  925. event_button = libinput_event_tablet_tool_get_button(
  926. tablet_event);
  927. state = libinput_event_tablet_tool_get_button_state(
  928. tablet_event);
  929. if (event_button == *button &&
  930. state == LIBINPUT_BUTTON_STATE_RELEASED)
  931. button_released = true;
  932. }
  933. libinput_event_destroy(event);
  934. } while ((event = libinput_get_event(li)));
  935. litest_assert_msg(button_released,
  936. "Button %s (%d) was not released.",
  937. libevdev_event_code_get_name(EV_KEY, *button),
  938. event_button);
  939. litest_assert(have_proximity);
  940. litest_assert_empty_queue(li);
  941. }
  942. }
  943. END_TEST
  944. START_TEST(proximity_has_axes)
  945. {
  946. struct litest_device *dev = litest_current_device();
  947. struct libinput *li = dev->libinput;
  948. struct libinput_event_tablet_tool *tablet_event;
  949. struct libinput_event *event;
  950. struct libinput_tablet_tool *tool;
  951. double x, y, distance;
  952. double last_x, last_y, last_distance = 0.0, last_tx = 0.0, last_ty = 0.0;
  953. struct axis_replacement axes[] = { { ABS_DISTANCE, 10 },
  954. { ABS_PRESSURE, 0 },
  955. { ABS_TILT_X, 10 },
  956. { ABS_TILT_Y, 10 },
  957. { -1, -1 } };
  958. litest_drain_events(li);
  959. litest_tablet_proximity_in(dev, 10, 10, axes);
  960. litest_dispatch(li);
  961. event = libinput_get_event(li);
  962. tablet_event =
  963. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  964. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  965. litest_assert(libinput_event_tablet_tool_x_has_changed(tablet_event));
  966. litest_assert(libinput_event_tablet_tool_y_has_changed(tablet_event));
  967. x = libinput_event_tablet_tool_get_x(tablet_event);
  968. y = libinput_event_tablet_tool_get_y(tablet_event);
  969. litest_assert_double_ne(x, 0);
  970. litest_assert_double_ne(y, 0);
  971. if (libinput_tablet_tool_has_distance(tool)) {
  972. litest_assert(
  973. libinput_event_tablet_tool_distance_has_changed(tablet_event));
  974. distance = libinput_event_tablet_tool_get_distance(tablet_event);
  975. litest_assert_double_ne(distance, 0);
  976. }
  977. if (libinput_tablet_tool_has_tilt(tool)) {
  978. litest_assert(
  979. libinput_event_tablet_tool_tilt_x_has_changed(tablet_event));
  980. litest_assert(
  981. libinput_event_tablet_tool_tilt_y_has_changed(tablet_event));
  982. x = libinput_event_tablet_tool_get_tilt_x(tablet_event);
  983. y = libinput_event_tablet_tool_get_tilt_y(tablet_event);
  984. litest_assert_double_ne(x, 0);
  985. litest_assert_double_ne(y, 0);
  986. }
  987. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  988. litest_assert_empty_queue(li);
  989. libinput_event_destroy(event);
  990. litest_axis_set_value(axes, ABS_DISTANCE, 20);
  991. litest_axis_set_value(axes, ABS_TILT_X, 15);
  992. litest_axis_set_value(axes, ABS_TILT_Y, 25);
  993. /* work around axis smoothing */
  994. litest_tablet_motion(dev, 20, 30, axes);
  995. litest_tablet_motion(dev, 20, 29, axes);
  996. litest_tablet_motion(dev, 20, 31, axes);
  997. litest_drain_events(li);
  998. litest_tablet_motion(dev, 20, 30, axes);
  999. litest_dispatch(li);
  1000. event = libinput_get_event(li);
  1001. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1002. last_x = libinput_event_tablet_tool_get_x(tablet_event);
  1003. last_y = libinput_event_tablet_tool_get_y(tablet_event);
  1004. if (libinput_tablet_tool_has_distance(tool))
  1005. last_distance = libinput_event_tablet_tool_get_distance(tablet_event);
  1006. if (libinput_tablet_tool_has_tilt(tool)) {
  1007. last_tx = libinput_event_tablet_tool_get_tilt_x(tablet_event);
  1008. last_ty = libinput_event_tablet_tool_get_tilt_y(tablet_event);
  1009. }
  1010. libinput_event_destroy(event);
  1011. /* Make sure that the axes are still present on proximity out */
  1012. litest_tablet_proximity_out(dev);
  1013. litest_timeout_tablet_proxout(li);
  1014. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  1015. event = libinput_get_event(li);
  1016. tablet_event =
  1017. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  1018. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  1019. litest_assert(!libinput_event_tablet_tool_x_has_changed(tablet_event));
  1020. litest_assert(!libinput_event_tablet_tool_y_has_changed(tablet_event));
  1021. x = libinput_event_tablet_tool_get_x(tablet_event);
  1022. y = libinput_event_tablet_tool_get_y(tablet_event);
  1023. litest_assert_double_ge(x, last_x - 1);
  1024. litest_assert_double_le(x, last_x + 1);
  1025. litest_assert_double_ge(y, last_y - 1);
  1026. litest_assert_double_le(y, last_y + 1);
  1027. if (libinput_tablet_tool_has_distance(tool)) {
  1028. litest_assert(
  1029. !libinput_event_tablet_tool_distance_has_changed(tablet_event));
  1030. distance = libinput_event_tablet_tool_get_distance(tablet_event);
  1031. litest_assert_double_eq(distance, last_distance);
  1032. }
  1033. if (libinput_tablet_tool_has_tilt(tool)) {
  1034. litest_assert(
  1035. !libinput_event_tablet_tool_tilt_x_has_changed(tablet_event));
  1036. litest_assert(
  1037. !libinput_event_tablet_tool_tilt_y_has_changed(tablet_event));
  1038. x = libinput_event_tablet_tool_get_tilt_x(tablet_event);
  1039. y = libinput_event_tablet_tool_get_tilt_y(tablet_event);
  1040. litest_assert_double_eq(x, last_tx);
  1041. litest_assert_double_eq(y, last_ty);
  1042. }
  1043. litest_assert_empty_queue(li);
  1044. libinput_event_destroy(event);
  1045. }
  1046. END_TEST
  1047. START_TEST(proximity_range_enter)
  1048. {
  1049. struct litest_device *dev = litest_current_device();
  1050. struct libinput *li = dev->libinput;
  1051. struct axis_replacement axes[] = {
  1052. { ABS_DISTANCE, 90 },
  1053. { -1, -1 },
  1054. };
  1055. litest_drain_events(li);
  1056. litest_with_event_frame(dev) {
  1057. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1058. litest_tablet_proximity_in(dev, 10, 10, axes);
  1059. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  1060. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1061. }
  1062. litest_assert_empty_queue(li);
  1063. litest_axis_set_value(axes, ABS_DISTANCE, 20);
  1064. litest_tablet_motion(dev, 10, 10, axes);
  1065. litest_dispatch(li);
  1066. litest_assert_tablet_proximity_event(li,
  1067. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  1068. litest_axis_set_value(axes, ABS_DISTANCE, 90);
  1069. litest_tablet_motion(dev, 10, 10, axes);
  1070. litest_dispatch(li);
  1071. litest_assert_tablet_proximity_event(li,
  1072. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1073. litest_with_event_frame(dev) {
  1074. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1075. litest_tablet_proximity_out(dev);
  1076. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
  1077. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1078. }
  1079. litest_assert_empty_queue(li);
  1080. }
  1081. END_TEST
  1082. START_TEST(proximity_range_in_out)
  1083. {
  1084. struct litest_device *dev = litest_current_device();
  1085. struct libinput *li = dev->libinput;
  1086. struct axis_replacement axes[] = {
  1087. { ABS_DISTANCE, 20 },
  1088. { -1, -1 },
  1089. };
  1090. litest_drain_events(li);
  1091. litest_with_event_frame(dev) {
  1092. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1093. litest_tablet_proximity_in(dev, 10, 10, axes);
  1094. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  1095. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1096. }
  1097. litest_dispatch(li);
  1098. litest_assert_tablet_proximity_event(li,
  1099. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  1100. litest_axis_set_value(axes, ABS_DISTANCE, 90);
  1101. litest_tablet_motion(dev, 10, 10, axes);
  1102. litest_dispatch(li);
  1103. litest_assert_tablet_proximity_event(li,
  1104. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1105. litest_tablet_motion(dev, 30, 30, axes);
  1106. litest_assert_empty_queue(li);
  1107. litest_axis_set_value(axes, ABS_DISTANCE, 20);
  1108. litest_tablet_motion(dev, 10, 10, axes);
  1109. litest_dispatch(li);
  1110. litest_assert_tablet_proximity_event(li,
  1111. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  1112. litest_with_event_frame(dev) {
  1113. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1114. litest_tablet_proximity_out(dev);
  1115. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
  1116. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1117. }
  1118. litest_timeout_tablet_proxout(li);
  1119. litest_assert_tablet_proximity_event(li,
  1120. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1121. litest_assert_empty_queue(li);
  1122. }
  1123. END_TEST
  1124. START_TEST(proximity_range_button_click)
  1125. {
  1126. struct litest_device *dev = litest_current_device();
  1127. struct libinput *li = dev->libinput;
  1128. struct axis_replacement axes[] = {
  1129. { ABS_DISTANCE, 90 },
  1130. { -1, -1 },
  1131. };
  1132. litest_drain_events(li);
  1133. litest_with_event_frame(dev) {
  1134. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1135. litest_tablet_proximity_in(dev, 10, 10, axes);
  1136. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  1137. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1138. }
  1139. litest_drain_events(li);
  1140. litest_event(dev, EV_KEY, BTN_STYLUS, 1);
  1141. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1142. litest_dispatch(li);
  1143. litest_event(dev, EV_KEY, BTN_STYLUS, 0);
  1144. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1145. litest_dispatch(li);
  1146. litest_with_event_frame(dev) {
  1147. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1148. litest_tablet_proximity_out(dev);
  1149. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
  1150. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1151. }
  1152. litest_timeout_tablet_proxout(li);
  1153. litest_assert_empty_queue(li);
  1154. }
  1155. END_TEST
  1156. START_TEST(proximity_range_button_press)
  1157. {
  1158. struct litest_device *dev = litest_current_device();
  1159. struct libinput *li = dev->libinput;
  1160. struct axis_replacement axes[] = {
  1161. { ABS_DISTANCE, 20 },
  1162. { -1, -1 },
  1163. };
  1164. litest_with_event_frame(dev) {
  1165. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1166. litest_tablet_proximity_in(dev, 10, 10, axes);
  1167. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  1168. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1169. }
  1170. litest_drain_events(li);
  1171. litest_event(dev, EV_KEY, BTN_STYLUS, 1);
  1172. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1173. litest_dispatch(li);
  1174. litest_assert_tablet_button_event(li,
  1175. BTN_STYLUS,
  1176. LIBINPUT_BUTTON_STATE_PRESSED);
  1177. litest_axis_set_value(axes, ABS_DISTANCE, 90);
  1178. litest_tablet_motion(dev, 15, 15, axes);
  1179. litest_dispatch(li);
  1180. /* expect fake button release */
  1181. litest_assert_tablet_button_event(li,
  1182. BTN_STYLUS,
  1183. LIBINPUT_BUTTON_STATE_RELEASED);
  1184. litest_assert_tablet_proximity_event(li,
  1185. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1186. litest_event(dev, EV_KEY, BTN_STYLUS, 0);
  1187. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1188. litest_dispatch(li);
  1189. litest_with_event_frame(dev) {
  1190. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1191. litest_tablet_proximity_out(dev);
  1192. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
  1193. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1194. }
  1195. litest_timeout_tablet_proxout(li);
  1196. litest_assert_empty_queue(li);
  1197. }
  1198. END_TEST
  1199. START_TEST(proximity_range_button_release)
  1200. {
  1201. struct litest_device *dev = litest_current_device();
  1202. struct libinput *li = dev->libinput;
  1203. struct axis_replacement axes[] = {
  1204. { ABS_DISTANCE, 90 },
  1205. { -1, -1 },
  1206. };
  1207. litest_with_event_frame(dev) {
  1208. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1209. litest_tablet_proximity_in(dev, 10, 10, axes);
  1210. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  1211. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1212. }
  1213. litest_drain_events(li);
  1214. litest_event(dev, EV_KEY, BTN_STYLUS, 1);
  1215. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1216. litest_assert_empty_queue(li);
  1217. litest_axis_set_value(axes, ABS_DISTANCE, 20);
  1218. litest_tablet_motion(dev, 15, 15, axes);
  1219. litest_dispatch(li);
  1220. litest_assert_tablet_proximity_event(li,
  1221. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  1222. /* expect fake button press */
  1223. litest_assert_tablet_button_event(li,
  1224. BTN_STYLUS,
  1225. LIBINPUT_BUTTON_STATE_PRESSED);
  1226. litest_assert_empty_queue(li);
  1227. litest_event(dev, EV_KEY, BTN_STYLUS, 0);
  1228. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1229. litest_dispatch(li);
  1230. litest_assert_tablet_button_event(li,
  1231. BTN_STYLUS,
  1232. LIBINPUT_BUTTON_STATE_RELEASED);
  1233. litest_with_event_frame(dev) {
  1234. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1235. litest_tablet_proximity_out(dev);
  1236. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
  1237. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1238. }
  1239. litest_timeout_tablet_proxout(li);
  1240. litest_assert_tablet_proximity_event(li,
  1241. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1242. }
  1243. END_TEST
  1244. START_TEST(proximity_out_slow_event)
  1245. {
  1246. struct litest_device *dev = litest_current_device();
  1247. struct libinput *li = dev->libinput;
  1248. struct axis_replacement axes[] = {
  1249. { ABS_DISTANCE, 90 },
  1250. { -1, -1 },
  1251. };
  1252. litest_tablet_proximity_in(dev, 10, 10, axes);
  1253. litest_tablet_motion(dev, 12, 12, axes);
  1254. litest_drain_events(li);
  1255. litest_timeout_tablet_proxout(li);
  1256. /* The forced prox out */
  1257. litest_assert_tablet_proximity_event(li,
  1258. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1259. litest_assert_empty_queue(li);
  1260. litest_tablet_proximity_out(dev);
  1261. litest_assert_empty_queue(li);
  1262. }
  1263. END_TEST
  1264. START_TEST(proximity_out_not_during_contact)
  1265. {
  1266. struct litest_device *dev = litest_current_device();
  1267. struct libinput *li = dev->libinput;
  1268. struct axis_replacement axes[] = {
  1269. { ABS_DISTANCE, 0 },
  1270. { ABS_PRESSURE, 10 },
  1271. { -1, -1 },
  1272. };
  1273. litest_tablet_proximity_in(dev, 10, 10, axes);
  1274. litest_tablet_tip_down(dev, 10, 10, axes);
  1275. litest_tablet_motion(dev, 12, 12, axes);
  1276. litest_drain_events(li);
  1277. litest_timeout_tablet_proxout(li);
  1278. /* No forced proxout yet */
  1279. litest_assert_empty_queue(li);
  1280. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  1281. litest_tablet_motion(dev, 14, 14, axes);
  1282. litest_tablet_tip_up(dev, 14, 14, axes);
  1283. litest_drain_events(li);
  1284. litest_timeout_tablet_proxout(li);
  1285. /* The forced prox out */
  1286. litest_assert_tablet_proximity_event(li,
  1287. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1288. litest_tablet_proximity_out(dev);
  1289. litest_assert_empty_queue(li);
  1290. }
  1291. END_TEST
  1292. START_TEST(proximity_out_not_during_buttonpress)
  1293. {
  1294. struct litest_device *dev = litest_current_device();
  1295. struct libinput *li = dev->libinput;
  1296. struct axis_replacement axes[] = {
  1297. { ABS_DISTANCE, 10 },
  1298. { ABS_PRESSURE, 0 },
  1299. { -1, -1 },
  1300. };
  1301. litest_tablet_proximity_in(dev, 10, 10, axes);
  1302. litest_tablet_motion(dev, 12, 12, axes);
  1303. litest_drain_events(li);
  1304. litest_event(dev, EV_KEY, BTN_STYLUS, 1);
  1305. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1306. litest_dispatch(li);
  1307. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  1308. litest_timeout_tablet_proxout(li);
  1309. /* No forced proxout yet */
  1310. litest_assert_empty_queue(li);
  1311. litest_event(dev, EV_KEY, BTN_STYLUS, 0);
  1312. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1313. litest_dispatch(li);
  1314. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  1315. litest_timeout_tablet_proxout(li);
  1316. /* The forced prox out */
  1317. litest_assert_tablet_proximity_event(li,
  1318. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1319. litest_tablet_proximity_out(dev);
  1320. litest_assert_empty_queue(li);
  1321. }
  1322. END_TEST
  1323. START_TEST(proximity_out_disables_forced)
  1324. {
  1325. struct litest_device *dev = litest_current_device();
  1326. struct libinput *li = dev->libinput;
  1327. struct axis_replacement axes[] = {
  1328. { ABS_DISTANCE, 10 },
  1329. { ABS_PRESSURE, 0 },
  1330. { -1, -1 },
  1331. };
  1332. /* A correct proximity out sequence from the device should disable
  1333. the forced proximity out */
  1334. litest_tablet_proximity_in(dev, 10, 10, axes);
  1335. litest_tablet_proximity_out(dev);
  1336. litest_drain_events(li);
  1337. /* expect no timeout-based prox out */
  1338. litest_tablet_proximity_in(dev, 10, 10, axes);
  1339. litest_drain_events(li);
  1340. litest_timeout_tablet_proxout(li);
  1341. litest_assert_empty_queue(li);
  1342. litest_tablet_proximity_out(dev);
  1343. litest_assert_tablet_proximity_event(li,
  1344. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1345. litest_dispatch(li);
  1346. }
  1347. END_TEST
  1348. START_TEST(proximity_out_disables_forced_after_forced)
  1349. {
  1350. struct litest_device *dev = litest_current_device();
  1351. struct libinput *li = dev->libinput;
  1352. struct axis_replacement axes[] = {
  1353. { ABS_DISTANCE, 10 },
  1354. { ABS_PRESSURE, 0 },
  1355. { -1, -1 },
  1356. };
  1357. /* A correct proximity out sequence from the device should disable
  1358. the forced proximity out, even when we had a forced prox-out */
  1359. litest_tablet_proximity_in(dev, 10, 10, axes);
  1360. litest_drain_events(li);
  1361. /* timeout-based forced prox out */
  1362. litest_timeout_tablet_proxout(li);
  1363. litest_assert_tablet_proximity_event(li,
  1364. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1365. litest_assert_empty_queue(li);
  1366. /* now send the real prox out (we're already in proximity out) and
  1367. * that should disable the proxout quirk */
  1368. litest_tablet_proximity_out(dev);
  1369. litest_dispatch(li);
  1370. litest_assert_empty_queue(li);
  1371. /* same again, but this time we expect no timeout-based prox out */
  1372. litest_tablet_proximity_in(dev, 10, 10, axes);
  1373. litest_drain_events(li);
  1374. litest_timeout_tablet_proxout(li);
  1375. litest_assert_empty_queue(li);
  1376. litest_tablet_proximity_out(dev);
  1377. litest_assert_tablet_proximity_event(li,
  1378. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1379. litest_dispatch(li);
  1380. }
  1381. END_TEST
  1382. START_TEST(proximity_forced_in_with_eraser_swap)
  1383. {
  1384. struct litest_device *dev = litest_current_device();
  1385. struct libinput *li = dev->libinput;
  1386. struct axis_replacement axes[] = {
  1387. { ABS_DISTANCE, 10 },
  1388. { ABS_PRESSURE, 0 },
  1389. { -1, -1 },
  1390. };
  1391. /* Test doesn't work with a double-tool device */
  1392. if (dev->which == LITEST_ELAN_TABLET)
  1393. return LITEST_NOT_APPLICABLE;
  1394. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
  1395. return LITEST_NOT_APPLICABLE;
  1396. /* https://gitlab.freedesktop.org/libinput/libinput/-/issues/1171:
  1397. * Device sends correct proximity for pen and eraser so both prox timer
  1398. * and double-tool are unregistered. Then it sends a single ABS_X event
  1399. * before an eraser proximity in - ensure that our forced proximity
  1400. * out is immediately removed.
  1401. */
  1402. /* A correct proximity out sequence from the device should disable
  1403. the forced proximity out, even when we had a forced prox-out */
  1404. litest_tablet_proximity_in(dev, 10, 10, axes);
  1405. litest_tablet_proximity_out(dev);
  1406. litest_drain_events(li);
  1407. litest_timeout_tablet_proxout(li);
  1408. /* correct eraser prox out disables forced tool plugin */
  1409. litest_tablet_set_tool_type(dev, BTN_TOOL_RUBBER);
  1410. litest_tablet_proximity_in(dev, 12, 12, axes);
  1411. litest_tablet_proximity_out(dev);
  1412. litest_drain_events(li);
  1413. litest_timeout_tablet_proxout(li);
  1414. litest_dispatch(li);
  1415. litest_log_group("Expecting ABS_X to trigger a proximity event") {
  1416. /* All our tablets have this within their range so hardcoding 100 should
  1417. * be fine here. If this breaks, scale it to absinfo */
  1418. auto abs = libevdev_get_abs_info(dev->evdev, ABS_X);
  1419. int x = absinfo_range(abs) / 3 + abs->minimum;
  1420. litest_event(dev, EV_ABS, ABS_X, x);
  1421. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1422. litest_dispatch(li);
  1423. _destroy_(libinput_event) *pen_in = libinput_get_event(li);
  1424. auto tev = litest_is_proximity_event(
  1425. pen_in,
  1426. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  1427. auto tool = libinput_event_tablet_tool_get_tool(tev);
  1428. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  1429. LIBINPUT_TABLET_TOOL_TYPE_PEN);
  1430. }
  1431. litest_log_group(
  1432. "Expecting eraser prox in to trigger prox out for pen and prox in for eraser") {
  1433. litest_tablet_proximity_in(dev, 15, 15, axes);
  1434. litest_dispatch(li);
  1435. _destroy_(libinput_event) *pen_out = libinput_get_event(li);
  1436. auto tev = litest_is_proximity_event(
  1437. pen_out,
  1438. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1439. auto tool = libinput_event_tablet_tool_get_tool(tev);
  1440. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  1441. LIBINPUT_TABLET_TOOL_TYPE_PEN);
  1442. _destroy_(libinput_event) *eraser_in = libinput_get_event(li);
  1443. tev = litest_is_proximity_event(
  1444. eraser_in,
  1445. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  1446. tool = libinput_event_tablet_tool_get_tool(tev);
  1447. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  1448. LIBINPUT_TABLET_TOOL_TYPE_ERASER);
  1449. }
  1450. litest_assert_empty_queue(li);
  1451. }
  1452. END_TEST
  1453. START_TEST(proximity_out_on_delete)
  1454. {
  1455. _litest_context_destroy_ struct libinput *li = litest_create_context();
  1456. struct litest_device *dev = litest_add_device(li, LITEST_WACOM_INTUOS5_PEN);
  1457. litest_tablet_proximity_in(dev, 10, 10, NULL);
  1458. litest_drain_events(li);
  1459. litest_device_destroy(dev);
  1460. litest_dispatch(li);
  1461. litest_assert_tablet_proximity_event(li,
  1462. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  1463. }
  1464. END_TEST
  1465. START_TEST(motion)
  1466. {
  1467. struct litest_device *dev = litest_current_device();
  1468. struct libinput *li = dev->libinput;
  1469. struct libinput_event_tablet_tool *tablet_event;
  1470. struct libinput_event *event;
  1471. int test_x, test_y;
  1472. double last_reported_x = 0, last_reported_y = 0;
  1473. enum libinput_event_type type;
  1474. struct axis_replacement axes[] = {
  1475. { ABS_DISTANCE, 10 },
  1476. { ABS_PRESSURE, 0 },
  1477. { -1, -1 },
  1478. };
  1479. bool x_changed, y_changed;
  1480. double reported_x, reported_y;
  1481. litest_drain_events(li);
  1482. litest_tablet_proximity_in(dev, 5, 100, axes);
  1483. litest_dispatch(li);
  1484. event = libinput_get_event(li);
  1485. tablet_event =
  1486. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  1487. x_changed = libinput_event_tablet_tool_x_has_changed(tablet_event);
  1488. y_changed = libinput_event_tablet_tool_y_has_changed(tablet_event);
  1489. litest_assert(x_changed);
  1490. litest_assert(y_changed);
  1491. reported_x = libinput_event_tablet_tool_get_x(tablet_event);
  1492. reported_y = libinput_event_tablet_tool_get_y(tablet_event);
  1493. litest_assert_double_lt(reported_x, reported_y);
  1494. last_reported_x = reported_x;
  1495. last_reported_y = reported_y;
  1496. libinput_event_destroy(event);
  1497. for (test_x = 10, test_y = 90; test_x <= 100; test_x += 10, test_y -= 10) {
  1498. bool x_changed, y_changed;
  1499. double reported_x, reported_y;
  1500. litest_tablet_motion(dev, test_x, test_y, axes);
  1501. litest_dispatch(li);
  1502. while ((event = libinput_get_event(li))) {
  1503. tablet_event = libinput_event_get_tablet_tool_event(event);
  1504. type = libinput_event_get_type(event);
  1505. if (type == LIBINPUT_EVENT_TABLET_TOOL_AXIS) {
  1506. x_changed = libinput_event_tablet_tool_x_has_changed(
  1507. tablet_event);
  1508. y_changed = libinput_event_tablet_tool_y_has_changed(
  1509. tablet_event);
  1510. litest_assert(x_changed);
  1511. litest_assert(y_changed);
  1512. reported_x =
  1513. libinput_event_tablet_tool_get_x(tablet_event);
  1514. reported_y =
  1515. libinput_event_tablet_tool_get_y(tablet_event);
  1516. litest_assert_double_gt(reported_x, last_reported_x);
  1517. litest_assert_double_lt(reported_y, last_reported_y);
  1518. last_reported_x = reported_x;
  1519. last_reported_y = reported_y;
  1520. }
  1521. libinput_event_destroy(event);
  1522. }
  1523. }
  1524. }
  1525. END_TEST
  1526. START_TEST(left_handed)
  1527. {
  1528. #ifdef HAVE_LIBWACOM
  1529. struct litest_device *dev = litest_current_device();
  1530. struct libinput *li = dev->libinput;
  1531. struct libinput_event *event;
  1532. struct libinput_event_tablet_tool *tablet_event;
  1533. double libinput_max_x, libinput_max_y;
  1534. double last_x = -1.0, last_y = -1.0;
  1535. double x, y;
  1536. struct axis_replacement axes[] = {
  1537. { ABS_DISTANCE, 10 },
  1538. { ABS_PRESSURE, 0 },
  1539. { -1, -1 },
  1540. };
  1541. litest_drain_events(li);
  1542. litest_assert(
  1543. libinput_device_config_left_handed_is_available(dev->libinput_device));
  1544. libinput_device_get_size(dev->libinput_device,
  1545. &libinput_max_x,
  1546. &libinput_max_y);
  1547. /* Test that left-handed mode doesn't go into effect until the tool has
  1548. * left proximity of the tablet. In order to test this, we have to bring
  1549. * the tool into proximity and make sure libinput processes the
  1550. * proximity events so that it updates it's internal tablet state, and
  1551. * then try setting it to left-handed mode. */
  1552. litest_tablet_proximity_in(dev, 0, 100, axes);
  1553. litest_dispatch(li);
  1554. libinput_device_config_left_handed_set(dev->libinput_device, 1);
  1555. event = libinput_get_event(li);
  1556. tablet_event =
  1557. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  1558. last_x = libinput_event_tablet_tool_get_x(tablet_event);
  1559. last_y = libinput_event_tablet_tool_get_y(tablet_event);
  1560. litest_assert_double_eq(last_x, 0);
  1561. litest_assert_double_eq(last_y, libinput_max_y);
  1562. libinput_event_destroy(event);
  1563. /* work around smoothing */
  1564. litest_axis_set_value(axes, ABS_DISTANCE, 9);
  1565. litest_tablet_motion(dev, 100, 0, axes);
  1566. litest_axis_set_value(axes, ABS_DISTANCE, 7);
  1567. litest_tablet_motion(dev, 100, 0, axes);
  1568. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  1569. litest_tablet_motion(dev, 100, 0, axes);
  1570. litest_drain_events(li);
  1571. litest_axis_set_value(axes, ABS_DISTANCE, 5);
  1572. litest_tablet_motion(dev, 100, 0, axes);
  1573. litest_dispatch(li);
  1574. event = libinput_get_event(li);
  1575. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1576. x = libinput_event_tablet_tool_get_x(tablet_event);
  1577. y = libinput_event_tablet_tool_get_y(tablet_event);
  1578. litest_assert_double_eq(x, libinput_max_x);
  1579. litest_assert_double_eq(y, 0);
  1580. litest_assert_double_gt(x, last_x);
  1581. litest_assert_double_lt(y, last_y);
  1582. libinput_event_destroy(event);
  1583. litest_tablet_proximity_out(dev);
  1584. litest_drain_events(li);
  1585. litest_timeout_tablet_proxout(li);
  1586. /* Since we've drained the events and libinput's aware the tool is out
  1587. * of proximity, it should have finally transitioned into left-handed
  1588. * mode, so the axes should be inverted once we bring it back into
  1589. * proximity */
  1590. litest_tablet_proximity_in(dev, 0, 100, axes);
  1591. litest_dispatch(li);
  1592. event = libinput_get_event(li);
  1593. tablet_event =
  1594. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  1595. last_x = libinput_event_tablet_tool_get_x(tablet_event);
  1596. last_y = libinput_event_tablet_tool_get_y(tablet_event);
  1597. litest_assert_double_eq(last_x, libinput_max_x);
  1598. litest_assert_double_eq(last_y, 0);
  1599. libinput_event_destroy(event);
  1600. /* work around smoothing */
  1601. litest_axis_set_value(axes, ABS_DISTANCE, 9);
  1602. litest_tablet_motion(dev, 100, 0, axes);
  1603. litest_axis_set_value(axes, ABS_DISTANCE, 7);
  1604. litest_tablet_motion(dev, 100, 0, axes);
  1605. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  1606. litest_tablet_motion(dev, 100, 0, axes);
  1607. litest_drain_events(li);
  1608. litest_axis_set_value(axes, ABS_DISTANCE, 5);
  1609. litest_tablet_motion(dev, 100, 0, axes);
  1610. litest_dispatch(li);
  1611. event = libinput_get_event(li);
  1612. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1613. x = libinput_event_tablet_tool_get_x(tablet_event);
  1614. y = libinput_event_tablet_tool_get_y(tablet_event);
  1615. litest_assert_double_eq(x, 0);
  1616. litest_assert_double_eq(y, libinput_max_y);
  1617. litest_assert_double_lt(x, last_x);
  1618. litest_assert_double_gt(y, last_y);
  1619. libinput_event_destroy(event);
  1620. #endif
  1621. }
  1622. END_TEST
  1623. START_TEST(no_left_handed)
  1624. {
  1625. struct litest_device *dev = litest_current_device();
  1626. /* Without libwacom we default to left-handed being available */
  1627. #ifdef HAVE_LIBWACOM
  1628. litest_assert(
  1629. !libinput_device_config_left_handed_is_available(dev->libinput_device));
  1630. #else
  1631. litest_assert(
  1632. libinput_device_config_left_handed_is_available(dev->libinput_device));
  1633. #endif
  1634. }
  1635. END_TEST
  1636. START_TEST(left_handed_tilt)
  1637. {
  1638. #ifdef HAVE_LIBWACOM
  1639. struct litest_device *dev = litest_current_device();
  1640. struct libinput *li = dev->libinput;
  1641. struct libinput_event *event;
  1642. struct libinput_event_tablet_tool *tev;
  1643. enum libinput_config_status status;
  1644. struct axis_replacement axes[] = {
  1645. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 90 },
  1646. { ABS_TILT_Y, 10 }, { -1, -1 },
  1647. };
  1648. double tx, ty;
  1649. status = libinput_device_config_left_handed_set(dev->libinput_device, 1);
  1650. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  1651. litest_drain_events(li);
  1652. litest_tablet_proximity_in(dev, 10, 10, axes);
  1653. litest_dispatch(li);
  1654. event = libinput_get_event(li);
  1655. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  1656. tx = libinput_event_tablet_tool_get_tilt_x(tev);
  1657. ty = libinput_event_tablet_tool_get_tilt_y(tev);
  1658. litest_assert_double_lt(tx, 0);
  1659. litest_assert_double_gt(ty, 0);
  1660. libinput_event_destroy(event);
  1661. #endif
  1662. }
  1663. END_TEST
  1664. static inline double
  1665. rotate_event(struct litest_device *dev, int angle_degrees)
  1666. {
  1667. struct libinput *li = dev->libinput;
  1668. struct libinput_event *event;
  1669. struct libinput_event_tablet_tool *tev;
  1670. const struct input_absinfo *abs;
  1671. double a = (angle_degrees - 90 - 175) / 180.0 * M_PI;
  1672. double val;
  1673. int x, y;
  1674. int tilt_center_x, tilt_center_y;
  1675. abs = libevdev_get_abs_info(dev->evdev, ABS_TILT_X);
  1676. litest_assert_notnull(abs);
  1677. tilt_center_x = absinfo_range(abs) / 2;
  1678. abs = libevdev_get_abs_info(dev->evdev, ABS_TILT_Y);
  1679. litest_assert_notnull(abs);
  1680. tilt_center_y = absinfo_range(abs) / 2;
  1681. x = cos(a) * 20 + tilt_center_x;
  1682. y = sin(a) * 20 + tilt_center_y;
  1683. litest_event(dev, EV_ABS, ABS_TILT_X, x);
  1684. litest_event(dev, EV_ABS, ABS_TILT_Y, y);
  1685. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1686. litest_dispatch(li);
  1687. event = libinput_get_event(li);
  1688. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1689. litest_assert(libinput_event_tablet_tool_rotation_has_changed(tev));
  1690. val = libinput_event_tablet_tool_get_rotation(tev);
  1691. libinput_event_destroy(event);
  1692. litest_assert_empty_queue(li);
  1693. return val;
  1694. }
  1695. START_TEST(left_handed_mouse_rotation)
  1696. {
  1697. #ifdef HAVE_LIBWACOM
  1698. struct litest_device *dev = litest_current_device();
  1699. struct libinput *li = dev->libinput;
  1700. enum libinput_config_status status;
  1701. int angle;
  1702. double val, old_val = 0;
  1703. struct axis_replacement axes[] = {
  1704. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 0 },
  1705. { ABS_TILT_Y, 0 }, { -1, -1 },
  1706. };
  1707. status = libinput_device_config_left_handed_set(dev->libinput_device, 1);
  1708. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  1709. litest_drain_events(li);
  1710. litest_with_event_frame(dev) {
  1711. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1712. litest_tablet_proximity_in(dev, 10, 10, axes);
  1713. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  1714. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  1715. }
  1716. litest_drain_events(li);
  1717. /* cos/sin are 90 degrees offset from the north-is-zero that
  1718. libinput uses. 175 is the CCW offset in the mouse HW */
  1719. for (angle = 185; angle < 540; angle += 5) {
  1720. int expected_angle = angle - 180;
  1721. val = rotate_event(dev, angle % 360);
  1722. /* rounding error galore, we can't test for anything more
  1723. precise than these */
  1724. litest_assert_double_lt(val, 360.0);
  1725. litest_assert_double_gt(val, old_val);
  1726. litest_assert_double_lt(val, expected_angle + 5);
  1727. old_val = val;
  1728. }
  1729. #endif
  1730. }
  1731. END_TEST
  1732. START_TEST(left_handed_artpen_rotation)
  1733. {
  1734. #ifdef HAVE_LIBWACOM
  1735. struct litest_device *dev = litest_current_device();
  1736. struct libinput *li = dev->libinput;
  1737. struct libinput_event *event;
  1738. struct libinput_event_tablet_tool *tev;
  1739. const struct input_absinfo *abs;
  1740. enum libinput_config_status status;
  1741. double val;
  1742. double scale;
  1743. int angle;
  1744. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_Z))
  1745. return LITEST_NOT_APPLICABLE;
  1746. status = libinput_device_config_left_handed_set(dev->libinput_device, 1);
  1747. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  1748. litest_drain_events(li);
  1749. abs = libevdev_get_abs_info(dev->evdev, ABS_Z);
  1750. litest_assert_notnull(abs);
  1751. scale = absinfo_range(abs) / 360.0;
  1752. litest_event(dev, EV_KEY, BTN_TOOL_BRUSH, 1);
  1753. litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
  1754. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  1755. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1756. litest_event(dev, EV_ABS, ABS_Z, abs->minimum);
  1757. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1758. litest_drain_events(li);
  1759. for (angle = 188; angle < 540; angle += 8) {
  1760. int a = angle * scale + abs->minimum;
  1761. int expected_angle = angle - 180;
  1762. litest_event(dev, EV_ABS, ABS_Z, a);
  1763. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1764. litest_dispatch(li);
  1765. event = libinput_get_event(li);
  1766. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1767. litest_assert(libinput_event_tablet_tool_rotation_has_changed(tev));
  1768. val = libinput_event_tablet_tool_get_rotation(tev);
  1769. /* artpen has a 90 deg offset cw */
  1770. litest_assert_int_eq(round(val), (expected_angle + 90) % 360);
  1771. libinput_event_destroy(event);
  1772. litest_assert_empty_queue(li);
  1773. }
  1774. #endif
  1775. }
  1776. END_TEST
  1777. START_TEST(motion_event_state)
  1778. {
  1779. struct litest_device *dev = litest_current_device();
  1780. struct libinput *li = dev->libinput;
  1781. struct libinput_event *event;
  1782. struct libinput_event_tablet_tool *tablet_event;
  1783. int test_x, test_y;
  1784. double last_x, last_y;
  1785. struct axis_replacement axes[] = {
  1786. { ABS_DISTANCE, 10 },
  1787. { ABS_PRESSURE, 0 },
  1788. { -1, -1 },
  1789. };
  1790. unsigned int button = pick_stylus_or_btn0(dev);
  1791. litest_drain_events(li);
  1792. litest_tablet_proximity_in(dev, 5, 100, axes);
  1793. litest_drain_events(li);
  1794. /* couple of events that go left/bottom to right/top */
  1795. for (test_x = 0, test_y = 100; test_x < 100; test_x += 10, test_y -= 10)
  1796. litest_tablet_motion(dev, test_x, test_y, axes);
  1797. litest_dispatch(li);
  1798. event = libinput_get_event(li);
  1799. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1800. last_x = libinput_event_tablet_tool_get_x(tablet_event);
  1801. last_y = libinput_event_tablet_tool_get_y(tablet_event);
  1802. /* mark with a button event, then go back to bottom/left */
  1803. litest_button_click(dev, button, true);
  1804. for (test_x = 100, test_y = 0; test_x > 0; test_x -= 10, test_y += 10)
  1805. litest_tablet_motion(dev, test_x, test_y, axes);
  1806. libinput_event_destroy(event);
  1807. litest_dispatch(li);
  1808. litest_assert_enum_eq(libinput_next_event_type(li),
  1809. LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1810. /* we expect all events up to the button event to go from
  1811. bottom/left to top/right */
  1812. while ((event = libinput_get_event(li))) {
  1813. double x, y;
  1814. if (libinput_event_get_type(event) != LIBINPUT_EVENT_TABLET_TOOL_AXIS)
  1815. break;
  1816. tablet_event = libinput_event_get_tablet_tool_event(event);
  1817. litest_assert_notnull(tablet_event);
  1818. x = libinput_event_tablet_tool_get_x(tablet_event);
  1819. y = libinput_event_tablet_tool_get_y(tablet_event);
  1820. litest_assert(x > last_x);
  1821. litest_assert(y < last_y);
  1822. last_x = x;
  1823. last_y = y;
  1824. libinput_event_destroy(event);
  1825. }
  1826. litest_assert_enum_eq(libinput_event_get_type(event),
  1827. LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  1828. libinput_event_destroy(event);
  1829. }
  1830. END_TEST
  1831. START_TEST(motion_outside_bounds)
  1832. {
  1833. struct litest_device *dev = litest_current_device();
  1834. struct libinput *li = dev->libinput;
  1835. struct libinput_event *event;
  1836. struct libinput_event_tablet_tool *tablet_event;
  1837. double val;
  1838. int i;
  1839. struct axis_replacement axes[] = {
  1840. { ABS_DISTANCE, 10 },
  1841. { ABS_PRESSURE, 0 },
  1842. { -1, -1 },
  1843. };
  1844. litest_tablet_proximity_in(dev, 50, 50, axes);
  1845. litest_drain_events(li);
  1846. /* Work around smoothing */
  1847. for (i = 5; i > 0; i--) {
  1848. litest_event(dev, EV_ABS, ABS_X, 0 + 5 * i);
  1849. litest_event(dev, EV_ABS, ABS_Y, 1000);
  1850. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1851. litest_dispatch(li);
  1852. }
  1853. litest_drain_events(li);
  1854. /* On the 24HD x/y of 0 is outside the limit */
  1855. litest_event(dev, EV_ABS, ABS_X, 0);
  1856. litest_event(dev, EV_ABS, ABS_Y, 1000);
  1857. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1858. litest_dispatch(li);
  1859. event = libinput_get_event(li);
  1860. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1861. val = libinput_event_tablet_tool_get_x(tablet_event);
  1862. litest_assert_double_lt(val, 0.0);
  1863. val = libinput_event_tablet_tool_get_y(tablet_event);
  1864. litest_assert_double_gt(val, 0.0);
  1865. val = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100);
  1866. litest_assert_double_lt(val, 0.0);
  1867. libinput_event_destroy(event);
  1868. /* Work around smoothing */
  1869. for (i = 5; i > 0; i--) {
  1870. litest_event(dev, EV_ABS, ABS_X, 1000);
  1871. litest_event(dev, EV_ABS, ABS_Y, 0 + 5 * i);
  1872. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1873. litest_dispatch(li);
  1874. }
  1875. litest_drain_events(li);
  1876. /* On the 24HD x/y of 0 is outside the limit */
  1877. litest_event(dev, EV_ABS, ABS_X, 1000);
  1878. litest_event(dev, EV_ABS, ABS_Y, 0);
  1879. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1880. litest_dispatch(li);
  1881. event = libinput_get_event(li);
  1882. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  1883. val = libinput_event_tablet_tool_get_x(tablet_event);
  1884. litest_assert_double_gt(val, 0.0);
  1885. val = libinput_event_tablet_tool_get_y(tablet_event);
  1886. litest_assert_double_lt(val, 0.0);
  1887. val = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100);
  1888. litest_assert_double_lt(val, 0.0);
  1889. libinput_event_destroy(event);
  1890. }
  1891. END_TEST
  1892. START_TEST(bad_distance_events)
  1893. {
  1894. struct litest_device *dev = litest_current_device();
  1895. struct libinput *li = dev->libinput;
  1896. const struct input_absinfo *absinfo;
  1897. struct axis_replacement axes[] = {
  1898. { -1, -1 },
  1899. };
  1900. litest_tablet_proximity_in(dev, 10, 10, axes);
  1901. litest_tablet_proximity_out(dev);
  1902. litest_timeout_tablet_proxout(li);
  1903. litest_drain_events(li);
  1904. absinfo = libevdev_get_abs_info(dev->evdev, ABS_DISTANCE);
  1905. litest_assert_notnull(absinfo);
  1906. litest_event(dev, EV_ABS, ABS_DISTANCE, absinfo->maximum);
  1907. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1908. litest_event(dev, EV_ABS, ABS_DISTANCE, absinfo->minimum);
  1909. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1910. litest_assert_empty_queue(li);
  1911. }
  1912. END_TEST
  1913. START_TEST(tool_unique)
  1914. {
  1915. struct litest_device *dev = litest_current_device();
  1916. struct libinput *li = dev->libinput;
  1917. struct libinput_event_tablet_tool *tablet_event;
  1918. struct libinput_event *event;
  1919. struct libinput_tablet_tool *tool;
  1920. litest_drain_events(li);
  1921. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  1922. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  1923. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1924. litest_dispatch(li);
  1925. event = libinput_get_event(li);
  1926. tablet_event =
  1927. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  1928. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  1929. litest_assert(libinput_tablet_tool_is_unique(tool));
  1930. libinput_event_destroy(event);
  1931. }
  1932. END_TEST
  1933. START_TEST(tool_serial)
  1934. {
  1935. struct litest_device *dev = litest_current_device();
  1936. struct libinput *li = dev->libinput;
  1937. struct libinput_event_tablet_tool *tablet_event;
  1938. struct libinput_event *event;
  1939. struct libinput_tablet_tool *tool;
  1940. litest_drain_events(li);
  1941. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  1942. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  1943. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  1944. litest_dispatch(li);
  1945. event = libinput_get_event(li);
  1946. tablet_event =
  1947. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  1948. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  1949. litest_assert_int_eq(libinput_tablet_tool_get_serial(tool), (uint64_t)1000);
  1950. libinput_event_destroy(event);
  1951. }
  1952. END_TEST
  1953. START_TEST(tool_id)
  1954. {
  1955. struct litest_device *dev = litest_current_device();
  1956. struct libinput *li = dev->libinput;
  1957. struct libinput_event_tablet_tool *tablet_event;
  1958. struct libinput_event *event;
  1959. struct libinput_tablet_tool *tool;
  1960. uint64_t tool_id = 0;
  1961. litest_drain_events(li);
  1962. litest_tablet_proximity_in(dev, 10, 10, NULL);
  1963. litest_dispatch(li);
  1964. event = libinput_get_event(li);
  1965. tablet_event =
  1966. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  1967. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  1968. litest_assert_int_eq(libinput_device_get_id_vendor(dev->libinput_device),
  1969. (unsigned int)VENDOR_ID_WACOM);
  1970. switch (libinput_device_get_id_product(dev->libinput_device)) {
  1971. case 0x27: /* Intuos 5 */
  1972. tool_id = 1050626;
  1973. break;
  1974. case 0xc6: /* Cintiq 12WX */
  1975. case 0xf4: /* Cintiq 24HD */
  1976. case 0x333: /* Cintiq 13HD */
  1977. case 0x350: /* Cintiq Pro 16 */
  1978. tool_id = 2083;
  1979. break;
  1980. default:
  1981. litest_abort_msg("Invalid button code");
  1982. }
  1983. litest_assert(tool_id == libinput_tablet_tool_get_tool_id(tool));
  1984. libinput_event_destroy(event);
  1985. }
  1986. END_TEST
  1987. START_TEST(tool_name)
  1988. {
  1989. struct litest_device *dev = litest_current_device();
  1990. struct libinput *li = dev->libinput;
  1991. int tool_id = litest_test_param_get_i32(test_env->params, "tool_id");
  1992. struct axis_replacement axes[] = {
  1993. { ABS_DISTANCE, 10 },
  1994. { ABS_PRESSURE, 0 },
  1995. { ABS_MISC, tool_id },
  1996. { -1, -1 },
  1997. };
  1998. litest_drain_events(li);
  1999. litest_tablet_proximity_in(dev, 10, 10, axes);
  2000. litest_dispatch(li);
  2001. _destroy_(libinput_event) *event = libinput_get_event(li);
  2002. auto tablet_event =
  2003. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2004. auto tool = libinput_event_tablet_tool_get_tool(tablet_event);
  2005. const char *name = libinput_tablet_tool_get_name(tool);
  2006. #ifdef HAVE_LIBWACOM
  2007. switch (tool_id) {
  2008. case 0x823:
  2009. litest_assert_str_eq(name, "Grip Pen");
  2010. break;
  2011. case 0x4802:
  2012. litest_assert_str_eq(name, "Classic Pen");
  2013. break;
  2014. case 0x100902:
  2015. litest_assert_str_eq(name, "Airbrush Pen");
  2016. break;
  2017. default:
  2018. litest_assert_not_reached();
  2019. }
  2020. #else
  2021. litest_assert_ptr_null(name);
  2022. #endif
  2023. }
  2024. END_TEST
  2025. START_TEST(tool_no_name)
  2026. {
  2027. struct litest_device *dev = litest_current_device();
  2028. struct libinput *li = dev->libinput;
  2029. struct axis_replacement axes[] = {
  2030. { ABS_DISTANCE, 10 },
  2031. { ABS_PRESSURE, 0 },
  2032. { -1, -1 },
  2033. };
  2034. litest_drain_events(li);
  2035. litest_tablet_proximity_in(dev, 10, 10, axes);
  2036. litest_dispatch(li);
  2037. _destroy_(libinput_event) *event = libinput_get_event(li);
  2038. auto tablet_event =
  2039. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2040. auto tool = libinput_event_tablet_tool_get_tool(tablet_event);
  2041. const char *name = libinput_tablet_tool_get_name(tool);
  2042. litest_assert_ptr_null(name);
  2043. }
  2044. END_TEST
  2045. START_TEST(serial_changes_tool)
  2046. {
  2047. struct litest_device *dev = litest_current_device();
  2048. struct libinput *li = dev->libinput;
  2049. struct libinput_event_tablet_tool *tablet_event;
  2050. struct libinput_event *event;
  2051. struct libinput_tablet_tool *tool;
  2052. litest_drain_events(li);
  2053. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2054. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2055. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2056. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
  2057. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2058. litest_drain_events(li);
  2059. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2060. litest_event(dev, EV_MSC, MSC_SERIAL, 2000);
  2061. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2062. litest_dispatch(li);
  2063. event = libinput_get_event(li);
  2064. tablet_event =
  2065. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2066. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  2067. litest_assert_int_eq(libinput_tablet_tool_get_serial(tool), (uint64_t)2000);
  2068. libinput_event_destroy(event);
  2069. }
  2070. END_TEST
  2071. START_TEST(invalid_serials)
  2072. {
  2073. struct litest_device *dev = litest_current_device();
  2074. struct libinput *li = dev->libinput;
  2075. struct libinput_event *event;
  2076. struct libinput_event_tablet_tool *tablet_event;
  2077. struct libinput_tablet_tool *tool;
  2078. litest_drain_events(li);
  2079. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2080. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2081. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2082. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
  2083. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2084. litest_drain_events(li);
  2085. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2086. litest_event(dev, EV_MSC, MSC_SERIAL, -1);
  2087. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2088. litest_dispatch(li);
  2089. while ((event = libinput_get_event(li))) {
  2090. if (libinput_event_get_type(event) ==
  2091. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY) {
  2092. tablet_event = libinput_event_get_tablet_tool_event(event);
  2093. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  2094. litest_assert_int_eq(libinput_tablet_tool_get_serial(tool),
  2095. (uint64_t)1000);
  2096. }
  2097. libinput_event_destroy(event);
  2098. }
  2099. }
  2100. END_TEST
  2101. START_TEST(tool_ref)
  2102. {
  2103. struct litest_device *dev = litest_current_device();
  2104. struct libinput *li = dev->libinput;
  2105. struct libinput_event_tablet_tool *tablet_event;
  2106. struct libinput_event *event;
  2107. struct libinput_tablet_tool *tool;
  2108. litest_drain_events(li);
  2109. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2110. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2111. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2112. litest_dispatch(li);
  2113. event = libinput_get_event(li);
  2114. tablet_event =
  2115. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2116. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  2117. litest_assert_notnull(tool);
  2118. litest_assert(tool == libinput_tablet_tool_ref(tool));
  2119. litest_assert(tool == libinput_tablet_tool_unref(tool));
  2120. libinput_event_destroy(event);
  2121. }
  2122. END_TEST
  2123. START_TEST(tool_user_data)
  2124. {
  2125. struct litest_device *dev = litest_current_device();
  2126. struct libinput *li = dev->libinput;
  2127. struct libinput_event_tablet_tool *tablet_event;
  2128. struct libinput_event *event;
  2129. struct libinput_tablet_tool *tool;
  2130. void *userdata = &dev; /* not dereferenced */
  2131. litest_drain_events(li);
  2132. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2133. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2134. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2135. litest_dispatch(li);
  2136. event = libinput_get_event(li);
  2137. tablet_event =
  2138. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2139. tool = libinput_event_tablet_tool_get_tool(tablet_event);
  2140. litest_assert_notnull(tool);
  2141. litest_assert(libinput_tablet_tool_get_user_data(tool) == NULL);
  2142. libinput_tablet_tool_set_user_data(tool, userdata);
  2143. litest_assert(libinput_tablet_tool_get_user_data(tool) == userdata);
  2144. libinput_tablet_tool_set_user_data(tool, NULL);
  2145. litest_assert(libinput_tablet_tool_get_user_data(tool) == NULL);
  2146. libinput_event_destroy(event);
  2147. }
  2148. END_TEST
  2149. START_TEST(pad_buttons_ignored)
  2150. {
  2151. struct litest_device *dev = litest_current_device();
  2152. struct libinput *li = dev->libinput;
  2153. struct axis_replacement axes[] = {
  2154. { ABS_DISTANCE, 10 },
  2155. { ABS_PRESSURE, 0 },
  2156. { -1, -1 },
  2157. };
  2158. int button;
  2159. litest_drain_events(li);
  2160. for (button = BTN_0; button < BTN_MOUSE; button++) {
  2161. litest_event(dev, EV_KEY, button, 1);
  2162. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2163. litest_event(dev, EV_KEY, button, 0);
  2164. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2165. litest_dispatch(li);
  2166. }
  2167. litest_assert_empty_queue(li);
  2168. /* same thing while in prox */
  2169. litest_tablet_proximity_in(dev, 10, 10, axes);
  2170. litest_drain_events(li);
  2171. for (button = BTN_0; button < BTN_MOUSE; button++)
  2172. litest_event(dev, EV_KEY, button, 1);
  2173. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2174. litest_dispatch(li);
  2175. for (button = BTN_0; button < BTN_MOUSE; button++)
  2176. litest_event(dev, EV_KEY, button, 0);
  2177. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2178. litest_dispatch(li);
  2179. litest_assert_empty_queue(li);
  2180. }
  2181. END_TEST
  2182. START_TEST(tools_with_serials)
  2183. {
  2184. _litest_context_destroy_ struct libinput *li = litest_create_context();
  2185. struct litest_device *dev[2];
  2186. struct libinput_tablet_tool *tool[2] = { 0 };
  2187. struct libinput_event *event;
  2188. struct libinput_event_tablet_tool *tev;
  2189. int i;
  2190. for (i = 0; i < 2; i++) {
  2191. dev[i] = litest_add_device(li, LITEST_WACOM_INTUOS5_PEN);
  2192. litest_drain_events(li);
  2193. /* WARNING: this test fails if UI_GET_SYSNAME isn't
  2194. * available or isn't used by libevdev (1.3, commit 2ff45c73).
  2195. * Put a sleep(1) here and that usually fixes it.
  2196. */
  2197. litest_with_event_frame(dev[i]) {
  2198. litest_tablet_proximity_in(dev[i], 10, 10, NULL);
  2199. litest_event(dev[i], EV_MSC, MSC_SERIAL, 100);
  2200. }
  2201. litest_dispatch(li);
  2202. event = libinput_get_event(li);
  2203. tev = litest_is_tablet_event(event,
  2204. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2205. tool[i] = libinput_event_tablet_tool_get_tool(tev);
  2206. libinput_event_destroy(event);
  2207. }
  2208. /* We should get the same object for both devices */
  2209. litest_assert_notnull(tool[0]);
  2210. litest_assert_notnull(tool[1]);
  2211. litest_assert_ptr_eq(tool[0], tool[1]);
  2212. litest_device_destroy(dev[0]);
  2213. litest_device_destroy(dev[1]);
  2214. }
  2215. END_TEST
  2216. START_TEST(tools_without_serials)
  2217. {
  2218. _litest_context_destroy_ struct libinput *li = litest_create_context();
  2219. struct litest_device *dev[2];
  2220. struct libinput_tablet_tool *tool[2] = { 0 };
  2221. struct libinput_event *event;
  2222. struct libinput_event_tablet_tool *tev;
  2223. int i;
  2224. for (i = 0; i < 2; i++) {
  2225. dev[i] = litest_add_device_with_overrides(li,
  2226. LITEST_WACOM_ISDV4_E6_PEN,
  2227. NULL,
  2228. NULL,
  2229. NULL,
  2230. NULL);
  2231. litest_drain_events(li);
  2232. /* WARNING: this test fails if UI_GET_SYSNAME isn't
  2233. * available or isn't used by libevdev (1.3, commit 2ff45c73).
  2234. * Put a sleep(1) here and that usually fixes it.
  2235. */
  2236. litest_tablet_proximity_in(dev[i], 10, 10, NULL);
  2237. litest_dispatch(li);
  2238. event = libinput_get_event(li);
  2239. tev = litest_is_tablet_event(event,
  2240. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2241. tool[i] = libinput_event_tablet_tool_get_tool(tev);
  2242. libinput_event_destroy(event);
  2243. }
  2244. /* We should get different tool objects for each device */
  2245. litest_assert_notnull(tool[0]);
  2246. litest_assert_notnull(tool[1]);
  2247. litest_assert_ptr_ne(tool[0], tool[1]);
  2248. litest_device_destroy(dev[0]);
  2249. litest_device_destroy(dev[1]);
  2250. }
  2251. END_TEST
  2252. START_TEST(tool_delayed_serial)
  2253. {
  2254. struct litest_device *dev = litest_current_device();
  2255. struct libinput *li = dev->libinput;
  2256. struct libinput_event *event;
  2257. struct libinput_event_tablet_tool *tev;
  2258. struct libinput_tablet_tool *tool;
  2259. unsigned int serial;
  2260. litest_drain_events(li);
  2261. litest_event(dev, EV_ABS, ABS_X, 4500);
  2262. litest_event(dev, EV_ABS, ABS_Y, 2000);
  2263. litest_event(dev, EV_MSC, MSC_SERIAL, 0);
  2264. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2265. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2266. litest_dispatch(li);
  2267. event = libinput_get_event(li);
  2268. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2269. tool = libinput_event_tablet_tool_get_tool(tev);
  2270. serial = libinput_tablet_tool_get_serial(tool);
  2271. litest_assert_int_eq(serial, (uint64_t)0);
  2272. libinput_event_destroy(event);
  2273. for (int x = 4500; x < 8000; x += 1000) {
  2274. litest_event(dev, EV_ABS, ABS_X, x);
  2275. litest_event(dev, EV_ABS, ABS_Y, 2000);
  2276. litest_event(dev, EV_MSC, MSC_SERIAL, 0);
  2277. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2278. litest_dispatch(li);
  2279. }
  2280. litest_drain_events(li);
  2281. /* Now send the serial */
  2282. litest_event(dev, EV_ABS, ABS_X, 4500);
  2283. litest_event(dev, EV_ABS, ABS_Y, 2000);
  2284. litest_event(dev, EV_MSC, MSC_SERIAL, 1234566);
  2285. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2286. litest_dispatch(li);
  2287. event = libinput_get_event(li);
  2288. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2289. tool = libinput_event_tablet_tool_get_tool(tev);
  2290. serial = libinput_tablet_tool_get_serial(tool);
  2291. litest_assert_int_eq(serial, (uint64_t)0);
  2292. libinput_event_destroy(event);
  2293. for (int x = 4500; x < 8000; x += 500) {
  2294. litest_event(dev, EV_ABS, ABS_X, x);
  2295. litest_event(dev, EV_ABS, ABS_Y, 2000);
  2296. litest_event(dev, EV_MSC, MSC_SERIAL, 1234566);
  2297. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2298. litest_dispatch(li);
  2299. }
  2300. event = libinput_get_event(li);
  2301. do {
  2302. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2303. tool = libinput_event_tablet_tool_get_tool(tev);
  2304. serial = libinput_tablet_tool_get_serial(tool);
  2305. litest_assert_int_eq(serial, (uint64_t)0);
  2306. libinput_event_destroy(event);
  2307. event = libinput_get_event(li);
  2308. } while (event != NULL);
  2309. /* Quirk: tool out event is a serial of 0 */
  2310. litest_event(dev, EV_ABS, ABS_X, 4500);
  2311. litest_event(dev, EV_ABS, ABS_Y, 2000);
  2312. litest_event(dev, EV_MSC, MSC_SERIAL, 0);
  2313. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
  2314. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2315. litest_dispatch(li);
  2316. event = libinput_get_event(li);
  2317. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2318. tool = libinput_event_tablet_tool_get_tool(tev);
  2319. serial = libinput_tablet_tool_get_serial(tool);
  2320. litest_assert_int_eq(serial, (uint64_t)0);
  2321. libinput_event_destroy(event);
  2322. }
  2323. END_TEST
  2324. START_TEST(tool_capability)
  2325. {
  2326. struct litest_device *dev = litest_current_device();
  2327. struct libinput_device *device = dev->libinput_device;
  2328. litest_assert(libinput_device_has_capability(device,
  2329. LIBINPUT_DEVICE_CAP_TABLET_TOOL));
  2330. }
  2331. END_TEST
  2332. START_TEST(tool_capabilities)
  2333. {
  2334. _litest_context_destroy_ struct libinput *li = litest_create_context();
  2335. struct litest_device *intuos;
  2336. struct litest_device *bamboo;
  2337. struct libinput_event *event;
  2338. struct libinput_event_tablet_tool *t;
  2339. struct libinput_tablet_tool *tool;
  2340. /* The axis capabilities of a tool can differ depending on the type of
  2341. * tablet the tool is being used with */
  2342. bamboo = litest_add_device(li, LITEST_WACOM_BAMBOO_16FG_PEN);
  2343. intuos = litest_add_device(li, LITEST_WACOM_INTUOS5_PEN);
  2344. litest_drain_events(li);
  2345. litest_event(bamboo, EV_KEY, BTN_TOOL_PEN, 1);
  2346. litest_event(bamboo, EV_SYN, SYN_REPORT, 0);
  2347. litest_dispatch(li);
  2348. event = libinput_get_event(li);
  2349. t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2350. tool = libinput_event_tablet_tool_get_tool(t);
  2351. litest_assert(libinput_tablet_tool_has_pressure(tool));
  2352. litest_assert(libinput_tablet_tool_has_distance(tool));
  2353. litest_assert(!libinput_tablet_tool_has_tilt(tool));
  2354. libinput_event_destroy(event);
  2355. litest_assert_empty_queue(li);
  2356. litest_event(intuos, EV_KEY, BTN_TOOL_PEN, 1);
  2357. litest_event(intuos, EV_SYN, SYN_REPORT, 0);
  2358. litest_dispatch(li);
  2359. event = libinput_get_event(li);
  2360. t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2361. tool = libinput_event_tablet_tool_get_tool(t);
  2362. litest_assert(libinput_tablet_tool_has_pressure(tool));
  2363. litest_assert(libinput_tablet_tool_has_distance(tool));
  2364. litest_assert(libinput_tablet_tool_has_tilt(tool));
  2365. libinput_event_destroy(event);
  2366. litest_assert_empty_queue(li);
  2367. litest_device_destroy(bamboo);
  2368. litest_device_destroy(intuos);
  2369. }
  2370. END_TEST
  2371. static inline bool
  2372. tablet_has_mouse(struct litest_device *dev)
  2373. {
  2374. return libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_MOUSE) &&
  2375. libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM;
  2376. }
  2377. START_TEST(tool_type)
  2378. {
  2379. struct litest_device *dev = litest_current_device();
  2380. struct libinput *li = dev->libinput;
  2381. struct libinput_event *event;
  2382. struct libinput_event_tablet_tool *t;
  2383. struct libinput_tablet_tool *tool;
  2384. struct axis_replacement axes[] = {
  2385. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 0 },
  2386. { ABS_TILT_Y, 0 }, { -1, -1 },
  2387. };
  2388. struct tool_type_match {
  2389. int code;
  2390. enum libinput_tablet_tool_type type;
  2391. } types[] = {
  2392. { BTN_TOOL_PEN, LIBINPUT_TABLET_TOOL_TYPE_PEN },
  2393. { BTN_TOOL_RUBBER, LIBINPUT_TABLET_TOOL_TYPE_ERASER },
  2394. { BTN_TOOL_BRUSH, LIBINPUT_TABLET_TOOL_TYPE_BRUSH },
  2395. { BTN_TOOL_PENCIL, LIBINPUT_TABLET_TOOL_TYPE_PENCIL },
  2396. { BTN_TOOL_AIRBRUSH, LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH },
  2397. { BTN_TOOL_MOUSE, LIBINPUT_TABLET_TOOL_TYPE_MOUSE },
  2398. { BTN_TOOL_LENS, LIBINPUT_TABLET_TOOL_TYPE_LENS },
  2399. { -1, -1 },
  2400. };
  2401. struct tool_type_match *tt;
  2402. double x = 50, y = 50;
  2403. litest_drain_events(li);
  2404. for (tt = types; tt->code != -1; tt++) {
  2405. enum libinput_tablet_tool_type type;
  2406. if (!libevdev_has_event_code(dev->evdev, EV_KEY, tt->code))
  2407. continue;
  2408. if ((tt->code == BTN_TOOL_MOUSE || tt->code == BTN_TOOL_LENS) &&
  2409. !tablet_has_mouse(dev))
  2410. continue;
  2411. litest_tablet_set_tool_type(dev, tt->code);
  2412. litest_tablet_proximity_in(dev, x, y, axes);
  2413. litest_dispatch(li);
  2414. event = libinput_get_event(li);
  2415. t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2416. tool = libinput_event_tablet_tool_get_tool(t);
  2417. type = libinput_tablet_tool_get_type(tool);
  2418. /* Devices with doubled-up tool bits send the pen
  2419. * in-prox and immediately out-of-prox before the real tool
  2420. * type. Drop those two and continue with what we expect is
  2421. * the real prox in event */
  2422. if (tt->type != LIBINPUT_TABLET_TOOL_TYPE_PEN &&
  2423. type == LIBINPUT_TABLET_TOOL_TYPE_PEN) {
  2424. libinput_event_destroy(event);
  2425. event = libinput_get_event(li);
  2426. litest_is_tablet_event(event,
  2427. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2428. libinput_event_destroy(event);
  2429. event = libinput_get_event(li);
  2430. t = litest_is_tablet_event(
  2431. event,
  2432. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2433. tool = libinput_event_tablet_tool_get_tool(t);
  2434. type = libinput_tablet_tool_get_type(tool);
  2435. }
  2436. litest_assert_int_eq(type, tt->type);
  2437. libinput_event_destroy(event);
  2438. litest_assert_empty_queue(li);
  2439. litest_tablet_proximity_out(dev);
  2440. litest_timeout_tablet_proxout(li);
  2441. litest_drain_events(li);
  2442. x++;
  2443. y++;
  2444. }
  2445. }
  2446. END_TEST
  2447. START_TEST(tool_in_prox_before_start)
  2448. {
  2449. struct litest_device *dev = litest_current_device();
  2450. struct libinput_event *event;
  2451. struct libinput_event_tablet_tool *tev;
  2452. struct libinput_tablet_tool *tool;
  2453. struct axis_replacement axes[] = {
  2454. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 0 },
  2455. { ABS_TILT_Y, 0 }, { -1, -1 },
  2456. };
  2457. const char *devnode;
  2458. uint64_t serial;
  2459. litest_tablet_proximity_in(dev, 10, 10, axes);
  2460. /* for simplicity, we create a new litest context */
  2461. devnode = libevdev_uinput_get_devnode(dev->uinput);
  2462. _litest_context_destroy_ struct libinput *li = litest_create_context();
  2463. libinput_path_add_device(li, devnode);
  2464. litest_drain_events_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED);
  2465. litest_assert_empty_queue(li);
  2466. litest_tablet_motion(dev, 10, 20, axes);
  2467. litest_dispatch(li);
  2468. event = libinput_get_event(li);
  2469. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2470. tool = libinput_event_tablet_tool_get_tool(tev);
  2471. serial = libinput_tablet_tool_get_serial(tool);
  2472. libinput_event_destroy(event);
  2473. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  2474. litest_tablet_motion(dev, 30, 40, axes);
  2475. litest_dispatch(li);
  2476. event = libinput_get_event(li);
  2477. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2478. tool = libinput_event_tablet_tool_get_tool(tev);
  2479. litest_assert_int_eq(serial, libinput_tablet_tool_get_serial(tool));
  2480. libinput_event_destroy(event);
  2481. litest_assert_empty_queue(li);
  2482. litest_button_click(dev, BTN_STYLUS, true);
  2483. litest_button_click(dev, BTN_STYLUS, false);
  2484. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  2485. litest_tablet_proximity_out(dev);
  2486. litest_timeout_tablet_proxout(li);
  2487. event = libinput_get_event(li);
  2488. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2489. libinput_event_destroy(event);
  2490. }
  2491. END_TEST
  2492. START_TEST(tool_direct_switch_skip_tool_update)
  2493. {
  2494. struct litest_device *dev = litest_current_device();
  2495. struct libinput *li = dev->libinput;
  2496. struct libinput_event *event;
  2497. struct libinput_event_tablet_tool *tev;
  2498. struct libinput_tablet_tool *pen = NULL, *eraser = NULL;
  2499. struct axis_replacement axes[] = {
  2500. { ABS_DISTANCE, 10 },
  2501. { ABS_PRESSURE, 0 },
  2502. { -1, -1 },
  2503. };
  2504. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
  2505. return LITEST_NOT_APPLICABLE;
  2506. litest_drain_events(li);
  2507. litest_tablet_proximity_in(dev, 10, 10, axes);
  2508. litest_dispatch(li);
  2509. event = libinput_get_event(li);
  2510. tev = litest_is_proximity_event(event, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  2511. pen = libinput_event_tablet_tool_get_tool(tev);
  2512. libinput_tablet_tool_ref(pen);
  2513. libinput_event_destroy(event);
  2514. litest_checkpoint("Switching directly to eraser");
  2515. litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
  2516. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2517. litest_dispatch(li);
  2518. litest_checkpoint("Expecting pen prox out followed by eraser prox in ");
  2519. event = libinput_get_event(li);
  2520. tev = litest_is_proximity_event(event,
  2521. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  2522. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), pen);
  2523. libinput_event_destroy(event);
  2524. event = libinput_get_event(li);
  2525. tev = litest_is_proximity_event(event, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  2526. litest_assert_ptr_ne(libinput_event_tablet_tool_get_tool(tev), pen);
  2527. eraser = libinput_event_tablet_tool_get_tool(tev);
  2528. libinput_tablet_tool_ref(eraser);
  2529. libinput_event_destroy(event);
  2530. litest_tablet_motion(dev, 20, 30, axes);
  2531. litest_dispatch(li);
  2532. event = libinput_get_event(li);
  2533. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2534. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), eraser);
  2535. libinput_event_destroy(event);
  2536. litest_checkpoint("Switching directly to pen, expecting eraser prox out");
  2537. litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
  2538. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2539. litest_dispatch(li);
  2540. event = libinput_get_event(li);
  2541. tev = litest_is_proximity_event(event,
  2542. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  2543. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), eraser);
  2544. libinput_event_destroy(event);
  2545. litest_with_event_frame(dev) {
  2546. litest_checkpoint("Prox in for eraser (pen still in prox)");
  2547. litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
  2548. litest_tablet_motion(dev, 30, 40, axes);
  2549. }
  2550. litest_dispatch(li);
  2551. event = libinput_get_event(li);
  2552. tev = litest_is_proximity_event(event, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  2553. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), eraser);
  2554. libinput_event_destroy(event);
  2555. litest_tablet_motion(dev, 40, 30, axes);
  2556. litest_dispatch(li);
  2557. event = libinput_get_event(li);
  2558. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2559. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), eraser);
  2560. libinput_event_destroy(event);
  2561. litest_with_event_frame(dev) {
  2562. litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
  2563. litest_tablet_proximity_out(dev);
  2564. }
  2565. litest_timeout_tablet_proxout(li);
  2566. event = libinput_get_event(li);
  2567. tev = litest_is_proximity_event(event,
  2568. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  2569. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), eraser);
  2570. libinput_event_destroy(event);
  2571. litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
  2572. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2573. litest_assert_empty_queue(li);
  2574. libinput_tablet_tool_unref(eraser);
  2575. libinput_tablet_tool_unref(pen);
  2576. }
  2577. END_TEST
  2578. START_TEST(tool_direct_switch_with_forced_proxout)
  2579. {
  2580. struct litest_device *dev = litest_current_device();
  2581. struct libinput *li = dev->libinput;
  2582. struct axis_replacement axes[] = {
  2583. { ABS_DISTANCE, 10 },
  2584. { ABS_PRESSURE, 0 },
  2585. { -1, -1 },
  2586. };
  2587. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
  2588. return LITEST_NOT_APPLICABLE;
  2589. litest_drain_events(li);
  2590. /* This is a *very* specific event sequence to trigger a bug:
  2591. - pen proximity in
  2592. - pen proximity forced out
  2593. - eraser proximity in without axis movement
  2594. - eraser axis move
  2595. */
  2596. /* pen prox in */
  2597. litest_tablet_proximity_in(dev, 10, 10, axes);
  2598. litest_dispatch(li);
  2599. litest_assert_tablet_proximity_event(li,
  2600. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  2601. /* pen motion */
  2602. litest_tablet_motion(dev, 20, 30, axes);
  2603. litest_dispatch(li);
  2604. litest_assert_tablet_axis_event(li);
  2605. litest_checkpoint("Forcing a timeout prox-out");
  2606. /* pen forced prox out */
  2607. litest_timeout_tablet_proxout(li);
  2608. litest_checkpoint("Actual prox-out");
  2609. /* actual prox out for tablets that don't do forced prox out */
  2610. litest_tablet_proximity_out(dev);
  2611. litest_timeout_tablet_proxout(li);
  2612. litest_assert_tablet_proximity_event(li,
  2613. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  2614. litest_assert_empty_queue(li);
  2615. /* eraser prox in without axes */
  2616. litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
  2617. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2618. litest_dispatch(li);
  2619. litest_assert_tablet_proximity_event(li,
  2620. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  2621. /* eraser motion */
  2622. litest_tablet_motion(dev, 30, 40, axes);
  2623. litest_tablet_motion(dev, 40, 50, axes);
  2624. litest_dispatch(li);
  2625. litest_assert_tablet_axis_event(li);
  2626. litest_assert_tablet_axis_event(li);
  2627. litest_assert_empty_queue(li);
  2628. }
  2629. END_TEST
  2630. START_TEST(stylus_buttons)
  2631. {
  2632. struct litest_device *dev = litest_current_device();
  2633. struct libinput *li = dev->libinput;
  2634. struct libinput_event *event;
  2635. struct libinput_event_tablet_tool *tev;
  2636. struct libinput_tablet_tool *tool;
  2637. uint32_t stylus_buttons[] = { BTN_STYLUS, BTN_STYLUS2, BTN_STYLUS3 };
  2638. litest_drain_events(li);
  2639. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2640. litest_event(dev, EV_ABS, ABS_MISC, 0x200); /* 3-button stylus tool_id */
  2641. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2642. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2643. litest_dispatch(li);
  2644. event = libinput_get_event(li);
  2645. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2646. tool = libinput_event_tablet_tool_get_tool(tev);
  2647. litest_assert_notnull(tool);
  2648. libinput_tablet_tool_ref(tool);
  2649. libinput_event_destroy(event);
  2650. ARRAY_FOR_EACH(stylus_buttons, code) {
  2651. litest_event(dev, EV_KEY, *code, 1);
  2652. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2653. litest_dispatch(li);
  2654. litest_event(dev, EV_KEY, *code, 0);
  2655. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2656. litest_dispatch(li);
  2657. litest_assert_tablet_button_event(li,
  2658. *code,
  2659. LIBINPUT_BUTTON_STATE_PRESSED);
  2660. litest_assert_tablet_button_event(li,
  2661. *code,
  2662. LIBINPUT_BUTTON_STATE_RELEASED);
  2663. }
  2664. libinput_tablet_tool_unref(tool);
  2665. }
  2666. END_TEST
  2667. START_TEST(mouse_tool)
  2668. {
  2669. struct litest_device *dev = litest_current_device();
  2670. struct libinput *li = dev->libinput;
  2671. struct libinput_event *event;
  2672. struct libinput_event_tablet_tool *tev;
  2673. struct libinput_tablet_tool *tool;
  2674. litest_drain_events(li);
  2675. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  2676. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2677. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2678. litest_dispatch(li);
  2679. event = libinput_get_event(li);
  2680. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2681. tool = libinput_event_tablet_tool_get_tool(tev);
  2682. litest_assert_notnull(tool);
  2683. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  2684. LIBINPUT_TABLET_TOOL_TYPE_MOUSE);
  2685. libinput_event_destroy(event);
  2686. }
  2687. END_TEST
  2688. START_TEST(mouse_buttons)
  2689. {
  2690. struct litest_device *dev = litest_current_device();
  2691. struct libinput *li = dev->libinput;
  2692. struct libinput_event *event;
  2693. struct libinput_event_tablet_tool *tev;
  2694. struct libinput_tablet_tool *tool;
  2695. int code;
  2696. litest_drain_events(li);
  2697. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  2698. litest_event(dev, EV_ABS, ABS_MISC, 0x806); /* 5-button mouse tool_id */
  2699. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2700. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2701. litest_dispatch(li);
  2702. event = libinput_get_event(li);
  2703. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2704. tool = libinput_event_tablet_tool_get_tool(tev);
  2705. litest_assert_notnull(tool);
  2706. libinput_tablet_tool_ref(tool);
  2707. libinput_event_destroy(event);
  2708. for (code = BTN_LEFT; code <= BTN_TASK; code++) {
  2709. bool has_button = libevdev_has_event_code(dev->evdev, EV_KEY, code);
  2710. litest_assert_int_eq(!!has_button,
  2711. !!libinput_tablet_tool_has_button(tool, code));
  2712. if (!has_button)
  2713. continue;
  2714. litest_event(dev, EV_KEY, code, 1);
  2715. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2716. litest_dispatch(li);
  2717. litest_event(dev, EV_KEY, code, 0);
  2718. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2719. litest_dispatch(li);
  2720. litest_assert_tablet_button_event(li,
  2721. code,
  2722. LIBINPUT_BUTTON_STATE_PRESSED);
  2723. litest_assert_tablet_button_event(li,
  2724. code,
  2725. LIBINPUT_BUTTON_STATE_RELEASED);
  2726. }
  2727. libinput_tablet_tool_unref(tool);
  2728. }
  2729. END_TEST
  2730. START_TEST(mouse_rotation)
  2731. {
  2732. struct litest_device *dev = litest_current_device();
  2733. struct libinput *li = dev->libinput;
  2734. int angle;
  2735. double val, old_val = 0;
  2736. struct axis_replacement axes[] = {
  2737. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 0 },
  2738. { ABS_TILT_Y, 0 }, { -1, -1 },
  2739. };
  2740. litest_drain_events(li);
  2741. litest_with_event_frame(dev) {
  2742. litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
  2743. litest_tablet_proximity_in(dev, 10, 10, axes);
  2744. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  2745. litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
  2746. }
  2747. litest_drain_events(li);
  2748. /* cos/sin are 90 degrees offset from the north-is-zero that
  2749. libinput uses. 175 is the CCW offset in the mouse HW */
  2750. for (angle = 5; angle < 360; angle += 5) {
  2751. val = rotate_event(dev, angle);
  2752. /* rounding error galore, we can't test for anything more
  2753. precise than these */
  2754. litest_assert_double_lt(val, 360.0);
  2755. litest_assert_double_gt(val, old_val);
  2756. litest_assert_double_lt(val, angle + 5);
  2757. old_val = val;
  2758. }
  2759. }
  2760. END_TEST
  2761. START_TEST(mouse_wheel)
  2762. {
  2763. struct litest_device *dev = litest_current_device();
  2764. struct libinput *li = dev->libinput;
  2765. struct libinput_event *event;
  2766. struct libinput_event_tablet_tool *tev;
  2767. struct libinput_tablet_tool *tool;
  2768. const struct input_absinfo *abs;
  2769. double val;
  2770. int i;
  2771. if (!libevdev_has_event_code(dev->evdev, EV_REL, REL_WHEEL))
  2772. return LITEST_NOT_APPLICABLE;
  2773. litest_drain_events(li);
  2774. litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
  2775. litest_event(dev, EV_ABS, ABS_MISC, 0x806); /* 5-button mouse tool_id */
  2776. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2777. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2778. litest_dispatch(li);
  2779. event = libinput_get_event(li);
  2780. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2781. tool = libinput_event_tablet_tool_get_tool(tev);
  2782. litest_assert_notnull(tool);
  2783. libinput_tablet_tool_ref(tool);
  2784. libinput_event_destroy(event);
  2785. litest_assert(libinput_tablet_tool_has_wheel(tool));
  2786. for (i = 0; i < 3; i++) {
  2787. litest_event(dev, EV_REL, REL_WHEEL, -1);
  2788. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2789. litest_dispatch(li);
  2790. event = libinput_get_event(li);
  2791. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2792. litest_assert(libinput_event_tablet_tool_wheel_has_changed(tev));
  2793. val = libinput_event_tablet_tool_get_wheel_delta(tev);
  2794. litest_assert_int_eq(val, 15);
  2795. val = libinput_event_tablet_tool_get_wheel_delta_discrete(tev);
  2796. litest_assert_int_eq(val, 1);
  2797. libinput_event_destroy(event);
  2798. litest_assert_empty_queue(li);
  2799. }
  2800. for (i = 2; i < 5; i++) {
  2801. /* send x/y events to make sure we reset the wheel */
  2802. abs = libevdev_get_abs_info(dev->evdev, ABS_X);
  2803. litest_event(dev, EV_ABS, ABS_X, absinfo_range(abs) / i);
  2804. abs = libevdev_get_abs_info(dev->evdev, ABS_Y);
  2805. litest_event(dev, EV_ABS, ABS_Y, absinfo_range(abs) / i);
  2806. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2807. litest_dispatch(li);
  2808. event = libinput_get_event(li);
  2809. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2810. litest_assert(!libinput_event_tablet_tool_wheel_has_changed(tev));
  2811. val = libinput_event_tablet_tool_get_wheel_delta(tev);
  2812. litest_assert_int_eq(val, 0);
  2813. val = libinput_event_tablet_tool_get_wheel_delta_discrete(tev);
  2814. litest_assert_int_eq(val, 0);
  2815. libinput_event_destroy(event);
  2816. litest_assert_empty_queue(li);
  2817. }
  2818. libinput_tablet_tool_unref(tool);
  2819. }
  2820. END_TEST
  2821. START_TEST(airbrush_tool)
  2822. {
  2823. struct litest_device *dev = litest_current_device();
  2824. struct libinput *li = dev->libinput;
  2825. struct libinput_event *event;
  2826. struct libinput_event_tablet_tool *tev;
  2827. struct libinput_tablet_tool *tool;
  2828. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_AIRBRUSH))
  2829. return LITEST_NOT_APPLICABLE;
  2830. litest_drain_events(li);
  2831. litest_event(dev, EV_KEY, BTN_TOOL_AIRBRUSH, 1);
  2832. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2833. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2834. litest_dispatch(li);
  2835. event = libinput_get_event(li);
  2836. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2837. tool = libinput_event_tablet_tool_get_tool(tev);
  2838. litest_assert_notnull(tool);
  2839. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  2840. LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH);
  2841. litest_assert(libinput_tablet_tool_has_slider(tool));
  2842. libinput_event_destroy(event);
  2843. }
  2844. END_TEST
  2845. START_TEST(airbrush_slider)
  2846. {
  2847. struct litest_device *dev = litest_current_device();
  2848. struct libinput *li = dev->libinput;
  2849. struct libinput_event *event;
  2850. struct libinput_event_tablet_tool *tev;
  2851. const struct input_absinfo *abs;
  2852. double val;
  2853. int v;
  2854. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_AIRBRUSH))
  2855. return LITEST_NOT_APPLICABLE;
  2856. litest_drain_events(li);
  2857. abs = libevdev_get_abs_info(dev->evdev, ABS_WHEEL);
  2858. litest_assert_notnull(abs);
  2859. litest_event(dev, EV_KEY, BTN_TOOL_AIRBRUSH, 1);
  2860. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2861. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2862. /* start with non-zero */
  2863. litest_event(dev, EV_ABS, ABS_WHEEL, 10);
  2864. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2865. litest_drain_events(li);
  2866. for (v = abs->minimum; v < abs->maximum; v += 8) {
  2867. double expected = absinfo_normalize_value(abs, v) * 2 - 1;
  2868. litest_event(dev, EV_ABS, ABS_WHEEL, v);
  2869. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2870. litest_dispatch(li);
  2871. event = libinput_get_event(li);
  2872. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2873. litest_assert(libinput_event_tablet_tool_slider_has_changed(tev));
  2874. val = libinput_event_tablet_tool_get_slider_position(tev);
  2875. litest_assert_double_eq(val, expected);
  2876. litest_assert_double_ge(val, -1.0);
  2877. litest_assert_double_le(val, 1.0);
  2878. libinput_event_destroy(event);
  2879. litest_assert_empty_queue(li);
  2880. }
  2881. }
  2882. END_TEST
  2883. START_TEST(artpen_tool)
  2884. {
  2885. struct litest_device *dev = litest_current_device();
  2886. struct libinput *li = dev->libinput;
  2887. struct libinput_event *event;
  2888. struct libinput_event_tablet_tool *tev;
  2889. struct libinput_tablet_tool *tool;
  2890. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_Z))
  2891. return LITEST_NOT_APPLICABLE;
  2892. litest_drain_events(li);
  2893. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  2894. litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
  2895. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2896. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2897. litest_dispatch(li);
  2898. event = libinput_get_event(li);
  2899. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2900. tool = libinput_event_tablet_tool_get_tool(tev);
  2901. litest_assert_notnull(tool);
  2902. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  2903. LIBINPUT_TABLET_TOOL_TYPE_PEN);
  2904. litest_assert(libinput_tablet_tool_has_rotation(tool));
  2905. libinput_event_destroy(event);
  2906. }
  2907. END_TEST
  2908. START_TEST(artpen_rotation)
  2909. {
  2910. struct litest_device *dev = litest_current_device();
  2911. struct libinput *li = dev->libinput;
  2912. struct libinput_event *event;
  2913. struct libinput_event_tablet_tool *tev;
  2914. const struct input_absinfo *abs;
  2915. double val;
  2916. double scale;
  2917. int angle;
  2918. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_Z))
  2919. return LITEST_NOT_APPLICABLE;
  2920. litest_drain_events(li);
  2921. abs = libevdev_get_abs_info(dev->evdev, ABS_Z);
  2922. litest_assert_notnull(abs);
  2923. scale = absinfo_range(abs) / 360.0;
  2924. litest_event(dev, EV_KEY, BTN_TOOL_BRUSH, 1);
  2925. litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
  2926. litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
  2927. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2928. litest_event(dev, EV_ABS, ABS_Z, abs->minimum);
  2929. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2930. litest_drain_events(li);
  2931. for (angle = 8; angle < 360; angle += 8) {
  2932. int a = angle * scale + abs->minimum;
  2933. litest_event(dev, EV_ABS, ABS_Z, a);
  2934. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  2935. litest_dispatch(li);
  2936. event = libinput_get_event(li);
  2937. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2938. litest_assert(libinput_event_tablet_tool_rotation_has_changed(tev));
  2939. val = libinput_event_tablet_tool_get_rotation(tev);
  2940. /* artpen has a 90 deg offset cw */
  2941. litest_assert_int_eq(round(val), (angle + 90) % 360);
  2942. libinput_event_destroy(event);
  2943. litest_assert_empty_queue(li);
  2944. }
  2945. }
  2946. END_TEST
  2947. START_TEST(tablet_time_usec)
  2948. {
  2949. struct litest_device *dev = litest_current_device();
  2950. struct libinput *li = dev->libinput;
  2951. struct libinput_event *event;
  2952. struct libinput_event_tablet_tool *tev;
  2953. struct axis_replacement axes[] = {
  2954. { ABS_DISTANCE, 10 },
  2955. { ABS_PRESSURE, 0 },
  2956. { -1, -1 },
  2957. };
  2958. uint64_t time_usec;
  2959. litest_drain_events(li);
  2960. litest_tablet_proximity_in(dev, 5, 100, axes);
  2961. litest_dispatch(li);
  2962. event = libinput_get_event(li);
  2963. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  2964. time_usec = libinput_event_tablet_tool_get_time_usec(tev);
  2965. litest_assert_int_eq(libinput_event_tablet_tool_get_time(tev),
  2966. (uint32_t)(time_usec / 1000));
  2967. libinput_event_destroy(event);
  2968. }
  2969. END_TEST
  2970. START_TEST(tablet_pressure_distance_exclusive)
  2971. {
  2972. struct litest_device *dev = litest_current_device();
  2973. struct libinput *li = dev->libinput;
  2974. struct libinput_event *event;
  2975. struct libinput_event_tablet_tool *tev;
  2976. struct axis_replacement axes[] = {
  2977. { ABS_DISTANCE, 10 },
  2978. { ABS_PRESSURE, 0 },
  2979. { -1, -1 },
  2980. };
  2981. double pressure, distance;
  2982. litest_tablet_proximity_in(dev, 5, 50, axes);
  2983. litest_drain_events(li);
  2984. /* We have 0.1% pressure above minimum threshold but we're still below
  2985. * the tip threshold */
  2986. litest_axis_set_value(axes, ABS_PRESSURE, 1.1);
  2987. litest_tablet_motion(dev, 70, 70, axes);
  2988. litest_dispatch(li);
  2989. event = libinput_get_event(li);
  2990. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  2991. pressure = libinput_event_tablet_tool_get_pressure(tev);
  2992. distance = libinput_event_tablet_tool_get_distance(tev);
  2993. litest_assert_double_eq(pressure, 0.001);
  2994. litest_assert_double_eq(distance, 0.0);
  2995. libinput_event_destroy(event);
  2996. /* We have pressure and we're above the tip threshold now */
  2997. litest_axis_set_value(axes, ABS_PRESSURE, 5.5);
  2998. litest_tablet_motion(dev, 70, 70, axes);
  2999. litest_dispatch(li);
  3000. event = libinput_get_event(li);
  3001. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  3002. pressure = libinput_event_tablet_tool_get_pressure(tev);
  3003. distance = libinput_event_tablet_tool_get_distance(tev);
  3004. litest_assert_double_gt(pressure, 0.0);
  3005. litest_assert_double_eq(distance, 0.0);
  3006. libinput_event_destroy(event);
  3007. }
  3008. END_TEST
  3009. static bool
  3010. device_has_calibration(struct litest_device *dev)
  3011. {
  3012. if (libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT))
  3013. return true;
  3014. bool has_calibration =
  3015. libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_PEN) ||
  3016. libevdev_has_event_code(dev->evdev, EV_KEY, BTN_STYLUS);
  3017. #ifdef HAVE_LIBWACOM
  3018. WacomDeviceDatabase *db = libwacom_database_new();
  3019. if (db) {
  3020. WacomDevice *d =
  3021. libwacom_new_from_path(db,
  3022. libevdev_uinput_get_devnode(dev->uinput),
  3023. WFALLBACK_NONE,
  3024. NULL);
  3025. if (d) {
  3026. has_calibration = !!(libwacom_get_integration_flags(d) &
  3027. (WACOM_DEVICE_INTEGRATED_SYSTEM |
  3028. WACOM_DEVICE_INTEGRATED_DISPLAY));
  3029. libwacom_destroy(d);
  3030. }
  3031. libwacom_database_destroy(db);
  3032. }
  3033. #endif
  3034. return has_calibration;
  3035. }
  3036. START_TEST(tablet_calibration_has_matrix)
  3037. {
  3038. struct litest_device *dev = litest_current_device();
  3039. struct libinput_device *d = dev->libinput_device;
  3040. enum libinput_config_status status;
  3041. int rc;
  3042. float calibration[6] = { 1, 0, 0, 0, 1, 0 };
  3043. int has_calibration;
  3044. has_calibration = device_has_calibration(dev);
  3045. rc = libinput_device_config_calibration_has_matrix(d);
  3046. litest_assert_int_eq(rc, has_calibration);
  3047. rc = libinput_device_config_calibration_get_matrix(d, calibration);
  3048. litest_assert_int_eq(rc, 0);
  3049. rc = libinput_device_config_calibration_get_default_matrix(d, calibration);
  3050. litest_assert_int_eq(rc, 0);
  3051. status = libinput_device_config_calibration_set_matrix(d, calibration);
  3052. if (has_calibration)
  3053. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3054. else
  3055. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
  3056. }
  3057. END_TEST
  3058. START_TEST(tablet_calibration_set_matrix_delta)
  3059. {
  3060. struct litest_device *dev = litest_current_device();
  3061. struct libinput *li = dev->libinput;
  3062. struct libinput_device *d = dev->libinput_device;
  3063. enum libinput_config_status status;
  3064. float calibration[6] = { 0.5, 0, 0, 0, 0.5, 0 };
  3065. struct libinput_event *event;
  3066. struct libinput_event_tablet_tool *tablet_event;
  3067. struct axis_replacement axes[] = {
  3068. { ABS_DISTANCE, 0 },
  3069. { ABS_PRESSURE, 10 },
  3070. { -1, -1 },
  3071. };
  3072. double x, y, dx, dy, mdx, mdy;
  3073. if (!device_has_calibration(dev))
  3074. return LITEST_NOT_APPLICABLE;
  3075. litest_drain_events(li);
  3076. litest_tablet_proximity_in(dev, 100, 100, axes);
  3077. litest_tablet_tip_down(dev, 100, 100, axes);
  3078. litest_dispatch(li);
  3079. event = libinput_get_event(li);
  3080. tablet_event =
  3081. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  3082. x = libinput_event_tablet_tool_get_x(tablet_event);
  3083. y = libinput_event_tablet_tool_get_y(tablet_event);
  3084. libinput_event_destroy(event);
  3085. event = libinput_get_event(li);
  3086. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  3087. libinput_event_destroy(event);
  3088. litest_tablet_motion(dev, 80, 80, axes);
  3089. litest_dispatch(li);
  3090. event = libinput_get_event(li);
  3091. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3092. dx = libinput_event_tablet_tool_get_x(tablet_event) - x;
  3093. dy = libinput_event_tablet_tool_get_y(tablet_event) - y;
  3094. libinput_event_destroy(event);
  3095. litest_tablet_tip_up(dev, 80, 80, axes);
  3096. litest_tablet_proximity_out(dev);
  3097. litest_timeout_tablet_proxout(li);
  3098. litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  3099. litest_drain_events(li);
  3100. status = libinput_device_config_calibration_set_matrix(d, calibration);
  3101. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3102. litest_tablet_proximity_in(dev, 100, 100, axes);
  3103. litest_tablet_tip_down(dev, 100, 100, axes);
  3104. litest_dispatch(li);
  3105. event = libinput_get_event(li);
  3106. tablet_event =
  3107. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  3108. x = libinput_event_tablet_tool_get_x(tablet_event);
  3109. y = libinput_event_tablet_tool_get_y(tablet_event);
  3110. libinput_event_destroy(event);
  3111. event = libinput_get_event(li);
  3112. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  3113. libinput_event_destroy(event);
  3114. litest_tablet_motion(dev, 80, 80, axes);
  3115. litest_dispatch(li);
  3116. event = libinput_get_event(li);
  3117. tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3118. mdx = libinput_event_tablet_tool_get_x(tablet_event) - x;
  3119. mdy = libinput_event_tablet_tool_get_y(tablet_event) - y;
  3120. libinput_event_destroy(event);
  3121. litest_drain_events(li);
  3122. litest_assert_double_gt(dx, mdx * 2 - 1);
  3123. litest_assert_double_lt(dx, mdx * 2 + 1);
  3124. litest_assert_double_gt(dy, mdy * 2 - 1);
  3125. litest_assert_double_lt(dy, mdy * 2 + 1);
  3126. }
  3127. END_TEST
  3128. START_TEST(tablet_calibration_set_matrix)
  3129. {
  3130. struct litest_device *dev = litest_current_device();
  3131. struct libinput *li = dev->libinput;
  3132. struct libinput_device *d = dev->libinput_device;
  3133. enum libinput_config_status status;
  3134. float calibration[6] = { 0.5, 0, 0, 0, 1, 0 };
  3135. struct libinput_event *event;
  3136. struct libinput_event_tablet_tool *tablet_event;
  3137. struct axis_replacement axes[] = {
  3138. { ABS_DISTANCE, 10 },
  3139. { ABS_PRESSURE, 0 },
  3140. { -1, -1 },
  3141. };
  3142. double x, y;
  3143. if (!device_has_calibration(dev))
  3144. return LITEST_NOT_APPLICABLE;
  3145. litest_drain_events(li);
  3146. status = libinput_device_config_calibration_set_matrix(d, calibration);
  3147. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3148. litest_tablet_proximity_in(dev, 100, 100, axes);
  3149. litest_dispatch(li);
  3150. event = libinput_get_event(li);
  3151. tablet_event =
  3152. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  3153. x = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100);
  3154. y = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100);
  3155. libinput_event_destroy(event);
  3156. litest_assert_double_gt(x, 49.0);
  3157. litest_assert_double_lt(x, 51.0);
  3158. litest_assert_double_gt(y, 99.0);
  3159. litest_assert_double_lt(y, 100.0);
  3160. litest_tablet_proximity_out(dev);
  3161. litest_timeout_tablet_proxout(li);
  3162. litest_tablet_proximity_in(dev, 50, 50, axes);
  3163. litest_tablet_proximity_out(dev);
  3164. litest_timeout_tablet_proxout(li);
  3165. litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  3166. litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  3167. litest_drain_events(li);
  3168. calibration[0] = 1;
  3169. calibration[4] = 0.5;
  3170. status = libinput_device_config_calibration_set_matrix(d, calibration);
  3171. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3172. litest_tablet_proximity_in(dev, 100, 100, axes);
  3173. litest_dispatch(li);
  3174. event = libinput_get_event(li);
  3175. tablet_event =
  3176. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  3177. x = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100);
  3178. y = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100);
  3179. libinput_event_destroy(event);
  3180. litest_assert(x > 99.0);
  3181. litest_assert(x < 100.0);
  3182. litest_assert(y > 49.0);
  3183. litest_assert(y < 51.0);
  3184. litest_tablet_proximity_out(dev);
  3185. litest_timeout_tablet_proxout(li);
  3186. }
  3187. END_TEST
  3188. START_TEST(tablet_area_has_rectangle)
  3189. {
  3190. struct litest_device *dev = litest_current_device();
  3191. struct libinput_device *d = dev->libinput_device;
  3192. enum libinput_config_status status;
  3193. int rc;
  3194. struct libinput_config_area_rectangle rect;
  3195. int has_area = !libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
  3196. rc = libinput_device_config_area_has_rectangle(d);
  3197. litest_assert_int_eq(rc, has_area);
  3198. rect = libinput_device_config_area_get_rectangle(d);
  3199. litest_assert_double_eq(rect.x1, 0.0);
  3200. litest_assert_double_eq(rect.y1, 0.0);
  3201. litest_assert_double_eq(rect.x2, 1.0);
  3202. litest_assert_double_eq(rect.y2, 1.0);
  3203. rect = libinput_device_config_area_get_default_rectangle(d);
  3204. litest_assert_double_eq(rect.x1, 0.0);
  3205. litest_assert_double_eq(rect.y1, 0.0);
  3206. litest_assert_double_eq(rect.x2, 1.0);
  3207. litest_assert_double_eq(rect.y2, 1.0);
  3208. status = libinput_device_config_area_set_rectangle(d, &rect);
  3209. if (has_area)
  3210. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3211. else
  3212. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
  3213. }
  3214. END_TEST
  3215. START_TEST(tablet_area_set_rectangle_invalid)
  3216. {
  3217. struct litest_device *dev = litest_current_device();
  3218. struct libinput_device *d = dev->libinput_device;
  3219. int rc;
  3220. struct libinput_config_area_rectangle rect;
  3221. int has_area = !libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
  3222. if (!has_area)
  3223. return LITEST_NOT_APPLICABLE;
  3224. rect.x1 = 1.0;
  3225. rect.x2 = 0.9;
  3226. rect.y1 = 0.0;
  3227. rect.y2 = 1.0;
  3228. rc = libinput_device_config_area_set_rectangle(d, &rect);
  3229. litest_assert_enum_eq(rc, LIBINPUT_CONFIG_STATUS_INVALID);
  3230. rect.x1 = 0.9;
  3231. rect.x2 = 1.0;
  3232. rect.y1 = 1.0;
  3233. rect.y2 = 0.9;
  3234. rc = libinput_device_config_area_set_rectangle(d, &rect);
  3235. litest_assert_enum_eq(rc, LIBINPUT_CONFIG_STATUS_INVALID);
  3236. rect.x1 = 0.9;
  3237. rect.x2 = 0.9;
  3238. rect.y1 = 0.9;
  3239. rect.y2 = 1.0;
  3240. rc = libinput_device_config_area_set_rectangle(d, &rect);
  3241. litest_assert_enum_eq(rc, LIBINPUT_CONFIG_STATUS_INVALID);
  3242. rect.x1 = 0.9;
  3243. rect.x2 = 1.0;
  3244. rect.y1 = 0.9;
  3245. rect.y2 = 0.9;
  3246. rc = libinput_device_config_area_set_rectangle(d, &rect);
  3247. litest_assert_enum_eq(rc, LIBINPUT_CONFIG_STATUS_INVALID);
  3248. rect.x1 = 0.9;
  3249. rect.x2 = 1.5;
  3250. rect.y1 = 0.0;
  3251. rect.y2 = 1.0;
  3252. rc = libinput_device_config_area_set_rectangle(d, &rect);
  3253. litest_assert_enum_eq(rc, LIBINPUT_CONFIG_STATUS_INVALID);
  3254. rect.x1 = 0.0;
  3255. rect.x2 = 1.0;
  3256. rect.y1 = 0.9;
  3257. rect.y2 = 1.4;
  3258. rc = libinput_device_config_area_set_rectangle(d, &rect);
  3259. litest_assert_enum_eq(rc, LIBINPUT_CONFIG_STATUS_INVALID);
  3260. }
  3261. END_TEST
  3262. static void
  3263. get_tool_xy(struct libinput *li, double *x, double *y)
  3264. {
  3265. struct libinput_event *event = libinput_get_event(li);
  3266. struct libinput_event_tablet_tool *tev;
  3267. litest_assert_ptr_notnull(event);
  3268. switch (libinput_event_get_type(event)) {
  3269. case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
  3270. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3271. break;
  3272. case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
  3273. tev = litest_is_tablet_event(event,
  3274. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  3275. break;
  3276. default:
  3277. litest_assert_not_reached();
  3278. }
  3279. *x = libinput_event_tablet_tool_get_x_transformed(tev, 100);
  3280. *y = libinput_event_tablet_tool_get_y_transformed(tev, 100);
  3281. libinput_event_destroy(event);
  3282. }
  3283. START_TEST(tablet_area_set_rectangle)
  3284. {
  3285. struct litest_device *dev = litest_current_device();
  3286. struct libinput *li = dev->libinput;
  3287. struct libinput_device *d = dev->libinput_device;
  3288. struct axis_replacement axes[] = {
  3289. { ABS_DISTANCE, 10 },
  3290. { ABS_PRESSURE, 0 },
  3291. { -1, -1 },
  3292. };
  3293. double x, y;
  3294. double *scaled, *unscaled;
  3295. const char *param_axis = litest_test_param_get_string(test_env->params, "axis");
  3296. const char *param_direction =
  3297. litest_test_param_get_string(test_env->params, "direction");
  3298. bool use_vertical = streq(param_axis, "vertical");
  3299. int direction = streq(param_direction, "down") ? 1 : -1;
  3300. if (libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT))
  3301. return LITEST_NOT_APPLICABLE;
  3302. struct libinput_config_area_rectangle rect;
  3303. if (use_vertical) {
  3304. rect = (struct libinput_config_area_rectangle){
  3305. 0.25,
  3306. 0.0,
  3307. 0.75,
  3308. 1.0,
  3309. };
  3310. scaled = &x;
  3311. unscaled = &y;
  3312. } else {
  3313. rect = (struct libinput_config_area_rectangle){
  3314. 0.0,
  3315. 0.25,
  3316. 1.0,
  3317. 0.75,
  3318. };
  3319. scaled = &y;
  3320. unscaled = &x;
  3321. }
  3322. enum libinput_config_status status =
  3323. libinput_device_config_area_set_rectangle(d, &rect);
  3324. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3325. litest_drain_events(li);
  3326. /* move from the center out */
  3327. litest_tablet_proximity_in(dev, 50, 50, axes);
  3328. litest_dispatch(li);
  3329. get_tool_xy(li, &x, &y);
  3330. litest_assert_double_eq_epsilon(*scaled, 50.0, 2);
  3331. litest_assert_double_eq_epsilon(*unscaled, 50.0, 2);
  3332. int i;
  3333. for (i = 50; i > 0 && i <= 100; i += 5 * direction) {
  3334. /* Negate any smoothing */
  3335. litest_tablet_motion(dev, i, i, axes);
  3336. litest_tablet_motion(dev, i - 1, i, axes);
  3337. litest_tablet_motion(dev, i, i - 1, axes);
  3338. litest_drain_events(li);
  3339. litest_tablet_motion(dev, i, i, axes);
  3340. litest_dispatch(li);
  3341. get_tool_xy(li, &x, &y);
  3342. if (i <= 25)
  3343. litest_assert_double_eq(*scaled, 0.0);
  3344. else if (i > 75)
  3345. litest_assert_double_eq_epsilon(*scaled, 100.0, 1);
  3346. else
  3347. litest_assert_double_eq_epsilon(*scaled, (i - 25) * 2, 1);
  3348. litest_assert_double_eq_epsilon(*unscaled, i, 2);
  3349. }
  3350. double final_stop = max(0.0, min(100.0, i));
  3351. /* Push through any smoothing */
  3352. litest_tablet_motion(dev, final_stop, final_stop, axes);
  3353. litest_tablet_motion(dev, final_stop, final_stop, axes);
  3354. litest_dispatch(li);
  3355. litest_drain_events(li);
  3356. litest_tablet_proximity_out(dev);
  3357. litest_timeout_tablet_proxout(li);
  3358. get_tool_xy(li, &x, &y);
  3359. litest_assert_double_eq_epsilon(x, final_stop, 1);
  3360. litest_assert_double_eq_epsilon(y, final_stop, 1);
  3361. }
  3362. END_TEST
  3363. START_TEST(tablet_area_set_rectangle_move_outside)
  3364. {
  3365. struct litest_device *dev = litest_current_device();
  3366. struct libinput *li = dev->libinput;
  3367. struct libinput_device *d = dev->libinput_device;
  3368. struct axis_replacement axes[] = {
  3369. { ABS_DISTANCE, 10 },
  3370. { ABS_PRESSURE, 0 },
  3371. { -1, -1 },
  3372. };
  3373. double x, y;
  3374. if (libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT))
  3375. return LITEST_NOT_APPLICABLE;
  3376. struct libinput_config_area_rectangle rect = {
  3377. 0.25,
  3378. 0.25,
  3379. 0.75,
  3380. 0.75,
  3381. };
  3382. enum libinput_config_status status =
  3383. libinput_device_config_area_set_rectangle(d, &rect);
  3384. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3385. litest_drain_events(li);
  3386. /* move in/out of prox outside the area */
  3387. litest_tablet_proximity_in(dev, 5, 5, axes);
  3388. litest_tablet_proximity_out(dev);
  3389. litest_timeout_tablet_proxout(li);
  3390. litest_assert_empty_queue(li);
  3391. x = 5;
  3392. y = 5;
  3393. /* Move around the area - since we stay outside the area expect no events */
  3394. litest_tablet_proximity_in(dev, x, y, axes);
  3395. litest_dispatch(li);
  3396. for (; x < 90; x += 5) {
  3397. litest_tablet_motion(dev, x, y, axes);
  3398. litest_dispatch(li);
  3399. litest_assert_empty_queue(li);
  3400. }
  3401. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  3402. litest_tablet_tip_down(dev, x, y, axes);
  3403. for (; y < 90; y += 5) {
  3404. litest_tablet_motion(dev, x, y, axes);
  3405. litest_dispatch(li);
  3406. litest_assert_empty_queue(li);
  3407. }
  3408. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  3409. litest_tablet_tip_up(dev, x, y, axes);
  3410. for (; x > 5; x -= 5) {
  3411. litest_tablet_motion(dev, x, y, axes);
  3412. litest_dispatch(li);
  3413. litest_assert_empty_queue(li);
  3414. }
  3415. litest_button_click(dev, BTN_STYLUS, LIBINPUT_BUTTON_STATE_PRESSED);
  3416. litest_button_click(dev, BTN_STYLUS, LIBINPUT_BUTTON_STATE_RELEASED);
  3417. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  3418. litest_tablet_tip_down(dev, x, y, axes);
  3419. for (; y > 5; y -= 5) {
  3420. litest_tablet_motion(dev, x, y, axes);
  3421. litest_dispatch(li);
  3422. litest_assert_empty_queue(li);
  3423. }
  3424. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  3425. litest_tablet_tip_up(dev, x, y, axes);
  3426. litest_tablet_proximity_out(dev);
  3427. litest_timeout_tablet_proxout(li);
  3428. litest_assert_empty_queue(li);
  3429. }
  3430. END_TEST
  3431. START_TEST(tablet_area_set_rectangle_move_outside_to_inside)
  3432. {
  3433. struct litest_device *dev = litest_current_device();
  3434. struct libinput *li = dev->libinput;
  3435. struct libinput_device *d = dev->libinput_device;
  3436. struct axis_replacement axes[] = {
  3437. { ABS_DISTANCE, 10 },
  3438. { ABS_PRESSURE, 0 },
  3439. { -1, -1 },
  3440. };
  3441. double x, y;
  3442. if (libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT))
  3443. return LITEST_NOT_APPLICABLE;
  3444. struct libinput_config_area_rectangle rect = {
  3445. 0.25,
  3446. 0.25,
  3447. 0.75,
  3448. 0.75,
  3449. };
  3450. enum libinput_config_status status =
  3451. libinput_device_config_area_set_rectangle(d, &rect);
  3452. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3453. litest_drain_events(li);
  3454. x = 5;
  3455. y = 50;
  3456. /* Move into the center of the area - since we started outside the area
  3457. * expect no events */
  3458. litest_tablet_proximity_in(dev, x, y, axes);
  3459. litest_dispatch(li);
  3460. for (; x < 50; x += 5) {
  3461. litest_tablet_motion(dev, x, y, axes);
  3462. litest_dispatch(li);
  3463. litest_assert_empty_queue(li);
  3464. }
  3465. litest_button_click(dev, BTN_STYLUS, LIBINPUT_BUTTON_STATE_PRESSED);
  3466. litest_button_click(dev, BTN_STYLUS, LIBINPUT_BUTTON_STATE_RELEASED);
  3467. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  3468. litest_tablet_tip_down(dev, x, y, axes);
  3469. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  3470. litest_tablet_tip_up(dev, x, y, axes);
  3471. litest_tablet_proximity_out(dev);
  3472. litest_timeout_tablet_proxout(li);
  3473. litest_assert_empty_queue(li);
  3474. y = 5;
  3475. x = 50;
  3476. litest_tablet_proximity_in(dev, x, y, axes);
  3477. for (; y < 50; y += 5) {
  3478. litest_tablet_motion(dev, x, y, axes);
  3479. litest_dispatch(li);
  3480. litest_assert_empty_queue(li);
  3481. }
  3482. litest_button_click(dev, BTN_STYLUS, LIBINPUT_BUTTON_STATE_PRESSED);
  3483. litest_button_click(dev, BTN_STYLUS, LIBINPUT_BUTTON_STATE_RELEASED);
  3484. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  3485. litest_tablet_tip_down(dev, x, y, axes);
  3486. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  3487. litest_tablet_tip_up(dev, x, y, axes);
  3488. litest_tablet_proximity_out(dev);
  3489. litest_timeout_tablet_proxout(li);
  3490. litest_assert_empty_queue(li);
  3491. }
  3492. END_TEST
  3493. START_TEST(tablet_area_set_rectangle_move_in_margin)
  3494. {
  3495. struct litest_device *dev = litest_current_device();
  3496. struct libinput *li = dev->libinput;
  3497. struct libinput_device *d = dev->libinput_device;
  3498. struct libinput_event *ev;
  3499. struct libinput_event_tablet_tool *tev;
  3500. struct axis_replacement axes[] = {
  3501. { ABS_DISTANCE, 10 },
  3502. { ABS_PRESSURE, 0 },
  3503. { -1, -1 },
  3504. };
  3505. double x, y;
  3506. if (libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT))
  3507. return LITEST_NOT_APPLICABLE;
  3508. struct libinput_config_area_rectangle rect = {
  3509. 0.25,
  3510. 0.25,
  3511. 0.75,
  3512. 0.75,
  3513. };
  3514. enum libinput_config_status status =
  3515. libinput_device_config_area_set_rectangle(d, &rect);
  3516. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3517. litest_drain_events(li);
  3518. /* move in/out of prox outside the area but within the margin */
  3519. litest_tablet_proximity_in(dev, 24, 24, axes);
  3520. litest_tablet_proximity_out(dev);
  3521. litest_timeout_tablet_proxout(li);
  3522. ev = libinput_get_event(li);
  3523. tev = litest_is_proximity_event(ev, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  3524. x = libinput_event_tablet_tool_get_x(tev);
  3525. y = libinput_event_tablet_tool_get_y(tev);
  3526. litest_assert_double_eq(x, 0.0);
  3527. litest_assert_double_eq(y, 0.0);
  3528. libinput_event_destroy(ev);
  3529. ev = libinput_get_event(li);
  3530. tev = litest_is_proximity_event(ev, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  3531. x = libinput_event_tablet_tool_get_x(tev);
  3532. y = libinput_event_tablet_tool_get_y(tev);
  3533. litest_assert_double_eq(x, 0.0);
  3534. litest_assert_double_eq(y, 0.0);
  3535. libinput_event_destroy(ev);
  3536. }
  3537. END_TEST
  3538. START_TEST(tablet_area_set_rectangle_while_outside)
  3539. {
  3540. struct litest_device *dev = litest_current_device();
  3541. struct libinput *li = dev->libinput;
  3542. struct libinput_device *d = dev->libinput_device;
  3543. struct libinput_event *ev;
  3544. struct libinput_event_tablet_tool *tev;
  3545. struct axis_replacement axes[] = {
  3546. { ABS_DISTANCE, 10 },
  3547. { ABS_PRESSURE, 0 },
  3548. { -1, -1 },
  3549. };
  3550. double x, y;
  3551. if (libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT))
  3552. return LITEST_NOT_APPLICABLE;
  3553. litest_checkpoint("Set tablet area");
  3554. struct libinput_config_area_rectangle rect = {
  3555. 0.25,
  3556. 0.25,
  3557. 0.75,
  3558. 0.75,
  3559. };
  3560. enum libinput_config_status status =
  3561. libinput_device_config_area_set_rectangle(d, &rect);
  3562. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3563. litest_drain_events(li);
  3564. litest_checkpoint("Proximity in + out outside tablet area");
  3565. litest_tablet_proximity_in(dev, 10, 10, axes);
  3566. litest_tablet_proximity_out(dev);
  3567. litest_timeout_tablet_proxout(li);
  3568. litest_assert_empty_queue(li);
  3569. litest_dispatch(li);
  3570. litest_checkpoint("Update tablet area");
  3571. rect = (struct libinput_config_area_rectangle){
  3572. 0.05,
  3573. 0.05,
  3574. 0.95,
  3575. 0.95,
  3576. };
  3577. status = libinput_device_config_area_set_rectangle(d, &rect);
  3578. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  3579. litest_checkpoint("Proximity in + out inside tablet area");
  3580. litest_tablet_proximity_in(dev, 11, 11, axes);
  3581. litest_tablet_motion(dev, 12, 12, axes);
  3582. litest_tablet_proximity_out(dev);
  3583. litest_timeout_tablet_proxout(li);
  3584. ev = libinput_get_event(li);
  3585. tev = litest_is_proximity_event(ev, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  3586. x = libinput_event_tablet_tool_get_x_transformed(tev, 100.0);
  3587. y = libinput_event_tablet_tool_get_y_transformed(tev, 100.0);
  3588. litest_assert_double_gt(
  3589. x,
  3590. 6); /* somewhere around 6%, precise number doesn't matter */
  3591. litest_assert_double_gt(y, 6);
  3592. libinput_event_destroy(ev);
  3593. ev = libinput_get_event(li);
  3594. tev = litest_is_tablet_event(ev, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3595. x = libinput_event_tablet_tool_get_x_transformed(tev, 100.0);
  3596. y = libinput_event_tablet_tool_get_y_transformed(tev, 100.0);
  3597. litest_assert_double_gt(x, 6);
  3598. litest_assert_double_gt(y, 6);
  3599. libinput_event_destroy(ev);
  3600. ev = libinput_get_event(li);
  3601. tev = litest_is_proximity_event(ev, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  3602. x = libinput_event_tablet_tool_get_x_transformed(tev, 100.0);
  3603. y = libinput_event_tablet_tool_get_y_transformed(tev, 100.0);
  3604. litest_assert_double_gt(x, 6);
  3605. litest_assert_double_gt(y, 6);
  3606. libinput_event_destroy(ev);
  3607. }
  3608. END_TEST
  3609. static void
  3610. assert_pressure(struct libinput *li,
  3611. enum libinput_event_type type,
  3612. double expected_pressure)
  3613. {
  3614. struct libinput_event *event = libinput_get_event(li);
  3615. struct libinput_event_tablet_tool *tev = litest_is_tablet_event(event, type);
  3616. double pressure = libinput_event_tablet_tool_get_pressure(tev);
  3617. litest_assert_double_eq_epsilon(pressure, expected_pressure, 0.01);
  3618. libinput_event_destroy(event);
  3619. }
  3620. START_TEST(tablet_pressure_offset_set)
  3621. {
  3622. struct litest_device *dev = litest_current_device();
  3623. struct libinput *li = dev->libinput;
  3624. struct libinput_event *event;
  3625. struct axis_replacement axes[] = {
  3626. { ABS_DISTANCE, 70 },
  3627. { ABS_PRESSURE, 20 },
  3628. { -1, -1 },
  3629. };
  3630. litest_drain_events(li);
  3631. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_DISTANCE)) {
  3632. /* First two prox ins won't do anything, coming with 10% should give
  3633. * us ~10% pressure */
  3634. for (int i = 0; i < 2; i++) {
  3635. litest_tablet_proximity_in(dev, 5, 100, axes);
  3636. litest_dispatch(li);
  3637. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, 0.20);
  3638. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.20);
  3639. litest_tablet_proximity_out(dev);
  3640. litest_timeout_tablet_proxout(li);
  3641. litest_drain_events(li);
  3642. }
  3643. }
  3644. /* This activates the pressure offset */
  3645. litest_tablet_proximity_in(dev, 5, 100, axes);
  3646. litest_drain_events(li);
  3647. /* Put the pen down, with a pressure high enough to meet the
  3648. * new offset */
  3649. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  3650. litest_axis_set_value(axes, ABS_PRESSURE, 26);
  3651. /* Tablet motion above threshold should trigger axis + tip down. Use
  3652. * the litest motion helper here to avoid false positives caused by
  3653. * BTN_TOUCH */
  3654. litest_tablet_motion(dev, 70, 70, axes);
  3655. litest_dispatch(li);
  3656. event = libinput_get_event(li);
  3657. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  3658. libinput_event_destroy(event);
  3659. /* Reduce pressure to just a tick over the offset, otherwise we get
  3660. * the tip up event again */
  3661. litest_axis_set_value(axes, ABS_PRESSURE, 20.1);
  3662. litest_tablet_motion(dev, 70, 70, axes);
  3663. litest_dispatch(li);
  3664. /* we can't actually get a real 0.0 because that would trigger a tip
  3665. up. but it's close enough to zero. */
  3666. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.01);
  3667. litest_drain_events(li);
  3668. litest_axis_set_value(axes, ABS_PRESSURE, 21);
  3669. litest_tablet_motion(dev, 70, 70, axes);
  3670. litest_dispatch(li);
  3671. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.015);
  3672. /* Make sure we can reach the upper range too */
  3673. litest_axis_set_value(axes, ABS_PRESSURE, 100);
  3674. litest_tablet_motion(dev, 70, 70, axes);
  3675. litest_dispatch(li);
  3676. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 1.0);
  3677. /* Tablet motion at offset should trigger tip up. Use
  3678. * the litest motion helper here to avoid false positives caused by
  3679. * BTN_TOUCH */
  3680. litest_axis_set_value(axes, ABS_PRESSURE, 20);
  3681. litest_tablet_motion(dev, 71, 71, axes);
  3682. litest_dispatch(li);
  3683. event = libinput_get_event(li);
  3684. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  3685. libinput_event_destroy(event);
  3686. }
  3687. END_TEST
  3688. START_TEST(tablet_pressure_offset_decrease)
  3689. {
  3690. struct litest_device *dev = litest_current_device();
  3691. struct libinput *li = dev->libinput;
  3692. struct axis_replacement axes[] = {
  3693. { ABS_DISTANCE, 70 },
  3694. { ABS_PRESSURE, 20 },
  3695. { -1, -1 },
  3696. };
  3697. /* offset 20 on prox in */
  3698. litest_tablet_proximity_in(dev, 5, 100, axes);
  3699. litest_tablet_proximity_out(dev);
  3700. litest_timeout_tablet_proxout(li);
  3701. litest_drain_events(li);
  3702. /* offset 15 on prox in - this one is so we trigger on the next prox
  3703. * in for the no-distance tablets */
  3704. litest_axis_set_value(axes, ABS_PRESSURE, 15);
  3705. litest_tablet_proximity_in(dev, 5, 100, axes);
  3706. litest_tablet_proximity_out(dev);
  3707. litest_timeout_tablet_proxout(li);
  3708. litest_drain_events(li);
  3709. /* a reduced pressure value must reduce the offset */
  3710. litest_axis_set_value(axes, ABS_PRESSURE, 10);
  3711. litest_tablet_proximity_in(dev, 5, 100, axes);
  3712. litest_tablet_proximity_out(dev);
  3713. litest_timeout_tablet_proxout(li);
  3714. litest_drain_events(li);
  3715. litest_tablet_proximity_in(dev, 5, 100, axes);
  3716. litest_dispatch(li);
  3717. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, 0.0);
  3718. litest_drain_events(li);
  3719. /* trigger the pressure threshold */
  3720. litest_axis_set_value(axes, ABS_PRESSURE, 15);
  3721. litest_tablet_tip_down(dev, 70, 70, axes);
  3722. litest_dispatch(li);
  3723. /* offset 10 + lower threshold of ~1% of original range,
  3724. * value 15 is 5% over original range but with the above taken into
  3725. * account it's closer to 5% into the remaining effective 89% range
  3726. */
  3727. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.05);
  3728. /* a reduced pressure value during motion events must reduce the offset
  3729. * - here back down to 5%.
  3730. * FIXME: this causes a tip up event which is a bug but working around
  3731. * this is more effort than it's worth for what should be quite a niche
  3732. * case.
  3733. */
  3734. litest_axis_set_value(axes, ABS_PRESSURE, 5);
  3735. litest_tablet_motion(dev, 75, 75, axes);
  3736. litest_dispatch(li);
  3737. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.0);
  3738. litest_drain_events(li);
  3739. /* back to 10% should now give us 5% pressure because we reduced the
  3740. * offset */
  3741. litest_axis_set_value(axes, ABS_PRESSURE, 10);
  3742. litest_tablet_motion(dev, 75, 75, axes);
  3743. litest_dispatch(li);
  3744. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.05);
  3745. litest_drain_events(li);
  3746. }
  3747. END_TEST
  3748. START_TEST(tablet_pressure_offset_increase)
  3749. {
  3750. struct litest_device *dev = litest_current_device();
  3751. struct libinput *li = dev->libinput;
  3752. struct axis_replacement axes[] = {
  3753. { ABS_DISTANCE, 70 },
  3754. { ABS_PRESSURE, 20 },
  3755. { -1, -1 },
  3756. };
  3757. /* offset 20 on first prox in */
  3758. litest_tablet_proximity_in(dev, 5, 100, axes);
  3759. litest_tablet_proximity_out(dev);
  3760. litest_dispatch(li);
  3761. litest_timeout_tablet_proxout(li);
  3762. litest_drain_events(li);
  3763. /* offset 25 on second prox in - must not change the offset */
  3764. litest_axis_set_value(axes, ABS_PRESSURE, 25);
  3765. litest_tablet_proximity_in(dev, 5, 100, axes);
  3766. litest_tablet_proximity_out(dev);
  3767. litest_timeout_tablet_proxout(li);
  3768. litest_drain_events(li);
  3769. /* offset 30 on third prox in - must not change the offset */
  3770. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  3771. litest_tablet_proximity_in(dev, 5, 100, axes);
  3772. litest_drain_events(li);
  3773. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  3774. litest_axis_set_value(axes, ABS_PRESSURE, 31);
  3775. litest_tablet_tip_down(dev, 70, 70, axes);
  3776. litest_dispatch(li);
  3777. litest_drain_events(li);
  3778. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  3779. litest_tablet_motion(dev, 70, 70, axes);
  3780. litest_dispatch(li);
  3781. /* offset 20 + lower threshold of 1% of original range,
  3782. * value 30 is 5% over original range but with the above taken into
  3783. * account it's closer to 12% into the remaining effective 79% range
  3784. */
  3785. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.12);
  3786. litest_drain_events(li);
  3787. litest_axis_set_value(axes, ABS_PRESSURE, 20);
  3788. litest_tablet_motion(dev, 70, 70, axes);
  3789. litest_dispatch(li);
  3790. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.0);
  3791. }
  3792. END_TEST
  3793. START_TEST(tablet_pressure_min_max)
  3794. {
  3795. struct litest_device *dev = litest_current_device();
  3796. struct libinput *li = dev->libinput;
  3797. struct axis_replacement axes[] = {
  3798. { ABS_DISTANCE, 10 },
  3799. { ABS_PRESSURE, 0 },
  3800. { -1, -1 },
  3801. };
  3802. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE))
  3803. return LITEST_NOT_APPLICABLE;
  3804. litest_tablet_proximity_in(dev, 5, 50, axes);
  3805. litest_drain_events(li);
  3806. litest_dispatch(li);
  3807. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  3808. /* Default pressure threshold is 1% of range */
  3809. litest_axis_set_value(axes, ABS_PRESSURE, 1.1);
  3810. litest_tablet_motion(dev, 5, 50, axes);
  3811. litest_dispatch(li);
  3812. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.0);
  3813. /* skip over pressure-based tip down */
  3814. litest_axis_set_value(axes, ABS_PRESSURE, 90);
  3815. litest_tablet_motion(dev, 5, 50, axes);
  3816. litest_drain_events(li);
  3817. /* need to fill the motion history */
  3818. litest_axis_set_value(axes, ABS_PRESSURE, 100);
  3819. litest_tablet_motion(dev, 5, 50, axes);
  3820. litest_tablet_motion(dev, 6, 50, axes);
  3821. litest_tablet_motion(dev, 7, 50, axes);
  3822. litest_tablet_motion(dev, 8, 50, axes);
  3823. litest_drain_events(li);
  3824. litest_tablet_motion(dev, 5, 50, axes);
  3825. litest_dispatch(li);
  3826. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 1.0);
  3827. }
  3828. END_TEST
  3829. START_TEST(tablet_pressure_range)
  3830. {
  3831. struct litest_device *dev = litest_current_device();
  3832. struct libinput *li = dev->libinput;
  3833. struct libinput_event *event;
  3834. struct libinput_event_tablet_tool *tev;
  3835. struct axis_replacement axes[] = {
  3836. { ABS_DISTANCE, 0 },
  3837. { ABS_PRESSURE, 10 },
  3838. { -1, -1 },
  3839. };
  3840. int pressure;
  3841. double p;
  3842. litest_tablet_proximity_in(dev, 5, 100, axes);
  3843. litest_drain_events(li);
  3844. litest_dispatch(li);
  3845. for (pressure = 10; pressure <= 100; pressure += 10) {
  3846. litest_axis_set_value(axes, ABS_PRESSURE, pressure);
  3847. litest_tablet_motion(dev, 70, 70, axes);
  3848. litest_dispatch(li);
  3849. event = libinput_get_event(li);
  3850. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3851. p = libinput_event_tablet_tool_get_pressure(tev);
  3852. litest_assert_double_ge(p, 0.0);
  3853. litest_assert_double_le(p, 1.0);
  3854. libinput_event_destroy(event);
  3855. }
  3856. }
  3857. END_TEST
  3858. START_TEST(tablet_pressure_config)
  3859. {
  3860. struct litest_device *dev = litest_current_device();
  3861. struct libinput *li = dev->libinput;
  3862. struct libinput_event_tablet_tool *tev;
  3863. struct axis_replacement axes[] = {
  3864. { ABS_DISTANCE, 0 },
  3865. { ABS_PRESSURE, 10 },
  3866. { -1, -1 },
  3867. };
  3868. bool has_pressure = libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE);
  3869. litest_tablet_proximity_in(dev, 5, 100, axes);
  3870. litest_drain_events(li);
  3871. litest_dispatch(li);
  3872. litest_tablet_motion(dev, 70, 70, axes);
  3873. litest_dispatch(li);
  3874. _destroy_(libinput_event) *event = libinput_get_event(li);
  3875. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3876. struct libinput_tablet_tool *tool = libinput_event_tablet_tool_get_tool(tev);
  3877. litest_assert_int_eq(
  3878. has_pressure,
  3879. libinput_tablet_tool_config_pressure_range_is_available(tool));
  3880. litest_assert_double_eq(
  3881. libinput_tablet_tool_config_pressure_range_get_minimum(tool),
  3882. 0.0);
  3883. litest_assert_double_eq(
  3884. libinput_tablet_tool_config_pressure_range_get_maximum(tool),
  3885. 1.0);
  3886. litest_assert_double_eq(
  3887. libinput_tablet_tool_config_pressure_range_get_default_minimum(tool),
  3888. 0.0);
  3889. litest_assert_double_eq(
  3890. libinput_tablet_tool_config_pressure_range_get_default_maximum(tool),
  3891. 1.0);
  3892. if (!has_pressure) {
  3893. litest_assert_enum_eq(
  3894. libinput_tablet_tool_config_pressure_range_set(tool, 0.0, 1.0),
  3895. LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
  3896. return LITEST_PASS;
  3897. }
  3898. litest_assert_enum_eq(
  3899. libinput_tablet_tool_config_pressure_range_set(tool, 0.0, 1.0),
  3900. LIBINPUT_CONFIG_STATUS_SUCCESS);
  3901. litest_assert_enum_eq(
  3902. libinput_tablet_tool_config_pressure_range_set(tool, 0.2, 0.5),
  3903. LIBINPUT_CONFIG_STATUS_SUCCESS);
  3904. litest_assert_enum_eq(
  3905. libinput_tablet_tool_config_pressure_range_set(tool, -0.1, 1.0),
  3906. LIBINPUT_CONFIG_STATUS_INVALID);
  3907. litest_assert_enum_eq(
  3908. libinput_tablet_tool_config_pressure_range_set(tool, 0.0, 0.0),
  3909. LIBINPUT_CONFIG_STATUS_INVALID);
  3910. litest_assert_enum_eq(
  3911. libinput_tablet_tool_config_pressure_range_set(tool, 1.0, 1.0),
  3912. LIBINPUT_CONFIG_STATUS_INVALID);
  3913. litest_assert_enum_eq(
  3914. libinput_tablet_tool_config_pressure_range_set(tool, 0.0, 1.1),
  3915. LIBINPUT_CONFIG_STATUS_INVALID);
  3916. /* The last successful one */
  3917. litest_assert_double_eq(
  3918. libinput_tablet_tool_config_pressure_range_get_minimum(tool),
  3919. 0.2);
  3920. litest_assert_double_eq(
  3921. libinput_tablet_tool_config_pressure_range_get_maximum(tool),
  3922. 0.5);
  3923. litest_assert_double_eq(
  3924. libinput_tablet_tool_config_pressure_range_get_default_minimum(tool),
  3925. 0.0);
  3926. litest_assert_double_eq(
  3927. libinput_tablet_tool_config_pressure_range_get_default_maximum(tool),
  3928. 1.0);
  3929. }
  3930. END_TEST
  3931. START_TEST(tablet_pressure_config_set_minimum)
  3932. {
  3933. struct litest_device *dev = litest_current_device();
  3934. struct libinput *li = dev->libinput;
  3935. struct libinput_event *event;
  3936. struct libinput_event_tablet_tool *tev;
  3937. struct libinput_tablet_tool *tool;
  3938. struct axis_replacement axes[] = {
  3939. { ABS_DISTANCE, 0 },
  3940. { ABS_PRESSURE, 10 },
  3941. { -1, -1 },
  3942. };
  3943. double p, old_pressure;
  3944. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE))
  3945. return LITEST_NOT_APPLICABLE;
  3946. litest_tablet_proximity_in(dev, 5, 100, axes);
  3947. litest_drain_events(li);
  3948. litest_dispatch(li);
  3949. litest_tablet_motion(dev, 70, 70, axes);
  3950. litest_dispatch(li);
  3951. event = libinput_get_event(li);
  3952. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3953. tool = libinput_event_tablet_tool_get_tool(tev);
  3954. p = libinput_event_tablet_tool_get_pressure(tev);
  3955. litest_assert_double_gt(p, 0.0);
  3956. old_pressure = p;
  3957. litest_assert(libinput_tablet_tool_config_pressure_range_is_available(tool));
  3958. litest_assert_enum_eq(
  3959. libinput_tablet_tool_config_pressure_range_set(tool, 0.4, 1.0),
  3960. LIBINPUT_CONFIG_STATUS_SUCCESS);
  3961. libinput_event_destroy(event);
  3962. /* config doesn't take effect until we're out of prox */
  3963. for (int pos = 71; pos < 80; pos++) {
  3964. litest_tablet_motion(dev, pos, pos, axes);
  3965. litest_dispatch(li);
  3966. event = libinput_get_event(li);
  3967. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3968. p = libinput_event_tablet_tool_get_pressure(tev);
  3969. litest_assert_double_eq(p, old_pressure);
  3970. libinput_event_destroy(event);
  3971. }
  3972. litest_tablet_proximity_out(dev);
  3973. litest_timeout_tablet_proxout(li);
  3974. litest_drain_events(li);
  3975. /* 10% hw value is below our thresholds, so logical zero */
  3976. litest_axis_set_value(axes, ABS_PRESSURE, 10);
  3977. litest_tablet_proximity_in(dev, 70, 70, axes);
  3978. litest_drain_events(li);
  3979. for (int pos = 71; pos < 80; pos++) {
  3980. litest_tablet_motion(dev, pos, pos, axes);
  3981. litest_dispatch(li);
  3982. event = libinput_get_event(li);
  3983. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  3984. p = libinput_event_tablet_tool_get_pressure(tev);
  3985. litest_assert_double_eq(p, 0.00);
  3986. libinput_event_destroy(event);
  3987. }
  3988. /* 50% hw value mapped into a reduced range of 60% from hw range,
  3989. plus the 1% minimum offset, so our output pressure is actually ~15% */
  3990. litest_axis_set_value(axes, ABS_PRESSURE, 50);
  3991. litest_tablet_motion(dev, 70, 70, axes);
  3992. litest_dispatch(li);
  3993. event = libinput_get_event(li);
  3994. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  3995. p = libinput_event_tablet_tool_get_pressure(tev);
  3996. litest_assert_double_gt(p, 0.15);
  3997. litest_assert_double_le(p, 0.16);
  3998. libinput_event_destroy(event);
  3999. for (int pos = 71; pos < 80; pos++) {
  4000. litest_tablet_motion(dev, pos, pos, axes);
  4001. litest_dispatch(li);
  4002. event = libinput_get_event(li);
  4003. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4004. p = libinput_event_tablet_tool_get_pressure(tev);
  4005. litest_assert_double_ge(p, 0.15);
  4006. litest_assert_double_le(p, 0.16);
  4007. libinput_event_destroy(event);
  4008. }
  4009. }
  4010. END_TEST
  4011. START_TEST(tablet_pressure_config_set_maximum)
  4012. {
  4013. struct litest_device *dev = litest_current_device();
  4014. struct libinput *li = dev->libinput;
  4015. struct libinput_event *event;
  4016. struct libinput_event_tablet_tool *tev;
  4017. struct libinput_tablet_tool *tool;
  4018. struct axis_replacement axes[] = {
  4019. { ABS_DISTANCE, 0 },
  4020. { ABS_PRESSURE, 10 },
  4021. { -1, -1 },
  4022. };
  4023. double p, old_pressure;
  4024. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE))
  4025. return LITEST_NOT_APPLICABLE;
  4026. litest_tablet_proximity_in(dev, 5, 100, axes);
  4027. litest_drain_events(li);
  4028. litest_dispatch(li);
  4029. litest_tablet_motion(dev, 70, 70, axes);
  4030. litest_dispatch(li);
  4031. event = libinput_get_event(li);
  4032. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4033. tool = libinput_event_tablet_tool_get_tool(tev);
  4034. p = libinput_event_tablet_tool_get_pressure(tev);
  4035. litest_assert_double_gt(p, 0.0);
  4036. old_pressure = p;
  4037. litest_assert(libinput_tablet_tool_config_pressure_range_is_available(tool));
  4038. litest_assert_enum_eq(
  4039. libinput_tablet_tool_config_pressure_range_set(tool, 0.0, 0.6),
  4040. LIBINPUT_CONFIG_STATUS_SUCCESS);
  4041. libinput_event_destroy(event);
  4042. /* config doesn't take effect until we're out of prox */
  4043. for (int pos = 71; pos < 80; pos++) {
  4044. litest_tablet_motion(dev, pos, pos, axes);
  4045. litest_dispatch(li);
  4046. event = libinput_get_event(li);
  4047. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4048. p = libinput_event_tablet_tool_get_pressure(tev);
  4049. litest_assert_double_eq(p, old_pressure);
  4050. libinput_event_destroy(event);
  4051. }
  4052. litest_tablet_proximity_out(dev);
  4053. litest_timeout_tablet_proxout(li);
  4054. litest_axis_set_value(axes, ABS_PRESSURE, 10);
  4055. litest_tablet_proximity_in(dev, 70, 70, axes);
  4056. litest_drain_events(li);
  4057. /* 10% hw value mapped into a reduced range of 60% from hw range,
  4058. plus the 1% minimum offset so our output pressure is actually ~15% */
  4059. for (int pos = 71; pos < 80; pos++) {
  4060. litest_tablet_motion(dev, pos, pos, axes);
  4061. litest_dispatch(li);
  4062. event = libinput_get_event(li);
  4063. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4064. p = libinput_event_tablet_tool_get_pressure(tev);
  4065. litest_assert_double_ge(p, 0.15);
  4066. litest_assert_double_le(p, 0.16);
  4067. litest_assert_double_gt(p, old_pressure);
  4068. libinput_event_destroy(event);
  4069. }
  4070. /* 50% hw value mapped into a reduced range of 60% from hw range,
  4071. plus the 1% minimum offset, so our output pressure is actually ~83% */
  4072. litest_axis_set_value(axes, ABS_PRESSURE, 50);
  4073. for (int pos = 71; pos < 80; pos++) {
  4074. litest_tablet_motion(dev, pos, pos, axes);
  4075. litest_dispatch(li);
  4076. event = libinput_get_event(li);
  4077. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4078. p = libinput_event_tablet_tool_get_pressure(tev);
  4079. litest_assert_double_ge(p, 0.82);
  4080. litest_assert_double_le(p, 0.84);
  4081. libinput_event_destroy(event);
  4082. }
  4083. for (int hwp = 60; hwp < 100; hwp += 10) {
  4084. litest_axis_set_value(axes, ABS_PRESSURE, hwp);
  4085. for (int pos = 71; pos < 80; pos++) {
  4086. litest_tablet_motion(dev, pos, pos, axes);
  4087. litest_dispatch(li);
  4088. event = libinput_get_event(li);
  4089. tev = litest_is_tablet_event(event,
  4090. LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4091. p = libinput_event_tablet_tool_get_pressure(tev);
  4092. litest_assert_double_eq(p, 1.0);
  4093. libinput_event_destroy(event);
  4094. }
  4095. }
  4096. }
  4097. END_TEST
  4098. START_TEST(tablet_pressure_config_set_range)
  4099. {
  4100. struct litest_device *dev = litest_current_device();
  4101. struct libinput *li = dev->libinput;
  4102. struct libinput_event *event;
  4103. struct libinput_event_tablet_tool *tev;
  4104. struct libinput_tablet_tool *tool;
  4105. struct axis_replacement axes[] = {
  4106. { ABS_DISTANCE, 0 },
  4107. { ABS_PRESSURE, 10 },
  4108. { -1, -1 },
  4109. };
  4110. double p, old_pressure;
  4111. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE))
  4112. return LITEST_NOT_APPLICABLE;
  4113. litest_tablet_proximity_in(dev, 5, 100, axes);
  4114. litest_drain_events(li);
  4115. litest_dispatch(li);
  4116. litest_tablet_motion(dev, 70, 70, axes);
  4117. litest_dispatch(li);
  4118. event = libinput_get_event(li);
  4119. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4120. tool = libinput_event_tablet_tool_get_tool(tev);
  4121. p = libinput_event_tablet_tool_get_pressure(tev);
  4122. litest_assert_double_gt(p, 0.0);
  4123. old_pressure = p;
  4124. litest_assert(libinput_tablet_tool_config_pressure_range_is_available(tool));
  4125. litest_assert_enum_eq(
  4126. libinput_tablet_tool_config_pressure_range_set(tool, 0.4, 0.6),
  4127. LIBINPUT_CONFIG_STATUS_SUCCESS);
  4128. libinput_event_destroy(event);
  4129. /* config doesn't take effect until we're out of prox */
  4130. for (int i = 71; i < 80; i++) {
  4131. litest_tablet_motion(dev, i, i, axes);
  4132. litest_dispatch(li);
  4133. event = libinput_get_event(li);
  4134. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4135. p = libinput_event_tablet_tool_get_pressure(tev);
  4136. litest_assert_double_eq(p, old_pressure);
  4137. libinput_event_destroy(event);
  4138. }
  4139. litest_tablet_proximity_out(dev);
  4140. litest_timeout_tablet_proxout(li);
  4141. litest_drain_events(li);
  4142. litest_tablet_proximity_in(dev, 70, 70, axes);
  4143. litest_drain_events(li);
  4144. for (double pressure = 0.0, i = 71; pressure <= 100; pressure += 5, i += 0.2) {
  4145. litest_axis_set_value(axes, ABS_PRESSURE, pressure);
  4146. litest_tablet_motion(dev, i, i, axes);
  4147. litest_dispatch(li);
  4148. event = libinput_get_event(li);
  4149. if (libinput_event_get_type(event) == LIBINPUT_EVENT_TABLET_TOOL_AXIS)
  4150. tev = litest_is_tablet_event(event,
  4151. LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4152. else
  4153. tev = litest_is_tablet_event(event,
  4154. LIBINPUT_EVENT_TABLET_TOOL_TIP);
  4155. p = libinput_event_tablet_tool_get_pressure(tev);
  4156. if (pressure <= 40) {
  4157. litest_assert_double_eq(p, 0.0);
  4158. } else if (pressure >= 60) {
  4159. litest_assert_double_eq(p, 1.0);
  4160. } else {
  4161. litest_assert_double_ge(p, (pressure - 1 - 40) / 20.0);
  4162. litest_assert_double_le(p, (pressure - 40) / 20.0);
  4163. }
  4164. libinput_event_destroy(event);
  4165. }
  4166. }
  4167. END_TEST
  4168. START_TEST(tablet_pressure_config_resets_offset)
  4169. {
  4170. struct litest_device *dev = litest_current_device();
  4171. struct libinput *li = dev->libinput;
  4172. struct axis_replacement axes[] = {
  4173. { ABS_DISTANCE, 70 },
  4174. { ABS_PRESSURE, 70 }, /* high pressure offset */
  4175. { -1, -1 },
  4176. };
  4177. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE))
  4178. return LITEST_NOT_APPLICABLE;
  4179. litest_tablet_proximity_in(dev, 5, 100, axes);
  4180. litest_drain_events(li);
  4181. litest_dispatch(li);
  4182. litest_tablet_motion(dev, 70, 70, axes);
  4183. litest_dispatch(li);
  4184. {
  4185. _destroy_(libinput_event) *event = libinput_get_event(li);
  4186. auto tev =
  4187. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4188. auto tool = libinput_event_tablet_tool_get_tool(tev);
  4189. litest_assert(
  4190. libinput_tablet_tool_config_pressure_range_is_available(tool));
  4191. litest_assert_enum_eq(
  4192. libinput_tablet_tool_config_pressure_range_set(tool,
  4193. 0.01,
  4194. 0.99),
  4195. LIBINPUT_CONFIG_STATUS_SUCCESS);
  4196. }
  4197. litest_tablet_proximity_out(dev);
  4198. litest_timeout_tablet_proxout(li);
  4199. litest_drain_events(li);
  4200. /* Config should be applied on prox in */
  4201. litest_axis_set_value(axes, ABS_PRESSURE, 71);
  4202. litest_tablet_proximity_in(dev, 72, 72, axes);
  4203. litest_drain_events(li);
  4204. litest_tablet_proximity_out(dev);
  4205. litest_timeout_tablet_proxout(li);
  4206. litest_drain_events(li);
  4207. /* Two prox in/out cycles to get past the heuristics on devices without
  4208. * ABS_DISTANCE
  4209. */
  4210. litest_axis_set_value(axes, ABS_PRESSURE, 72);
  4211. litest_tablet_proximity_in(dev, 75, 75, axes);
  4212. litest_drain_events(li);
  4213. litest_tablet_proximity_out(dev);
  4214. litest_timeout_tablet_proxout(li);
  4215. litest_drain_events(li);
  4216. for (double pressure = 10.0, i = 71; pressure <= 25; pressure += 5, i += 0.2) {
  4217. litest_log_group("Prox in/out with pressure %.f", pressure) {
  4218. litest_axis_set_value(axes, ABS_PRESSURE, pressure);
  4219. litest_tablet_proximity_in(dev, i, i, axes);
  4220. litest_dispatch(li);
  4221. _destroy_(libinput_event) *event = libinput_get_event(li);
  4222. auto tev = litest_is_tablet_event(
  4223. event,
  4224. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4225. double p = libinput_event_tablet_tool_get_pressure(tev);
  4226. /* checking if >5% is good enough here, it'd be zero if the
  4227. * 70% threshold were locked in */
  4228. litest_assert_double_gt(p, 0.05);
  4229. litest_tablet_proximity_out(dev);
  4230. litest_timeout_tablet_proxout(li);
  4231. litest_drain_events(li);
  4232. }
  4233. }
  4234. }
  4235. END_TEST
  4236. START_TEST(tablet_pressure_config_01_does_not_reset_offset)
  4237. {
  4238. struct litest_device *dev = litest_current_device();
  4239. struct libinput *li = dev->libinput;
  4240. struct axis_replacement axes[] = {
  4241. { ABS_PRESSURE, 20 }, /* high pressure offset */
  4242. { -1, -1 },
  4243. };
  4244. /* test is only run for specific devices because some of our test devices
  4245. * write ABS_PRESSURE 0 events on prox out and that changes the test outcomes.
  4246. */
  4247. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE))
  4248. return LITEST_NOT_APPLICABLE;
  4249. if (libevdev_has_event_code(dev->evdev, EV_ABS, ABS_DISTANCE))
  4250. return LITEST_NOT_APPLICABLE;
  4251. litest_drain_events(li); /* Drain potential tip event */
  4252. litest_tablet_proximity_in(dev, 68, 68, axes);
  4253. litest_dispatch(li);
  4254. {
  4255. _destroy_(libinput_event) *event = libinput_get_event(li);
  4256. auto tev = litest_is_tablet_event(event,
  4257. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4258. auto tool = libinput_event_tablet_tool_get_tool(tev);
  4259. litest_assert(
  4260. libinput_tablet_tool_config_pressure_range_is_available(tool));
  4261. litest_assert_enum_eq(
  4262. libinput_tablet_tool_config_pressure_range_set(tool, 0.0, 1.0),
  4263. LIBINPUT_CONFIG_STATUS_SUCCESS);
  4264. }
  4265. /* Drain potential tip event. */
  4266. litest_drain_events(li);
  4267. /* No motion events here, that might change the offset! */
  4268. litest_tablet_proximity_out(dev);
  4269. litest_timeout_tablet_proxout(li);
  4270. litest_drain_events(li);
  4271. litest_checkpoint("second prox in");
  4272. /* Config should be applied on prox in */
  4273. litest_axis_set_value(axes, ABS_PRESSURE, 31);
  4274. litest_tablet_proximity_in(dev, 72, 72, axes);
  4275. litest_drain_events(li);
  4276. litest_tablet_proximity_out(dev);
  4277. litest_timeout_tablet_proxout(li);
  4278. litest_drain_events(li);
  4279. /* Two prox in/out cycles to finalize heuristics */
  4280. litest_with_logcapture(li, capture) {
  4281. libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_INFO);
  4282. litest_axis_set_value(axes, ABS_PRESSURE, 32);
  4283. litest_tablet_proximity_in(dev, 75, 75, axes);
  4284. litest_drain_events(li);
  4285. litest_tablet_proximity_out(dev);
  4286. litest_timeout_tablet_proxout(li);
  4287. litest_drain_events(li);
  4288. /* Full message is "Pressure offset detected of n% detected on tool pen"
  4289. */
  4290. litest_assert_strv_substring(capture->infos, "detected on tool pen");
  4291. }
  4292. litest_log_group("Expecting pressure with offset factored in") {
  4293. litest_axis_set_value(axes, ABS_PRESSURE, 25);
  4294. litest_tablet_proximity_in(dev, 50, 50, axes);
  4295. litest_dispatch(li);
  4296. _destroy_(libinput_event) *event = libinput_get_event(li);
  4297. auto tev = litest_is_tablet_event(event,
  4298. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4299. double p = libinput_event_tablet_tool_get_pressure(tev);
  4300. /* Pressure 25%, base offset of 20% so we should get 5% plus the 1% we
  4301. * use anyway */
  4302. litest_assert_double_ge(p, 0.05);
  4303. litest_assert_double_le(p, 0.07);
  4304. litest_tablet_proximity_out(dev);
  4305. litest_timeout_tablet_proxout(li);
  4306. litest_drain_events(li);
  4307. }
  4308. litest_log_group("Expecting low pressure to reduce offset") {
  4309. /* Because we didn't configure the range, we expect lower pressure to
  4310. * reduce the offset */
  4311. litest_axis_set_value(axes, ABS_PRESSURE, 5);
  4312. litest_tablet_proximity_in(dev, 50, 50, axes);
  4313. litest_dispatch(li);
  4314. _destroy_(libinput_event) *event = libinput_get_event(li);
  4315. auto tev = litest_is_tablet_event(event,
  4316. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4317. double p = libinput_event_tablet_tool_get_pressure(tev);
  4318. litest_assert_double_eq(p, 0.00);
  4319. litest_tablet_proximity_out(dev);
  4320. litest_timeout_tablet_proxout(li);
  4321. litest_drain_events(li);
  4322. }
  4323. }
  4324. END_TEST
  4325. static void
  4326. pressure_threshold_warning(struct libinput *libinput,
  4327. enum libinput_log_priority priority,
  4328. const char *format,
  4329. va_list args)
  4330. {
  4331. struct litest_user_data *user_data = libinput_get_user_data(libinput);
  4332. int *warning_triggered = user_data->private;
  4333. if (priority == LIBINPUT_LOG_PRIORITY_ERROR &&
  4334. strstr(format, "pressure offset greater"))
  4335. (*warning_triggered)++;
  4336. }
  4337. START_TEST(tablet_pressure_offset_exceed_threshold)
  4338. {
  4339. struct litest_device *dev = litest_current_device();
  4340. struct libinput *li = dev->libinput;
  4341. struct axis_replacement axes[] = {
  4342. { ABS_DISTANCE, 70 },
  4343. { ABS_PRESSURE, 60 },
  4344. { -1, -1 },
  4345. };
  4346. int warning_triggered = 0;
  4347. struct litest_user_data *user_data = libinput_get_user_data(li);
  4348. /* Tablet without distance: offset takes effect on third prox-in */
  4349. if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_DISTANCE)) {
  4350. for (int i = 0; i < 2; i++) {
  4351. litest_tablet_proximity_in(dev, 5, 100, axes);
  4352. litest_tablet_proximity_out(dev);
  4353. litest_timeout_tablet_proxout(li);
  4354. }
  4355. }
  4356. litest_drain_events(li);
  4357. user_data->private = &warning_triggered;
  4358. libinput_log_set_handler(li, pressure_threshold_warning);
  4359. litest_tablet_proximity_in(dev, 5, 100, axes);
  4360. litest_dispatch(li);
  4361. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, 0.60);
  4362. litest_assert_int_eq(warning_triggered, 1);
  4363. litest_restore_log_handler(li);
  4364. }
  4365. END_TEST
  4366. START_TEST(tablet_pressure_offset_none_for_zero_distance)
  4367. {
  4368. struct litest_device *dev = litest_current_device();
  4369. struct libinput *li = dev->libinput;
  4370. struct axis_replacement axes[] = {
  4371. { ABS_DISTANCE, 0 },
  4372. { ABS_PRESSURE, 20 },
  4373. { -1, -1 },
  4374. };
  4375. litest_drain_events(li);
  4376. /* we're going straight to touch on proximity, make sure we don't
  4377. * offset the pressure here */
  4378. litest_with_event_frame(dev) {
  4379. litest_tablet_proximity_in(dev, 5, 100, axes);
  4380. litest_tablet_tip_down(dev, 5, 100, axes);
  4381. }
  4382. litest_dispatch(li);
  4383. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, 0.20);
  4384. }
  4385. END_TEST
  4386. START_TEST(tablet_pressure_offset_none_for_small_distance)
  4387. {
  4388. struct litest_device *dev = litest_current_device();
  4389. struct libinput *li = dev->libinput;
  4390. struct axis_replacement axes[] = {
  4391. { ABS_DISTANCE, 20 },
  4392. { ABS_PRESSURE, 20 },
  4393. { -1, -1 },
  4394. };
  4395. /* stylus too close to the tablet on the proximity in, ignore any
  4396. * pressure offset */
  4397. litest_tablet_proximity_in(dev, 5, 100, axes);
  4398. litest_drain_events(li);
  4399. litest_dispatch(li);
  4400. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  4401. litest_axis_set_value(axes, ABS_PRESSURE, 21);
  4402. litest_tablet_tip_down(dev, 70, 70, axes);
  4403. litest_drain_events(li);
  4404. litest_axis_set_value(axes, ABS_PRESSURE, 20);
  4405. litest_tablet_motion(dev, 70, 70, axes);
  4406. litest_dispatch(li);
  4407. assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.20);
  4408. }
  4409. END_TEST
  4410. START_TEST(tablet_pressure_across_multiple_tablets)
  4411. {
  4412. struct litest_device *cintiq12wx = litest_current_device();
  4413. struct libinput *li = cintiq12wx->libinput;
  4414. struct litest_device *mobilestudio =
  4415. litest_add_device(li, LITEST_WACOM_CINTIQ_PRO16_PEN);
  4416. bool direction = litest_test_param_get_bool(test_env->params, "8k-to-1k");
  4417. struct litest_device *first = direction ? mobilestudio : cintiq12wx;
  4418. struct litest_device *second = direction ? cintiq12wx : mobilestudio;
  4419. bool with_range = litest_test_param_get_bool(test_env->params, "with-range");
  4420. bool with_second_range =
  4421. litest_test_param_get_bool(test_env->params, "with-second-range");
  4422. struct axis_replacement axes[] = {
  4423. { ABS_DISTANCE, 20 },
  4424. { ABS_PRESSURE, 0 },
  4425. { -1, -1 },
  4426. };
  4427. bool have_cintiq12wx = false;
  4428. bool have_mobilestudio = false;
  4429. litest_dispatch(li);
  4430. while (!have_cintiq12wx || !have_mobilestudio) {
  4431. litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED);
  4432. _destroy_(libinput_event) *ev = libinput_get_event(li);
  4433. litest_assert_event_type(ev, LIBINPUT_EVENT_DEVICE_ADDED);
  4434. if (libinput_event_get_device(ev) == cintiq12wx->libinput_device)
  4435. have_cintiq12wx = true;
  4436. if (libinput_event_get_device(ev) == mobilestudio->libinput_device)
  4437. have_mobilestudio = true;
  4438. litest_checkpoint("Have Cintiq 12WX: %s, MobileStudio: %s",
  4439. yesno(have_cintiq12wx),
  4440. yesno(have_mobilestudio));
  4441. litest_dispatch(li);
  4442. }
  4443. litest_drain_events(li);
  4444. litest_mark_test_start();
  4445. _unref_(libinput_tablet_tool) *tool = NULL;
  4446. if (with_range) {
  4447. litest_log_group("Prox in/out on %s to apply pressure range to tool",
  4448. libinput_device_get_name(first->libinput_device)) {
  4449. litest_tablet_proximity_in(first, 50, 50, axes);
  4450. litest_dispatch(li);
  4451. _destroy_(libinput_event) *ev = libinput_get_event(li);
  4452. struct libinput_event_tablet_tool *tev = litest_is_tablet_event(
  4453. ev,
  4454. LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4455. tool = libinput_tablet_tool_ref(
  4456. libinput_event_tablet_tool_get_tool(tev));
  4457. libinput_tablet_tool_config_pressure_range_set(tool, 0.2, 0.7);
  4458. litest_tablet_proximity_out(first);
  4459. litest_timeout_tablet_proxout(li);
  4460. litest_drain_events(li);
  4461. }
  4462. }
  4463. /* Proximity in followed by pressure up to 70%, on the first
  4464. * device, then on the second one. They have different pressure
  4465. * ranges but we expect the normalized range to be the same
  4466. * proportionate range */
  4467. struct litest_device *dev = first;
  4468. for (int i = 0; i < 2; i++, dev = second) {
  4469. litest_checkpoint("Putting pen into proximity on %s",
  4470. libinput_device_get_name(dev->libinput_device));
  4471. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  4472. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  4473. litest_tablet_proximity_in(dev, 50, 50, axes);
  4474. litest_dispatch(li);
  4475. /* FIXME: this tests a bug in the code. The pressure range is updated
  4476. * on proximity out only, so if we update the range while the tool
  4477. * is in prox only the tablet the tool *leaves* from gets updated.
  4478. * If we move into a new tablet the pressure range there isn't updated
  4479. * until we leave proximity of that tablet.
  4480. *
  4481. * Since pressure ranges don't change often and the vast majority of
  4482. * users don't have more than one tablet anyway, this isn't worth
  4483. * fixing.
  4484. *
  4485. * For this test, if we have a second range and we're on the second
  4486. * device we add an extra prox out/in to get the pressure range applied
  4487. * correctly.
  4488. */
  4489. if (with_second_range && dev == second) {
  4490. litest_log_group("Updating pressure range") {
  4491. libinput_tablet_tool_config_pressure_range_set(tool,
  4492. 0.5,
  4493. 0.9);
  4494. litest_tablet_proximity_out(dev);
  4495. litest_timeout_tablet_proxout(li);
  4496. litest_drain_events(li);
  4497. litest_tablet_proximity_in(dev, 50, 50, axes);
  4498. litest_dispatch(li);
  4499. }
  4500. }
  4501. litest_assert_tablet_proximity_event(
  4502. li,
  4503. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  4504. for (int pressure = 10; pressure <= 70; pressure += 10) {
  4505. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  4506. litest_axis_set_value(axes, ABS_PRESSURE, pressure);
  4507. litest_tablet_motion(dev, 50, 50, axes);
  4508. litest_dispatch(li);
  4509. _destroy_(libinput_event) *ev = libinput_get_event(li);
  4510. litest_assert_event_type_is_one_of(
  4511. ev,
  4512. LIBINPUT_EVENT_TABLET_TOOL_AXIS,
  4513. LIBINPUT_EVENT_TABLET_TOOL_TIP);
  4514. struct libinput_event_tablet_tool *tev =
  4515. libinput_event_get_tablet_tool_event(ev);
  4516. double tool_pressure =
  4517. libinput_event_tablet_tool_get_pressure(tev);
  4518. if (with_second_range && dev == second) {
  4519. if (pressure < 50) {
  4520. litest_assert_double_eq(tool_pressure, 0.0);
  4521. } else if (pressure == 60) {
  4522. litest_assert_event_type(
  4523. ev,
  4524. LIBINPUT_EVENT_TABLET_TOOL_TIP);
  4525. litest_assert_double_ge(tool_pressure, 0.0);
  4526. } else {
  4527. litest_assert_double_lt(tool_pressure, 0.7);
  4528. }
  4529. } else if (with_range) {
  4530. /* with our range 30% device pressure should be around
  4531. * 10% actual pressure and trigger the tip down */
  4532. if (pressure < 30) {
  4533. litest_assert_double_eq(tool_pressure, 0.0);
  4534. } else if (pressure == 30) {
  4535. litest_assert_event_type(
  4536. ev,
  4537. LIBINPUT_EVENT_TABLET_TOOL_TIP);
  4538. litest_assert_double_ge(tool_pressure, 0.0);
  4539. } else if (pressure < 70) {
  4540. litest_assert_double_ge(tool_pressure, 0.1);
  4541. litest_assert_double_lt(tool_pressure, 1.0);
  4542. } else {
  4543. litest_assert_double_eq(tool_pressure, 1.0);
  4544. }
  4545. } else {
  4546. if (pressure == 10)
  4547. litest_assert_event_type(
  4548. ev,
  4549. LIBINPUT_EVENT_TABLET_TOOL_TIP);
  4550. /* We start at device range 10% but we always have a
  4551. * small threshold */
  4552. litest_assert_double_gt_epsilon(pressure, 0.09, 0);
  4553. litest_assert_double_le(tool_pressure, 0.7);
  4554. }
  4555. if (!tool)
  4556. tool = libinput_tablet_tool_ref(
  4557. libinput_event_tablet_tool_get_tool(tev));
  4558. }
  4559. litest_checkpoint("Leaving proximity on %s",
  4560. libinput_device_get_name(dev->libinput_device));
  4561. litest_tablet_proximity_out(dev);
  4562. litest_timeout_tablet_proxout(li);
  4563. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4564. litest_assert_tablet_tip_event(li, LIBINPUT_TABLET_TOOL_TIP_UP);
  4565. litest_assert_tablet_proximity_event(
  4566. li,
  4567. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  4568. }
  4569. litest_device_destroy(mobilestudio);
  4570. }
  4571. END_TEST
  4572. START_TEST(tablet_pressure_after_unplug)
  4573. {
  4574. _litest_context_destroy_ struct libinput *li = litest_create_context();
  4575. struct litest_device *dev =
  4576. litest_add_device(li, LITEST_WACOM_CINTIQ_PRO16_PEN);
  4577. struct axis_replacement axes[] = {
  4578. { ABS_DISTANCE, 20 },
  4579. { ABS_PRESSURE, 0 },
  4580. { -1, -1 },
  4581. };
  4582. litest_drain_events(li);
  4583. litest_mark_test_start();
  4584. /* Unplug 10 times because that's more than however many tablets
  4585. * we keep track of internally */
  4586. for (int iteration = 0; iteration < 10; iteration++) {
  4587. litest_checkpoint("Putting pen into proximity");
  4588. litest_tablet_proximity_in(dev, 50, 50, axes);
  4589. litest_tablet_motion(dev, 51, 51, axes);
  4590. litest_dispatch(li);
  4591. litest_tablet_proximity_out(dev);
  4592. litest_checkpoint("Unplugging/replugging device");
  4593. litest_device_destroy(dev);
  4594. litest_dispatch(li);
  4595. litest_drain_events(li);
  4596. dev = litest_add_device(li, LITEST_WACOM_CINTIQ_PRO16_PEN);
  4597. litest_dispatch(li);
  4598. litest_drain_events(li);
  4599. }
  4600. litest_checkpoint("Putting pen into proximity");
  4601. litest_tablet_proximity_in(dev, 49, 49, axes);
  4602. litest_dispatch(li);
  4603. litest_assert_tablet_proximity_event(li,
  4604. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  4605. for (int i = 1; i < 5; i++) {
  4606. litest_tablet_motion(dev, 50 + i, 50 + i, axes);
  4607. litest_dispatch(li);
  4608. struct libinput_event *event = libinput_get_event(li);
  4609. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4610. libinput_event_destroy(event);
  4611. }
  4612. litest_checkpoint("Putting pen tip down");
  4613. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  4614. litest_axis_set_value(axes, ABS_PRESSURE, 10);
  4615. litest_tablet_tip_down(dev, 50, 50, axes);
  4616. litest_dispatch(li);
  4617. litest_assert_tablet_tip_event(li, LIBINPUT_TABLET_TOOL_TIP_DOWN);
  4618. double old_pressure = 0;
  4619. for (int i = 1; i < 5; i++) {
  4620. litest_axis_set_value(axes, ABS_PRESSURE, 10 + i);
  4621. litest_tablet_motion(dev, 50 + i, 50 + i, axes);
  4622. litest_dispatch(li);
  4623. struct libinput_event *event = libinput_get_event(li);
  4624. struct libinput_event_tablet_tool *tev =
  4625. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4626. double pressure = libinput_event_tablet_tool_get_pressure(tev);
  4627. litest_assert_double_gt(pressure, old_pressure);
  4628. libinput_event_destroy(event);
  4629. }
  4630. litest_checkpoint("Putting pen tip up");
  4631. litest_axis_set_value(axes, ABS_DISTANCE, 20);
  4632. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  4633. litest_tablet_tip_up(dev, 50, 50, axes);
  4634. litest_dispatch(li);
  4635. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4636. litest_assert_tablet_tip_event(li, LIBINPUT_TABLET_TOOL_TIP_UP);
  4637. litest_checkpoint("Putting out of proximity");
  4638. litest_tablet_proximity_out(dev);
  4639. litest_timeout_tablet_proxout(li);
  4640. litest_assert_tablet_proximity_event(li,
  4641. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  4642. litest_device_destroy(dev);
  4643. }
  4644. END_TEST
  4645. START_TEST(tablet_distance_range)
  4646. {
  4647. struct litest_device *dev = litest_current_device();
  4648. struct libinput *li = dev->libinput;
  4649. struct libinput_event *event;
  4650. struct libinput_event_tablet_tool *tev;
  4651. struct axis_replacement axes[] = {
  4652. { ABS_DISTANCE, 20 },
  4653. { ABS_PRESSURE, 0 },
  4654. { -1, -1 },
  4655. };
  4656. int distance;
  4657. double dist;
  4658. litest_tablet_proximity_in(dev, 5, 100, axes);
  4659. litest_drain_events(li);
  4660. litest_dispatch(li);
  4661. for (distance = 0; distance <= 100; distance += 10) {
  4662. litest_axis_set_value(axes, ABS_DISTANCE, distance);
  4663. litest_tablet_motion(dev, 70, 70, axes);
  4664. litest_dispatch(li);
  4665. event = libinput_get_event(li);
  4666. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4667. dist = libinput_event_tablet_tool_get_distance(tev);
  4668. litest_assert_double_ge(dist, 0.0);
  4669. litest_assert_double_le(dist, 1.0);
  4670. libinput_event_destroy(event);
  4671. }
  4672. }
  4673. END_TEST
  4674. START_TEST(tilt_available)
  4675. {
  4676. struct litest_device *dev = litest_current_device();
  4677. struct libinput *li = dev->libinput;
  4678. struct libinput_event *event;
  4679. struct libinput_event_tablet_tool *tev;
  4680. struct libinput_tablet_tool *tool;
  4681. struct axis_replacement axes[] = {
  4682. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 80 },
  4683. { ABS_TILT_Y, 20 }, { -1, -1 },
  4684. };
  4685. litest_drain_events(li);
  4686. litest_tablet_proximity_in(dev, 10, 10, axes);
  4687. litest_dispatch(li);
  4688. event = libinput_get_event(li);
  4689. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4690. tool = libinput_event_tablet_tool_get_tool(tev);
  4691. litest_assert(libinput_tablet_tool_has_tilt(tool));
  4692. libinput_event_destroy(event);
  4693. }
  4694. END_TEST
  4695. START_TEST(tilt_not_available)
  4696. {
  4697. struct litest_device *dev = litest_current_device();
  4698. struct libinput *li = dev->libinput;
  4699. struct libinput_event *event;
  4700. struct libinput_event_tablet_tool *tev;
  4701. struct libinput_tablet_tool *tool;
  4702. struct axis_replacement axes[] = {
  4703. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 80 },
  4704. { ABS_TILT_Y, 20 }, { -1, -1 },
  4705. };
  4706. litest_drain_events(li);
  4707. litest_tablet_proximity_in(dev, 10, 10, axes);
  4708. litest_dispatch(li);
  4709. event = libinput_get_event(li);
  4710. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4711. tool = libinput_event_tablet_tool_get_tool(tev);
  4712. litest_assert(!libinput_tablet_tool_has_tilt(tool));
  4713. libinput_event_destroy(event);
  4714. }
  4715. END_TEST
  4716. START_TEST(tilt_x)
  4717. {
  4718. struct litest_device *dev = litest_current_device();
  4719. struct libinput *li = dev->libinput;
  4720. struct libinput_event *event;
  4721. struct libinput_event_tablet_tool *tev;
  4722. struct axis_replacement axes[] = {
  4723. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 10 },
  4724. { ABS_TILT_Y, 0 }, { -1, -1 },
  4725. };
  4726. double tx, ty;
  4727. int tilt;
  4728. double expected_tx;
  4729. litest_drain_events(li);
  4730. litest_tablet_proximity_in(dev, 10, 10, axes);
  4731. litest_dispatch(li);
  4732. event = libinput_get_event(li);
  4733. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4734. /* 90% of the actual axis but mapped into a [-64, 64] tilt range, so
  4735. * we expect 51 degrees ± rounding errors */
  4736. tx = libinput_event_tablet_tool_get_tilt_x(tev);
  4737. litest_assert_double_le(tx, -50);
  4738. litest_assert_double_ge(tx, -52);
  4739. ty = libinput_event_tablet_tool_get_tilt_y(tev);
  4740. litest_assert_double_ge(ty, -65);
  4741. litest_assert_double_lt(ty, -63);
  4742. libinput_event_destroy(event);
  4743. expected_tx = -64.0;
  4744. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  4745. litest_axis_set_value(axes, ABS_PRESSURE, 1);
  4746. for (tilt = 0; tilt <= 100; tilt += 5) {
  4747. litest_axis_set_value(axes, ABS_TILT_X, tilt);
  4748. /* work around smoothing */
  4749. litest_tablet_motion(dev, 10, 10, axes);
  4750. litest_tablet_motion(dev, 10, 11, axes);
  4751. litest_tablet_motion(dev, 10, 10, axes);
  4752. litest_drain_events(li);
  4753. litest_tablet_motion(dev, 10, 11, axes);
  4754. litest_dispatch(li);
  4755. event = libinput_get_event(li);
  4756. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4757. tx = libinput_event_tablet_tool_get_tilt_x(tev);
  4758. litest_assert_double_ge(tx, expected_tx - 2);
  4759. litest_assert_double_le(tx, expected_tx + 2);
  4760. ty = libinput_event_tablet_tool_get_tilt_y(tev);
  4761. litest_assert_double_ge(ty, -65);
  4762. litest_assert_double_lt(ty, -63);
  4763. libinput_event_destroy(event);
  4764. expected_tx = tx + 6.04;
  4765. }
  4766. /* the last event must reach the max */
  4767. litest_assert_double_ge(tx, 63.0);
  4768. litest_assert_double_le(tx, 64.0);
  4769. }
  4770. END_TEST
  4771. START_TEST(tilt_y)
  4772. {
  4773. struct litest_device *dev = litest_current_device();
  4774. struct libinput *li = dev->libinput;
  4775. struct libinput_event *event;
  4776. struct libinput_event_tablet_tool *tev;
  4777. struct axis_replacement axes[] = {
  4778. { ABS_DISTANCE, 10 }, { ABS_PRESSURE, 0 }, { ABS_TILT_X, 0 },
  4779. { ABS_TILT_Y, 10 }, { -1, -1 },
  4780. };
  4781. double tx, ty;
  4782. int tilt;
  4783. double expected_ty;
  4784. litest_drain_events(li);
  4785. litest_tablet_proximity_in(dev, 10, 10, axes);
  4786. litest_dispatch(li);
  4787. event = libinput_get_event(li);
  4788. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4789. /* 90% of the actual axis but mapped into a [-64, 64] tilt range, so
  4790. * we expect 50 degrees ± rounding errors */
  4791. ty = libinput_event_tablet_tool_get_tilt_y(tev);
  4792. litest_assert_double_le(ty, -50);
  4793. litest_assert_double_ge(ty, -52);
  4794. tx = libinput_event_tablet_tool_get_tilt_x(tev);
  4795. litest_assert_double_ge(tx, -65);
  4796. litest_assert_double_lt(tx, -63);
  4797. libinput_event_destroy(event);
  4798. expected_ty = -64;
  4799. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  4800. litest_axis_set_value(axes, ABS_PRESSURE, 1);
  4801. for (tilt = 0; tilt <= 100; tilt += 5) {
  4802. litest_axis_set_value(axes, ABS_TILT_Y, tilt);
  4803. /* work around smoothing */
  4804. litest_tablet_motion(dev, 10, 11, axes);
  4805. litest_tablet_motion(dev, 10, 10, axes);
  4806. litest_tablet_motion(dev, 10, 11, axes);
  4807. litest_drain_events(li);
  4808. litest_tablet_motion(dev, 10, 10, axes);
  4809. litest_dispatch(li);
  4810. event = libinput_get_event(li);
  4811. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4812. ty = libinput_event_tablet_tool_get_tilt_y(tev);
  4813. litest_assert_double_ge(ty, expected_ty - 2);
  4814. litest_assert_double_le(ty, expected_ty + 2);
  4815. tx = libinput_event_tablet_tool_get_tilt_x(tev);
  4816. litest_assert_double_ge(tx, -65);
  4817. litest_assert_double_lt(tx, -63);
  4818. libinput_event_destroy(event);
  4819. expected_ty = ty + 6;
  4820. }
  4821. /* the last event must reach the max */
  4822. litest_assert_double_ge(ty, 63.0);
  4823. litest_assert_double_le(tx, 64.0);
  4824. }
  4825. END_TEST
  4826. START_TEST(tilt_fixed_points)
  4827. {
  4828. struct litest_device *dev = litest_current_device();
  4829. struct libinput *li = dev->libinput;
  4830. struct libinput_event *event;
  4831. struct libinput_event_tablet_tool *tev;
  4832. struct axis_replacement axes[] = {
  4833. { ABS_DISTANCE, 10 },
  4834. { ABS_PRESSURE, 0 },
  4835. { -1, -1 },
  4836. };
  4837. /* On devices with a range of [-N, M], make sure we calculate the hw zero
  4838. * position as zero and that the respective min/max resolve to our (hardcoded)
  4839. * min/max degree values
  4840. */
  4841. const struct input_absinfo *abs = libevdev_get_abs_info(dev->evdev, ABS_TILT_X);
  4842. if (abs->minimum >= 0)
  4843. return LITEST_NOT_APPLICABLE;
  4844. /* If the tablet reports physical resolutions we don't need to test them */
  4845. if (abs->resolution != 0)
  4846. return LITEST_NOT_APPLICABLE;
  4847. /* see tablet_fix_tilt() */
  4848. bool is_adjusted = (int)absinfo_range(abs) % 2 == 0;
  4849. int axis_value;
  4850. double expected;
  4851. int testcase = litest_test_param_get_i32(test_env->params, "tilt");
  4852. switch (testcase) {
  4853. case TILT_MINIMUM:
  4854. axis_value = abs->minimum;
  4855. expected = -64.0;
  4856. break;
  4857. case TILT_CENTER:
  4858. axis_value = 0;
  4859. expected = 0.0;
  4860. break;
  4861. case TILT_MAXIMUM:
  4862. axis_value = abs->maximum;
  4863. expected = 64.0;
  4864. break;
  4865. default:
  4866. litest_abort_msg("Invalid tilt testcase '%d'", testcase);
  4867. }
  4868. litest_drain_events(li);
  4869. litest_with_event_frame(dev) {
  4870. litest_tablet_proximity_in(dev, 10, 10, axes);
  4871. litest_event(dev, EV_ABS, ABS_TILT_X, axis_value);
  4872. litest_event(dev, EV_ABS, ABS_TILT_Y, axis_value);
  4873. }
  4874. litest_dispatch(li);
  4875. event = libinput_get_event(li);
  4876. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4877. double tx = libinput_event_tablet_tool_get_tilt_x(tev);
  4878. double ty = libinput_event_tablet_tool_get_tilt_y(tev);
  4879. litest_assert_double_eq(tx, expected);
  4880. if (is_adjusted) {
  4881. litest_assert_double_ge(ty, expected - 1);
  4882. litest_assert_double_lt(ty, expected);
  4883. } else {
  4884. litest_assert_double_eq(ty, expected);
  4885. }
  4886. libinput_event_destroy(event);
  4887. }
  4888. END_TEST
  4889. START_TEST(relative_no_profile)
  4890. {
  4891. struct litest_device *dev = litest_current_device();
  4892. struct libinput_device *device = dev->libinput_device;
  4893. enum libinput_config_accel_profile profile;
  4894. enum libinput_config_status status;
  4895. uint32_t profiles;
  4896. litest_assert(libinput_device_config_accel_is_available(device));
  4897. profile = libinput_device_config_accel_get_default_profile(device);
  4898. litest_assert_enum_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
  4899. profile = libinput_device_config_accel_get_profile(device);
  4900. litest_assert_enum_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
  4901. profiles = libinput_device_config_accel_get_profiles(device);
  4902. litest_assert_enum_eq(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, 0);
  4903. litest_assert_enum_eq(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, 0);
  4904. status = libinput_device_config_accel_set_profile(
  4905. device,
  4906. LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
  4907. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
  4908. profile = libinput_device_config_accel_get_profile(device);
  4909. litest_assert_enum_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
  4910. status = libinput_device_config_accel_set_profile(
  4911. device,
  4912. LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
  4913. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
  4914. profile = libinput_device_config_accel_get_profile(device);
  4915. litest_assert_enum_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
  4916. }
  4917. END_TEST
  4918. START_TEST(relative_no_delta_prox_in)
  4919. {
  4920. struct litest_device *dev = litest_current_device();
  4921. struct libinput *li = dev->libinput;
  4922. struct libinput_event *event;
  4923. struct libinput_event_tablet_tool *tev;
  4924. struct axis_replacement axes[] = {
  4925. { ABS_DISTANCE, 10 },
  4926. { ABS_PRESSURE, 0 },
  4927. { -1, -1 },
  4928. };
  4929. double dx, dy;
  4930. litest_drain_events(li);
  4931. litest_tablet_proximity_in(dev, 10, 10, axes);
  4932. litest_dispatch(li);
  4933. event = libinput_get_event(li);
  4934. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  4935. dx = libinput_event_tablet_tool_get_dx(tev);
  4936. dy = libinput_event_tablet_tool_get_dy(tev);
  4937. litest_assert(dx == 0.0);
  4938. litest_assert(dy == 0.0);
  4939. libinput_event_destroy(event);
  4940. }
  4941. END_TEST
  4942. START_TEST(relative_delta)
  4943. {
  4944. struct litest_device *dev = litest_current_device();
  4945. struct libinput *li = dev->libinput;
  4946. struct libinput_event *event;
  4947. struct libinput_event_tablet_tool *tev;
  4948. struct axis_replacement axes[] = {
  4949. { ABS_DISTANCE, 10 },
  4950. { ABS_PRESSURE, 0 },
  4951. { -1, -1 },
  4952. };
  4953. double dx, dy;
  4954. litest_tablet_proximity_in(dev, 10, 10, axes);
  4955. litest_drain_events(li);
  4956. /* flush the motion history */
  4957. for (int i = 0; i < 5; i++)
  4958. litest_tablet_motion(dev, 10 + i, 10, axes);
  4959. litest_drain_events(li);
  4960. litest_tablet_motion(dev, 20, 10, axes);
  4961. litest_dispatch(li);
  4962. event = libinput_get_event(li);
  4963. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4964. dx = libinput_event_tablet_tool_get_dx(tev);
  4965. dy = libinput_event_tablet_tool_get_dy(tev);
  4966. litest_assert(dx > 0.0);
  4967. litest_assert(dy == 0.0);
  4968. libinput_event_destroy(event);
  4969. /* flush the motion history */
  4970. for (int i = 0; i < 5; i++)
  4971. litest_tablet_motion(dev, 20 - i, 10, axes);
  4972. litest_drain_events(li);
  4973. litest_tablet_motion(dev, 5, 10, axes);
  4974. litest_dispatch(li);
  4975. event = libinput_get_event(li);
  4976. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4977. dx = libinput_event_tablet_tool_get_dx(tev);
  4978. dy = libinput_event_tablet_tool_get_dy(tev);
  4979. litest_assert(dx < 0.0);
  4980. litest_assert(dy == 0.0);
  4981. libinput_event_destroy(event);
  4982. /* flush the motion history */
  4983. for (int i = 0; i < 5; i++)
  4984. litest_tablet_motion(dev, 5, 10 + i, axes);
  4985. litest_drain_events(li);
  4986. litest_tablet_motion(dev, 5, 20, axes);
  4987. litest_dispatch(li);
  4988. event = libinput_get_event(li);
  4989. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  4990. dx = libinput_event_tablet_tool_get_dx(tev);
  4991. dy = libinput_event_tablet_tool_get_dy(tev);
  4992. litest_assert(dx == 0.0);
  4993. litest_assert(dy > 0.0);
  4994. libinput_event_destroy(event);
  4995. /* flush the motion history */
  4996. for (int i = 0; i < 5; i++)
  4997. litest_tablet_motion(dev, 5, 20 - i, axes);
  4998. litest_drain_events(li);
  4999. litest_tablet_motion(dev, 5, 10, axes);
  5000. litest_dispatch(li);
  5001. event = libinput_get_event(li);
  5002. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5003. dx = libinput_event_tablet_tool_get_dx(tev);
  5004. dy = libinput_event_tablet_tool_get_dy(tev);
  5005. litest_assert(dx == 0.0);
  5006. litest_assert(dy < 0.0);
  5007. libinput_event_destroy(event);
  5008. }
  5009. END_TEST
  5010. START_TEST(relative_no_delta_on_tip)
  5011. {
  5012. struct litest_device *dev = litest_current_device();
  5013. struct libinput *li = dev->libinput;
  5014. struct libinput_event *event;
  5015. struct libinput_event_tablet_tool *tev;
  5016. struct axis_replacement axes[] = {
  5017. { ABS_DISTANCE, 10 },
  5018. { ABS_PRESSURE, 0 },
  5019. { -1, -1 },
  5020. };
  5021. double dx, dy;
  5022. litest_tablet_proximity_in(dev, 10, 10, axes);
  5023. litest_drain_events(li);
  5024. litest_tablet_motion(dev, 20, 10, axes);
  5025. litest_drain_events(li);
  5026. /* tip down */
  5027. litest_axis_set_value(axes, ABS_DISTANCE, 0);
  5028. litest_axis_set_value(axes, ABS_PRESSURE, 30);
  5029. litest_tablet_tip_down(dev, 30, 20, axes);
  5030. litest_dispatch(li);
  5031. event = libinput_get_event(li);
  5032. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  5033. litest_assert(libinput_event_tablet_tool_x_has_changed(tev));
  5034. litest_assert(libinput_event_tablet_tool_y_has_changed(tev));
  5035. dx = libinput_event_tablet_tool_get_dx(tev);
  5036. dy = libinput_event_tablet_tool_get_dy(tev);
  5037. litest_assert(dx == 0.0);
  5038. litest_assert(dy == 0.0);
  5039. libinput_event_destroy(event);
  5040. /* normal motion */
  5041. litest_tablet_motion(dev, 40, 30, axes);
  5042. litest_dispatch(li);
  5043. event = libinput_get_event(li);
  5044. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5045. dx = libinput_event_tablet_tool_get_dx(tev);
  5046. dy = libinput_event_tablet_tool_get_dy(tev);
  5047. litest_assert(dx > 0.0);
  5048. litest_assert(dy > 0.0);
  5049. libinput_event_destroy(event);
  5050. /* tip up */
  5051. litest_axis_set_value(axes, ABS_DISTANCE, 10);
  5052. litest_axis_set_value(axes, ABS_PRESSURE, 0);
  5053. litest_tablet_tip_up(dev, 50, 40, axes);
  5054. litest_dispatch(li);
  5055. event = libinput_get_event(li);
  5056. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
  5057. litest_assert(libinput_event_tablet_tool_x_has_changed(tev));
  5058. litest_assert(libinput_event_tablet_tool_y_has_changed(tev));
  5059. dx = libinput_event_tablet_tool_get_dx(tev);
  5060. dy = libinput_event_tablet_tool_get_dy(tev);
  5061. litest_assert(dx == 0.0);
  5062. litest_assert(dy == 0.0);
  5063. libinput_event_destroy(event);
  5064. }
  5065. END_TEST
  5066. START_TEST(relative_calibration)
  5067. {
  5068. struct litest_device *dev = litest_current_device();
  5069. struct libinput *li = dev->libinput;
  5070. struct libinput_event *event;
  5071. struct libinput_event_tablet_tool *tev;
  5072. struct axis_replacement axes[] = {
  5073. { ABS_DISTANCE, 10 },
  5074. { ABS_PRESSURE, 0 },
  5075. { -1, -1 },
  5076. };
  5077. double dx, dy;
  5078. float calibration[] = { -1, 0, 1, 0, -1, 1 };
  5079. enum libinput_config_status status;
  5080. if (!libinput_device_config_calibration_has_matrix(dev->libinput_device))
  5081. return LITEST_NOT_APPLICABLE;
  5082. status = libinput_device_config_calibration_set_matrix(dev->libinput_device,
  5083. calibration);
  5084. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  5085. litest_tablet_proximity_in(dev, 10, 10, axes);
  5086. litest_drain_events(li);
  5087. litest_tablet_motion(dev, 20, 10, axes);
  5088. litest_dispatch(li);
  5089. event = libinput_get_event(li);
  5090. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5091. dx = libinput_event_tablet_tool_get_dx(tev);
  5092. dy = libinput_event_tablet_tool_get_dy(tev);
  5093. litest_assert(dx < 0.0);
  5094. litest_assert(dy == 0.0);
  5095. libinput_event_destroy(event);
  5096. /* work around axis smoothing */
  5097. litest_tablet_motion(dev, 19, 10, axes);
  5098. litest_tablet_motion(dev, 18, 10, axes);
  5099. litest_tablet_motion(dev, 17, 10, axes);
  5100. litest_drain_events(li);
  5101. litest_tablet_motion(dev, 5, 10, axes);
  5102. litest_dispatch(li);
  5103. event = libinput_get_event(li);
  5104. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5105. dx = libinput_event_tablet_tool_get_dx(tev);
  5106. dy = libinput_event_tablet_tool_get_dy(tev);
  5107. litest_assert(dx > 0.0);
  5108. litest_assert(dy == 0.0);
  5109. libinput_event_destroy(event);
  5110. /* work around axis smoothing */
  5111. litest_tablet_motion(dev, 5, 11, axes);
  5112. litest_tablet_motion(dev, 5, 12, axes);
  5113. litest_tablet_motion(dev, 5, 13, axes);
  5114. litest_drain_events(li);
  5115. litest_tablet_motion(dev, 5, 20, axes);
  5116. litest_dispatch(li);
  5117. event = libinput_get_event(li);
  5118. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5119. dx = libinput_event_tablet_tool_get_dx(tev);
  5120. dy = libinput_event_tablet_tool_get_dy(tev);
  5121. litest_assert(dx == 0.0);
  5122. litest_assert(dy < 0.0);
  5123. libinput_event_destroy(event);
  5124. /* work around axis smoothing */
  5125. litest_tablet_motion(dev, 5, 19, axes);
  5126. litest_tablet_motion(dev, 5, 18, axes);
  5127. litest_tablet_motion(dev, 5, 17, axes);
  5128. litest_drain_events(li);
  5129. litest_tablet_motion(dev, 5, 5, axes);
  5130. litest_dispatch(li);
  5131. event = libinput_get_event(li);
  5132. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5133. dx = libinput_event_tablet_tool_get_dx(tev);
  5134. dy = libinput_event_tablet_tool_get_dy(tev);
  5135. litest_assert(dx == 0.0);
  5136. litest_assert(dy > 0.0);
  5137. libinput_event_destroy(event);
  5138. }
  5139. END_TEST
  5140. static enum litest_device_type
  5141. paired_device(struct litest_device *dev)
  5142. {
  5143. switch (dev->which) {
  5144. case LITEST_WACOM_INTUOS5_PEN:
  5145. return LITEST_WACOM_INTUOS5_FINGER;
  5146. case LITEST_WACOM_INTUOS5_FINGER:
  5147. return LITEST_WACOM_INTUOS5_PEN;
  5148. case LITEST_WACOM_CINTIQ_13HDT_PEN:
  5149. return LITEST_WACOM_CINTIQ_13HDT_FINGER;
  5150. case LITEST_WACOM_CINTIQ_13HDT_FINGER:
  5151. return LITEST_WACOM_CINTIQ_13HDT_PEN;
  5152. default:
  5153. return LITEST_NO_DEVICE;
  5154. }
  5155. }
  5156. static void
  5157. assert_touch_is_arbitrated(struct litest_device *dev, struct litest_device *finger)
  5158. {
  5159. struct libinput *li = dev->libinput;
  5160. bool is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
  5161. struct axis_replacement axes[] = {
  5162. { ABS_TILT_X, 80 }, { ABS_TILT_Y, 80 }, { ABS_DISTANCE, 10 },
  5163. { ABS_PRESSURE, 0 }, { -1, -1 },
  5164. };
  5165. litest_tablet_proximity_in(dev, 10, 10, axes);
  5166. litest_tablet_motion(dev, 10, 10, axes);
  5167. litest_tablet_motion(dev, 20, 40, axes);
  5168. litest_drain_events(li);
  5169. double tx = 20;
  5170. double ty = 40;
  5171. double x = 21;
  5172. double y = 41;
  5173. litest_touch_down(finger, 0, x, y);
  5174. /* We need to intersperce the touch events with tablets so we don't
  5175. trigger the tablet proximity timeout. */
  5176. for (int i = 0; i < 60; i += 5) {
  5177. litest_touch_move(finger, 0, x + i, y + i);
  5178. litest_tablet_motion(dev, tx + 0.1 * i, ty + 0.1 * i, axes);
  5179. }
  5180. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5181. litest_tablet_proximity_out(dev);
  5182. litest_timeout_tablet_proxout(li);
  5183. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  5184. litest_timeout_touch_arbitration(li);
  5185. /* finger still down */
  5186. litest_touch_move_to(finger, 0, 80, 80, 30, 30, 10);
  5187. litest_touch_up(finger, 0);
  5188. litest_assert_empty_queue(li);
  5189. litest_timeout_touch_arbitration(li);
  5190. /* lift finger, expect expect events */
  5191. litest_touch_down(finger, 0, 30, 30);
  5192. litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10);
  5193. litest_touch_up(finger, 0);
  5194. litest_dispatch(li);
  5195. if (is_touchpad)
  5196. litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
  5197. else
  5198. litest_assert_touch_sequence(li);
  5199. }
  5200. START_TEST(touch_arbitration)
  5201. {
  5202. struct litest_device *dev = litest_current_device();
  5203. enum litest_device_type other;
  5204. struct libinput *li = dev->libinput;
  5205. other = paired_device(dev);
  5206. if (other == LITEST_NO_DEVICE)
  5207. return LITEST_NOT_APPLICABLE;
  5208. struct litest_device *finger = litest_add_device(li, other);
  5209. litest_drain_events(li);
  5210. bool is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
  5211. if (is_touchpad)
  5212. litest_disable_hold_gestures(finger->libinput_device);
  5213. assert_touch_is_arbitrated(dev, finger);
  5214. litest_device_destroy(finger);
  5215. }
  5216. END_TEST
  5217. START_TEST(touch_arbitration_outside_rect)
  5218. {
  5219. struct litest_device *dev = litest_current_device();
  5220. enum litest_device_type other;
  5221. struct litest_device *finger;
  5222. struct libinput *li = dev->libinput;
  5223. struct axis_replacement axes[] = {
  5224. { ABS_TILT_X, 80 }, { ABS_TILT_Y, 80 }, { ABS_DISTANCE, 10 },
  5225. { ABS_PRESSURE, 0 }, { -1, -1 },
  5226. };
  5227. double x, y;
  5228. bool is_touchpad;
  5229. bool tilt_left = litest_test_param_get_bool(test_env->params, "tilt-left");
  5230. if (tilt_left) {
  5231. litest_axis_set_value(axes, ABS_TILT_X, 40);
  5232. } else {
  5233. litest_axis_set_value(axes, ABS_TILT_X, 80);
  5234. }
  5235. other = paired_device(dev);
  5236. if (other == LITEST_NO_DEVICE)
  5237. return LITEST_NOT_APPLICABLE;
  5238. finger = litest_add_device(li, other);
  5239. litest_drain_events(li);
  5240. is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
  5241. if (is_touchpad)
  5242. return LITEST_NOT_APPLICABLE;
  5243. x = 50;
  5244. y = 50;
  5245. /* disable prox-out timer quirk */
  5246. litest_tablet_proximity_in(dev, x, y - 1, axes);
  5247. litest_tablet_proximity_out(dev);
  5248. litest_timeout_tablet_proxout(li);
  5249. litest_tablet_proximity_in(dev, x, y - 1, axes);
  5250. litest_drain_events(li);
  5251. /* these are in percent, but the pen/finger have different
  5252. * resolution and the rect works in mm, so the numbers below are
  5253. * hand-picked for the test device */
  5254. litest_tablet_motion(dev, x, y, axes);
  5255. litest_drain_events(li);
  5256. if (tilt_left) {
  5257. /* slightly right of tip */
  5258. litest_touch_sequence(finger, 0, x + 10, y + 2, x - 10, y + 20, 3);
  5259. litest_dispatch(li);
  5260. litest_assert_touch_sequence(li);
  5261. } else {
  5262. /* slightly left of tip */
  5263. litest_touch_sequence(finger, 0, x - 10, y + 2, x - 10, y + 20, 3);
  5264. litest_dispatch(li);
  5265. litest_assert_touch_sequence(li);
  5266. }
  5267. litest_device_destroy(finger);
  5268. }
  5269. END_TEST
  5270. START_TEST(touch_arbitration_remove_after)
  5271. {
  5272. struct litest_device *dev = litest_current_device();
  5273. enum litest_device_type other;
  5274. struct litest_device *finger;
  5275. struct libinput *li = dev->libinput;
  5276. struct axis_replacement axes[] = {
  5277. { ABS_TILT_X, 80 }, { ABS_TILT_Y, 80 }, { ABS_DISTANCE, 10 },
  5278. { ABS_PRESSURE, 0 }, { -1, -1 },
  5279. };
  5280. bool is_touchpad;
  5281. other = paired_device(dev);
  5282. if (other == LITEST_NO_DEVICE)
  5283. return LITEST_NOT_APPLICABLE;
  5284. finger = litest_add_device(li, other);
  5285. litest_drain_events(li);
  5286. is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
  5287. if (is_touchpad)
  5288. return LITEST_NOT_APPLICABLE;
  5289. litest_tablet_proximity_in(dev, 50, 50, axes);
  5290. litest_drain_events(li);
  5291. litest_touch_down(finger, 0, 70, 70);
  5292. litest_drain_events(li);
  5293. litest_tablet_proximity_out(dev);
  5294. litest_timeout_tablet_proxout(li);
  5295. /* Delete the device immediately after the tablet goes out of prox.
  5296. * This merely tests that the arbitration timer gets cleaned up */
  5297. litest_device_destroy(finger);
  5298. }
  5299. END_TEST
  5300. START_TEST(touch_arbitration_stop_touch)
  5301. {
  5302. struct litest_device *dev = litest_current_device();
  5303. enum litest_device_type other;
  5304. struct litest_device *finger;
  5305. struct libinput *li = dev->libinput;
  5306. struct axis_replacement axes[] = {
  5307. { ABS_DISTANCE, 10 },
  5308. { ABS_PRESSURE, 0 },
  5309. { -1, -1 },
  5310. };
  5311. bool is_touchpad;
  5312. other = paired_device(dev);
  5313. if (other == LITEST_NO_DEVICE)
  5314. return LITEST_NOT_APPLICABLE;
  5315. finger = litest_add_device(li, other);
  5316. is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
  5317. if (is_touchpad)
  5318. litest_disable_hold_gestures(finger->libinput_device);
  5319. /* disable prox-out timer quirk */
  5320. litest_tablet_proximity_in(dev, 30, 30, axes);
  5321. litest_tablet_proximity_out(dev);
  5322. litest_timeout_tablet_proxout(li);
  5323. litest_drain_events(li);
  5324. litest_touch_down(finger, 0, 30, 30);
  5325. litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10);
  5326. litest_tablet_proximity_in(dev, 10, 10, axes);
  5327. litest_tablet_motion(dev, 10, 10, axes);
  5328. litest_tablet_motion(dev, 20, 40, axes);
  5329. litest_drain_events(li);
  5330. litest_touch_move_to(finger, 0, 80, 80, 30, 30, 10);
  5331. litest_assert_empty_queue(li);
  5332. /* tablet event so we don't time out for proximity */
  5333. litest_tablet_motion(dev, 30, 40, axes);
  5334. litest_drain_events(li);
  5335. /* start another finger to make sure that one doesn't send events
  5336. either */
  5337. litest_touch_down(finger, 1, 30, 30);
  5338. litest_touch_move_to(finger, 1, 30, 30, 80, 80, 3);
  5339. litest_assert_empty_queue(li);
  5340. litest_tablet_motion(dev, 10, 10, axes);
  5341. litest_tablet_motion(dev, 20, 40, axes);
  5342. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5343. litest_tablet_proximity_out(dev);
  5344. litest_drain_events(li);
  5345. litest_timeout_tablet_proxout(li);
  5346. litest_drain_events(li);
  5347. /* Finger needs to be lifted for events to happen*/
  5348. litest_touch_move_to(finger, 0, 30, 30, 80, 80, 3);
  5349. litest_assert_empty_queue(li);
  5350. litest_touch_move_to(finger, 1, 80, 80, 30, 30, 3);
  5351. litest_assert_empty_queue(li);
  5352. litest_touch_up(finger, 0);
  5353. litest_touch_move_to(finger, 1, 30, 30, 80, 80, 3);
  5354. litest_assert_empty_queue(li);
  5355. litest_touch_up(finger, 1);
  5356. litest_dispatch(li);
  5357. litest_touch_down(finger, 0, 30, 30);
  5358. litest_touch_move_to(finger, 0, 30, 30, 80, 80, 3);
  5359. litest_touch_up(finger, 0);
  5360. litest_dispatch(li);
  5361. if (is_touchpad)
  5362. litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
  5363. else
  5364. litest_assert_touch_sequence(li);
  5365. litest_device_destroy(finger);
  5366. litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
  5367. }
  5368. END_TEST
  5369. START_TEST(touch_arbitration_suspend_touch_device)
  5370. {
  5371. struct litest_device *dev = litest_current_device();
  5372. enum litest_device_type other;
  5373. struct litest_device *tablet;
  5374. struct libinput *li = dev->libinput;
  5375. enum libinput_config_status status;
  5376. struct axis_replacement axes[] = {
  5377. { ABS_DISTANCE, 10 },
  5378. { ABS_PRESSURE, 0 },
  5379. { -1, -1 },
  5380. };
  5381. bool is_touchpad;
  5382. other = paired_device(dev);
  5383. if (other == LITEST_NO_DEVICE)
  5384. return LITEST_NOT_APPLICABLE;
  5385. tablet = litest_add_device(li, other);
  5386. is_touchpad = !libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
  5387. if (is_touchpad)
  5388. litest_disable_hold_gestures(dev->libinput_device);
  5389. /* we can't force a device suspend, but we can at least make sure
  5390. the device doesn't send events */
  5391. status = libinput_device_config_send_events_set_mode(
  5392. dev->libinput_device,
  5393. LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
  5394. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  5395. litest_drain_events(li);
  5396. /* Disable the proximity timer */
  5397. litest_tablet_proximity_in(tablet, 12, 12, axes);
  5398. litest_tablet_proximity_out(tablet);
  5399. litest_timeout_tablet_proxout(li);
  5400. litest_drain_events(li);
  5401. litest_tablet_proximity_in(tablet, 10, 10, axes);
  5402. litest_tablet_motion(tablet, 10, 10, axes);
  5403. litest_tablet_motion(tablet, 20, 40, axes);
  5404. litest_drain_events(li);
  5405. litest_touch_down(dev, 0, 30, 30);
  5406. litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
  5407. litest_touch_up(dev, 0);
  5408. litest_assert_empty_queue(li);
  5409. /* Remove tablet device to unpair, still disabled though */
  5410. litest_device_destroy(tablet);
  5411. litest_assert_tablet_proximity_event(li,
  5412. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  5413. litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
  5414. litest_timeout_touch_arbitration(li);
  5415. litest_touch_down(dev, 0, 30, 30);
  5416. litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
  5417. litest_touch_up(dev, 0);
  5418. litest_assert_empty_queue(li);
  5419. /* Touch device is still disabled */
  5420. litest_touch_down(dev, 0, 30, 30);
  5421. litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
  5422. litest_touch_up(dev, 0);
  5423. litest_assert_empty_queue(li);
  5424. status = libinput_device_config_send_events_set_mode(
  5425. dev->libinput_device,
  5426. LIBINPUT_CONFIG_SEND_EVENTS_ENABLED);
  5427. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  5428. litest_touch_down(dev, 0, 30, 30);
  5429. litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
  5430. litest_touch_up(dev, 0);
  5431. litest_dispatch(li);
  5432. if (is_touchpad)
  5433. litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
  5434. else
  5435. litest_assert_touch_sequence(li);
  5436. }
  5437. END_TEST
  5438. START_TEST(touch_arbitration_remove_touch)
  5439. {
  5440. struct litest_device *dev = litest_current_device();
  5441. enum litest_device_type other;
  5442. struct litest_device *finger;
  5443. struct libinput *li = dev->libinput;
  5444. struct axis_replacement axes[] = {
  5445. { ABS_DISTANCE, 10 },
  5446. { ABS_PRESSURE, 0 },
  5447. { -1, -1 },
  5448. };
  5449. other = paired_device(dev);
  5450. if (other == LITEST_NO_DEVICE)
  5451. return LITEST_NOT_APPLICABLE;
  5452. /* Disable the proximity timer */
  5453. litest_tablet_proximity_in(dev, 12, 12, axes);
  5454. litest_tablet_proximity_out(dev);
  5455. litest_timeout_tablet_proxout(li);
  5456. litest_drain_events(li);
  5457. finger = litest_add_device(li, other);
  5458. litest_touch_down(finger, 0, 30, 30);
  5459. litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10);
  5460. litest_tablet_proximity_in(dev, 10, 10, axes);
  5461. litest_drain_events(li);
  5462. litest_device_destroy(finger);
  5463. litest_dispatch(li);
  5464. litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
  5465. litest_assert_empty_queue(li);
  5466. litest_tablet_motion(dev, 10, 10, axes);
  5467. litest_tablet_motion(dev, 20, 40, axes);
  5468. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5469. }
  5470. END_TEST
  5471. START_TEST(touch_arbitration_remove_tablet)
  5472. {
  5473. struct litest_device *dev = litest_current_device();
  5474. enum litest_device_type other;
  5475. struct litest_device *tablet;
  5476. struct libinput *li = dev->libinput;
  5477. struct axis_replacement axes[] = {
  5478. { ABS_DISTANCE, 10 },
  5479. { ABS_PRESSURE, 0 },
  5480. { -1, -1 },
  5481. };
  5482. bool is_touchpad;
  5483. other = paired_device(dev);
  5484. if (other == LITEST_NO_DEVICE)
  5485. return LITEST_NOT_APPLICABLE;
  5486. tablet = litest_add_device(li, other);
  5487. is_touchpad = !libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
  5488. if (is_touchpad)
  5489. litest_disable_hold_gestures(dev->libinput_device);
  5490. /* Disable the proximity timer */
  5491. litest_tablet_proximity_in(tablet, 12, 12, axes);
  5492. litest_tablet_proximity_out(tablet);
  5493. litest_timeout_tablet_proxout(li);
  5494. litest_drain_events(li);
  5495. litest_dispatch(li);
  5496. litest_tablet_proximity_in(tablet, 10, 10, axes);
  5497. litest_tablet_motion(tablet, 10, 10, axes);
  5498. litest_tablet_motion(tablet, 20, 40, axes);
  5499. litest_drain_events(li);
  5500. litest_touch_down(dev, 0, 30, 30);
  5501. litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
  5502. litest_assert_empty_queue(li);
  5503. litest_device_destroy(tablet);
  5504. litest_assert_tablet_proximity_event(li,
  5505. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  5506. litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
  5507. litest_timeout_touch_arbitration(li);
  5508. /* Touch is still down, don't enable */
  5509. litest_touch_move_to(dev, 0, 80, 80, 30, 30, 10);
  5510. litest_touch_up(dev, 0);
  5511. litest_assert_empty_queue(li);
  5512. litest_touch_down(dev, 0, 30, 30);
  5513. litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
  5514. litest_touch_up(dev, 0);
  5515. litest_dispatch(li);
  5516. if (is_touchpad)
  5517. litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
  5518. else
  5519. litest_assert_touch_sequence(li);
  5520. }
  5521. END_TEST
  5522. START_TEST(touch_arbitration_keep_ignoring)
  5523. {
  5524. struct litest_device *tablet = litest_current_device();
  5525. enum litest_device_type other;
  5526. struct litest_device *finger;
  5527. struct libinput *li = tablet->libinput;
  5528. struct axis_replacement axes[] = {
  5529. { ABS_DISTANCE, 10 },
  5530. { ABS_PRESSURE, 0 },
  5531. { -1, -1 },
  5532. };
  5533. other = paired_device(tablet);
  5534. if (other == LITEST_NO_DEVICE)
  5535. return LITEST_NOT_APPLICABLE;
  5536. /* Disable the proximity timer */
  5537. litest_tablet_proximity_in(tablet, 12, 12, axes);
  5538. litest_tablet_proximity_out(tablet);
  5539. litest_timeout_tablet_proxout(li);
  5540. litest_drain_events(li);
  5541. finger = litest_add_device(li, other);
  5542. litest_tablet_proximity_in(tablet, 10, 10, axes);
  5543. litest_tablet_motion(tablet, 10, 10, axes);
  5544. litest_tablet_motion(tablet, 20, 40, axes);
  5545. litest_touch_down(finger, 0, 30, 30);
  5546. litest_drain_events(li);
  5547. litest_tablet_proximity_out(tablet);
  5548. litest_dispatch(li);
  5549. litest_timeout_tablet_proxout(li);
  5550. litest_drain_events(li);
  5551. /* a touch during pen interaction stays a palm after the pen lifts.
  5552. */
  5553. litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10);
  5554. litest_touch_up(finger, 0);
  5555. litest_dispatch(li);
  5556. litest_assert_empty_queue(li);
  5557. litest_device_destroy(finger);
  5558. }
  5559. END_TEST
  5560. START_TEST(touch_arbitration_late_touch_lift)
  5561. {
  5562. struct litest_device *tablet = litest_current_device();
  5563. enum litest_device_type other;
  5564. struct litest_device *finger;
  5565. struct libinput *li = tablet->libinput;
  5566. struct axis_replacement axes[] = {
  5567. { ABS_DISTANCE, 10 },
  5568. { ABS_PRESSURE, 0 },
  5569. { -1, -1 },
  5570. };
  5571. bool is_touchpad;
  5572. other = paired_device(tablet);
  5573. if (other == LITEST_NO_DEVICE)
  5574. return LITEST_NOT_APPLICABLE;
  5575. /* Disable the proximity timer */
  5576. litest_tablet_proximity_in(tablet, 12, 12, axes);
  5577. litest_tablet_proximity_out(tablet);
  5578. litest_timeout_tablet_proxout(li);
  5579. litest_drain_events(li);
  5580. finger = litest_add_device(li, other);
  5581. is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
  5582. if (is_touchpad) {
  5583. litest_enable_tap(finger->libinput_device);
  5584. litest_disable_hold_gestures(finger->libinput_device);
  5585. }
  5586. litest_tablet_proximity_in(tablet, 10, 10, axes);
  5587. litest_tablet_motion(tablet, 10, 10, axes);
  5588. litest_tablet_motion(tablet, 20, 40, axes);
  5589. litest_drain_events(li);
  5590. litest_tablet_proximity_out(tablet);
  5591. litest_drain_events(li);
  5592. /* with kernel arbitration, a finger + stylus in prox only generates
  5593. * stylus events. When a user lifts the hand with the stylus, the
  5594. * stylus usually goes out of prox while the hand is still touching
  5595. * the surface. This causes a touch down event now that the stylus
  5596. * is out of proximity. A few ms later, the hand really lifts off
  5597. * the surface, causing a touch down and thus a fake tap event.
  5598. */
  5599. litest_touch_down(finger, 0, 30, 30);
  5600. litest_touch_up(finger, 0);
  5601. litest_timeout_tap(li);
  5602. litest_assert_empty_queue(li);
  5603. litest_device_destroy(finger);
  5604. }
  5605. END_TEST
  5606. START_TEST(touch_arbitration_swap_device)
  5607. {
  5608. struct litest_device *tablet = litest_current_device();
  5609. struct libinput *li = tablet->libinput;
  5610. struct axis_replacement axes[] = {
  5611. { ABS_DISTANCE, 10 },
  5612. { ABS_PRESSURE, 0 },
  5613. { -1, -1 },
  5614. };
  5615. enum litest_device_type paired = paired_device(tablet);
  5616. if (paired == LITEST_NO_DEVICE)
  5617. return LITEST_NOT_APPLICABLE;
  5618. /* Disable the proximity timer */
  5619. litest_tablet_proximity_in(tablet, 12, 12, axes);
  5620. litest_tablet_proximity_out(tablet);
  5621. litest_timeout_tablet_proxout(li);
  5622. litest_drain_events(li);
  5623. /* First, add a normal touchscreen */
  5624. struct litest_device *touchscreen =
  5625. litest_add_device(li, LITEST_GENERIC_MULTITOUCH_SCREEN);
  5626. libinput_device_config_gesture_set_hold_enabled(touchscreen->libinput_device,
  5627. LIBINPUT_CONFIG_HOLD_DISABLED);
  5628. litest_drain_events(li);
  5629. assert_touch_is_arbitrated(tablet, touchscreen);
  5630. /* Now add a better device to override the pairing */
  5631. struct litest_device *finger = litest_add_device(li, paired);
  5632. libinput_device_config_gesture_set_hold_enabled(finger->libinput_device,
  5633. LIBINPUT_CONFIG_HOLD_DISABLED);
  5634. litest_drain_events(li);
  5635. assert_touch_is_arbitrated(tablet, finger);
  5636. litest_device_destroy(touchscreen);
  5637. litest_device_destroy(finger);
  5638. }
  5639. END_TEST
  5640. #ifdef HAVE_LIBWACOM
  5641. static void
  5642. verify_left_handed_tablet_motion(struct litest_device *tablet,
  5643. struct libinput *li,
  5644. double x,
  5645. double y,
  5646. bool left_handed)
  5647. {
  5648. struct libinput_event *event;
  5649. struct libinput_event_tablet_tool *t;
  5650. /* proximity in/out must be handled by caller */
  5651. for (int i = 5; i < 25; i += 5) {
  5652. litest_tablet_motion(tablet, x + i, y - i, NULL);
  5653. litest_dispatch(li);
  5654. }
  5655. event = libinput_get_event(li);
  5656. t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5657. x = libinput_event_tablet_tool_get_x(t);
  5658. y = libinput_event_tablet_tool_get_y(t);
  5659. libinput_event_destroy(event);
  5660. event = libinput_get_event(li);
  5661. litest_assert_ptr_notnull(event);
  5662. while (event) {
  5663. double last_x = x, last_y = y;
  5664. t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5665. x = libinput_event_tablet_tool_get_x(t);
  5666. y = libinput_event_tablet_tool_get_y(t);
  5667. if (left_handed) {
  5668. litest_assert_double_lt(x, last_x);
  5669. litest_assert_double_gt(y, last_y);
  5670. } else {
  5671. litest_assert_double_gt(x, last_x);
  5672. litest_assert_double_lt(y, last_y);
  5673. }
  5674. libinput_event_destroy(event);
  5675. event = libinput_get_event(li);
  5676. }
  5677. }
  5678. static void
  5679. verify_left_handed_tablet_sequence(struct litest_device *tablet,
  5680. struct libinput *li,
  5681. bool left_handed)
  5682. {
  5683. double x, y;
  5684. /* verifies a whole sequence, including prox in/out and timeouts */
  5685. x = 60;
  5686. y = 60;
  5687. litest_tablet_proximity_in(tablet, x, y, NULL);
  5688. litest_dispatch(li);
  5689. litest_drain_events(li);
  5690. verify_left_handed_tablet_motion(tablet, li, x, y, left_handed);
  5691. litest_tablet_proximity_out(tablet);
  5692. litest_timeout_tablet_proxout(li);
  5693. litest_drain_events(li);
  5694. }
  5695. static void
  5696. verify_left_handed_touch_motion(struct litest_device *finger,
  5697. struct libinput *li,
  5698. double x,
  5699. double y,
  5700. bool left_handed)
  5701. {
  5702. struct libinput_event *event;
  5703. struct libinput_event_pointer *p;
  5704. /* touch down/up must be handled by caller */
  5705. litest_touch_move_to(finger, 0, x + 1, y - 1, x + 20, y - 20, 10);
  5706. litest_dispatch(li);
  5707. event = libinput_get_event(li);
  5708. litest_assert_notnull(event);
  5709. while (event) {
  5710. p = litest_is_motion_event(event);
  5711. x = libinput_event_pointer_get_dx(p);
  5712. y = libinput_event_pointer_get_dy(p);
  5713. if (left_handed) {
  5714. litest_assert_double_lt(x, 0);
  5715. litest_assert_double_gt(y, 0);
  5716. } else {
  5717. litest_assert_double_gt(x, 0);
  5718. litest_assert_double_lt(y, 0);
  5719. }
  5720. libinput_event_destroy(event);
  5721. event = libinput_get_event(li);
  5722. }
  5723. }
  5724. static void
  5725. verify_left_handed_touch_sequence(struct litest_device *finger,
  5726. struct libinput *li,
  5727. bool left_handed)
  5728. {
  5729. double x, y;
  5730. /* verifies a whole sequence, including prox in/out and timeouts */
  5731. x = 10;
  5732. y = 30;
  5733. litest_touch_down(finger, 0, x, y);
  5734. litest_drain_events(li);
  5735. verify_left_handed_touch_motion(finger, li, x, y, left_handed);
  5736. litest_touch_up(finger, 0);
  5737. litest_dispatch(li);
  5738. }
  5739. #endif
  5740. START_TEST(tablet_rotation_left_handed)
  5741. {
  5742. #ifdef HAVE_LIBWACOM
  5743. struct litest_device *tablet = litest_current_device();
  5744. enum litest_device_type other;
  5745. struct litest_device *finger;
  5746. struct libinput *li = tablet->libinput;
  5747. other = paired_device(tablet);
  5748. if (other == LITEST_NO_DEVICE)
  5749. return LITEST_NOT_APPLICABLE;
  5750. finger = litest_add_device(li, other);
  5751. litest_drain_events(li);
  5752. if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
  5753. goto out;
  5754. bool tablet_from = litest_test_param_get_bool(test_env->params, "tablet_from");
  5755. bool touch_from = litest_test_param_get_bool(test_env->params, "touch_from");
  5756. bool tablet_to = litest_test_param_get_bool(test_env->params, "tablet_to");
  5757. bool touch_to = litest_test_param_get_bool(test_env->params, "touch_to");
  5758. bool enabled_from = tablet_from || touch_from;
  5759. bool enabled_to = tablet_to || touch_to;
  5760. litest_disable_hold_gestures(finger->libinput_device);
  5761. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_from);
  5762. libinput_device_config_left_handed_set(finger->libinput_device, touch_from);
  5763. verify_left_handed_tablet_sequence(tablet, li, enabled_from);
  5764. verify_left_handed_touch_sequence(finger, li, enabled_from);
  5765. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_to);
  5766. libinput_device_config_left_handed_set(finger->libinput_device, touch_to);
  5767. verify_left_handed_tablet_sequence(tablet, li, enabled_to);
  5768. verify_left_handed_touch_sequence(finger, li, enabled_to);
  5769. out:
  5770. litest_device_destroy(finger);
  5771. #endif
  5772. }
  5773. END_TEST
  5774. START_TEST(tablet_rotation_left_handed_configuration)
  5775. {
  5776. #ifdef HAVE_LIBWACOM
  5777. struct litest_device *tablet = litest_current_device();
  5778. enum litest_device_type other;
  5779. struct litest_device *finger;
  5780. struct libinput *li = tablet->libinput;
  5781. bool tablet_enabled, touch_enabled;
  5782. struct libinput_device *tablet_dev, *touch_dev;
  5783. other = paired_device(tablet);
  5784. if (other == LITEST_NO_DEVICE)
  5785. return LITEST_NOT_APPLICABLE;
  5786. finger = litest_add_device(li, other);
  5787. litest_drain_events(li);
  5788. if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
  5789. goto out;
  5790. bool tablet_from = litest_test_param_get_bool(test_env->params, "tablet_from");
  5791. bool touch_from = litest_test_param_get_bool(test_env->params, "touch_from");
  5792. bool tablet_to = litest_test_param_get_bool(test_env->params, "tablet_to");
  5793. bool touch_to = litest_test_param_get_bool(test_env->params, "touch_to");
  5794. tablet_dev = tablet->libinput_device;
  5795. touch_dev = finger->libinput_device;
  5796. /* Make sure that toggling one device doesn't toggle the other one */
  5797. libinput_device_config_left_handed_set(tablet_dev, tablet_from);
  5798. libinput_device_config_left_handed_set(touch_dev, touch_from);
  5799. litest_dispatch(li);
  5800. tablet_enabled = libinput_device_config_left_handed_get(tablet_dev);
  5801. touch_enabled = libinput_device_config_left_handed_get(touch_dev);
  5802. litest_assert_int_eq(tablet_enabled, tablet_from);
  5803. litest_assert_int_eq(touch_enabled, touch_from);
  5804. libinput_device_config_left_handed_set(tablet_dev, tablet_to);
  5805. libinput_device_config_left_handed_set(touch_dev, touch_to);
  5806. litest_dispatch(li);
  5807. tablet_enabled = libinput_device_config_left_handed_get(tablet_dev);
  5808. touch_enabled = libinput_device_config_left_handed_get(touch_dev);
  5809. litest_assert_int_eq(tablet_enabled, tablet_to);
  5810. litest_assert_int_eq(touch_enabled, touch_to);
  5811. out:
  5812. litest_device_destroy(finger);
  5813. #endif
  5814. }
  5815. END_TEST
  5816. START_TEST(tablet_rotation_left_handed_while_in_prox)
  5817. {
  5818. #ifdef HAVE_LIBWACOM
  5819. struct litest_device *tablet = litest_current_device();
  5820. enum litest_device_type other;
  5821. struct litest_device *finger;
  5822. struct libinput *li = tablet->libinput;
  5823. double x, y;
  5824. double tx, ty;
  5825. other = paired_device(tablet);
  5826. if (other == LITEST_NO_DEVICE)
  5827. return LITEST_NOT_APPLICABLE;
  5828. finger = litest_add_device(li, other);
  5829. litest_drain_events(li);
  5830. if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
  5831. goto out;
  5832. bool tablet_from = litest_test_param_get_bool(test_env->params, "tablet_from");
  5833. bool touch_from = litest_test_param_get_bool(test_env->params, "touch_from");
  5834. bool tablet_to = litest_test_param_get_bool(test_env->params, "tablet_to");
  5835. bool touch_to = litest_test_param_get_bool(test_env->params, "touch_to");
  5836. bool enabled_from = tablet_from || touch_from;
  5837. bool enabled_to = tablet_to || touch_to;
  5838. litest_disable_hold_gestures(finger->libinput_device);
  5839. libinput_device_config_left_handed_set(finger->libinput_device, touch_from);
  5840. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_from);
  5841. litest_checkpoint("Moving into proximity");
  5842. tx = 60;
  5843. ty = 60;
  5844. litest_tablet_proximity_in(tablet, tx, ty, NULL);
  5845. litest_dispatch(li);
  5846. litest_drain_events(li);
  5847. litest_checkpoint("Changing tablet to left-handed: %s", truefalse(tablet_to));
  5848. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_to);
  5849. litest_checkpoint("Changing touch to left-handed: %s", truefalse(touch_to));
  5850. libinput_device_config_left_handed_set(finger->libinput_device, touch_to);
  5851. /* not yet neutral, so still whatever the original was */
  5852. litest_checkpoint("Expecting tablet motion with left-handed: %s",
  5853. truefalse(enabled_from));
  5854. verify_left_handed_tablet_motion(tablet, li, tx, ty, enabled_from);
  5855. litest_drain_events(li);
  5856. /* test pointer, should be left-handed already */
  5857. #if 0
  5858. /* Touch arbitration discards events, so we can't check for the
  5859. right behaviour here. */
  5860. verify_left_handed_touch_sequence(finger, li, enabled_to);
  5861. #else
  5862. x = 10;
  5863. y = 30;
  5864. litest_touch_down(finger, 0, x, y);
  5865. /* We need to intersperse the touch events with tablets so we don't
  5866. trigger the tablet proximity timeout. */
  5867. for (int i = 0; i < 10; i++) {
  5868. litest_touch_move(finger, 0, x + i, y - i);
  5869. litest_tablet_motion(tablet, tx + 0.1 * i, ty + 0.1 * i, NULL);
  5870. }
  5871. litest_touch_up(finger, 0);
  5872. litest_dispatch(li);
  5873. /* this will fail once we have location-based touch arbitration on
  5874. * touchpads */
  5875. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  5876. #endif
  5877. litest_checkpoint("Moving out of proximity");
  5878. litest_tablet_proximity_out(tablet);
  5879. litest_timeout_tablet_proxout(li);
  5880. litest_drain_events(li);
  5881. litest_assert_empty_queue(li);
  5882. /* now both should've switched */
  5883. litest_checkpoint("Expecting tablet motion with left-handed: %s",
  5884. truefalse(enabled_to));
  5885. verify_left_handed_tablet_sequence(tablet, li, enabled_to);
  5886. litest_checkpoint("Expecting touch motion with left-handed: %s",
  5887. truefalse(enabled_to));
  5888. verify_left_handed_touch_sequence(finger, li, enabled_to);
  5889. out:
  5890. litest_device_destroy(finger);
  5891. #endif
  5892. }
  5893. END_TEST
  5894. START_TEST(tablet_rotation_left_handed_while_touch_down)
  5895. {
  5896. #ifdef HAVE_LIBWACOM
  5897. struct litest_device *tablet = litest_current_device();
  5898. enum litest_device_type other;
  5899. struct litest_device *finger;
  5900. struct libinput *li = tablet->libinput;
  5901. double x, y;
  5902. other = paired_device(tablet);
  5903. if (other == LITEST_NO_DEVICE)
  5904. return LITEST_NOT_APPLICABLE;
  5905. finger = litest_add_device(li, other);
  5906. litest_drain_events(li);
  5907. if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
  5908. goto out;
  5909. bool tablet_from = litest_test_param_get_bool(test_env->params, "tablet_from");
  5910. bool touch_from = litest_test_param_get_bool(test_env->params, "touch_from");
  5911. bool tablet_to = litest_test_param_get_bool(test_env->params, "tablet_to");
  5912. bool touch_to = litest_test_param_get_bool(test_env->params, "touch_to");
  5913. bool enabled_from = tablet_from || touch_from;
  5914. bool enabled_to = tablet_to || touch_to;
  5915. litest_disable_hold_gestures(finger->libinput_device);
  5916. libinput_device_config_left_handed_set(finger->libinput_device, touch_from);
  5917. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_from);
  5918. /* Touch down when setting to left-handed */
  5919. x = 10;
  5920. y = 30;
  5921. litest_touch_down(finger, 0, x, y);
  5922. litest_dispatch(li);
  5923. litest_drain_events(li);
  5924. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_to);
  5925. libinput_device_config_left_handed_set(finger->libinput_device, touch_to);
  5926. /* not yet neutral, so still whatever the original was */
  5927. verify_left_handed_touch_motion(finger, li, x, y, enabled_from);
  5928. litest_assert_empty_queue(li);
  5929. /* test tablet, should be left-handed already */
  5930. verify_left_handed_tablet_sequence(tablet, li, enabled_to);
  5931. litest_touch_up(finger, 0);
  5932. litest_drain_events(li);
  5933. /* now both should've switched */
  5934. verify_left_handed_tablet_sequence(tablet, li, enabled_to);
  5935. verify_left_handed_touch_sequence(finger, li, enabled_to);
  5936. out:
  5937. litest_device_destroy(finger);
  5938. #endif
  5939. }
  5940. END_TEST
  5941. START_TEST(tablet_rotation_left_handed_add_touchpad)
  5942. {
  5943. #ifdef HAVE_LIBWACOM
  5944. struct litest_device *tablet = litest_current_device();
  5945. enum litest_device_type other;
  5946. struct litest_device *finger;
  5947. struct libinput *li = tablet->libinput;
  5948. other = paired_device(tablet);
  5949. if (other == LITEST_NO_DEVICE)
  5950. return LITEST_NOT_APPLICABLE;
  5951. bool tablet_from = litest_test_param_get_bool(test_env->params, "tablet_from");
  5952. bool touch_from = litest_test_param_get_bool(test_env->params, "touch_from");
  5953. bool tablet_to = litest_test_param_get_bool(test_env->params, "tablet_to");
  5954. bool touch_to = litest_test_param_get_bool(test_env->params, "touch_to");
  5955. bool enabled_from = tablet_from || touch_from;
  5956. bool enabled_to = tablet_to || touch_to;
  5957. /* change left-handed before touchpad appears */
  5958. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_from);
  5959. finger = litest_add_device(li, other);
  5960. litest_drain_events(li);
  5961. if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
  5962. goto out;
  5963. libinput_device_config_left_handed_set(finger->libinput_device, touch_from);
  5964. litest_disable_hold_gestures(finger->libinput_device);
  5965. verify_left_handed_touch_sequence(finger, li, enabled_from);
  5966. verify_left_handed_tablet_sequence(tablet, li, enabled_from);
  5967. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_to);
  5968. libinput_device_config_left_handed_set(finger->libinput_device, touch_to);
  5969. verify_left_handed_touch_sequence(finger, li, enabled_to);
  5970. verify_left_handed_tablet_sequence(tablet, li, enabled_to);
  5971. out:
  5972. litest_device_destroy(finger);
  5973. #endif
  5974. }
  5975. END_TEST
  5976. START_TEST(tablet_rotation_left_handed_add_tablet)
  5977. {
  5978. #ifdef HAVE_LIBWACOM
  5979. struct litest_device *finger = litest_current_device();
  5980. enum litest_device_type other;
  5981. struct litest_device *tablet;
  5982. struct libinput *li = finger->libinput;
  5983. unsigned int transition = _i; /* ranged test */
  5984. bool tablet_from, touch_from, tablet_to, touch_to;
  5985. bool enabled_from, enabled_to;
  5986. if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
  5987. return LITEST_NOT_APPLICABLE;
  5988. other = paired_device(finger);
  5989. if (other == LITEST_NO_DEVICE)
  5990. return LITEST_NOT_APPLICABLE;
  5991. tablet_from = !!(transition & bit(0));
  5992. touch_from = !!(transition & bit(1));
  5993. tablet_to = !!(transition & bit(2));
  5994. touch_to = !!(transition & bit(3));
  5995. enabled_from = tablet_from || touch_from;
  5996. enabled_to = tablet_to || touch_to;
  5997. /* change left-handed before tablet appears */
  5998. libinput_device_config_left_handed_set(finger->libinput_device, touch_from);
  5999. litest_disable_hold_gestures(finger->libinput_device);
  6000. tablet = litest_add_device(li, other);
  6001. litest_drain_events(li);
  6002. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_from);
  6003. verify_left_handed_touch_sequence(finger, li, enabled_from);
  6004. verify_left_handed_tablet_sequence(tablet, li, enabled_from);
  6005. libinput_device_config_left_handed_set(tablet->libinput_device, tablet_to);
  6006. libinput_device_config_left_handed_set(finger->libinput_device, touch_to);
  6007. verify_left_handed_touch_sequence(finger, li, enabled_to);
  6008. verify_left_handed_tablet_sequence(tablet, li, enabled_to);
  6009. litest_device_destroy(tablet);
  6010. #endif
  6011. }
  6012. END_TEST
  6013. START_TEST(huion_static_btn_tool_pen)
  6014. {
  6015. struct litest_device *dev = litest_current_device();
  6016. struct libinput *li = dev->libinput;
  6017. int i;
  6018. bool send_btn_tool =
  6019. litest_test_param_get_bool(test_env->params, "send-btn-tool");
  6020. litest_drain_events(li);
  6021. litest_event(dev, EV_ABS, ABS_X, 20000);
  6022. litest_event(dev, EV_ABS, ABS_Y, 20000);
  6023. litest_event(dev, EV_ABS, ABS_PRESSURE, 100);
  6024. if (send_btn_tool)
  6025. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  6026. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6027. litest_drain_events(li);
  6028. for (i = 0; i < 10; i++) {
  6029. litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
  6030. litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
  6031. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6032. litest_dispatch(li);
  6033. }
  6034. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6035. /* Wait past the timeout to expect a proximity out */
  6036. litest_timeout_tablet_proxout(li);
  6037. litest_assert_tablet_proximity_event(li,
  6038. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  6039. litest_dispatch(li);
  6040. /* New events should fake a proximity in again */
  6041. litest_event(dev, EV_ABS, ABS_X, 20000);
  6042. litest_event(dev, EV_ABS, ABS_Y, 20000);
  6043. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6044. litest_dispatch(li);
  6045. litest_assert_tablet_proximity_event(li,
  6046. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  6047. litest_dispatch(li);
  6048. for (i = 0; i < 10; i++) {
  6049. litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
  6050. litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
  6051. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6052. litest_dispatch(li);
  6053. }
  6054. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6055. litest_timeout_tablet_proxout(li);
  6056. litest_assert_tablet_proximity_event(li,
  6057. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  6058. litest_dispatch(li);
  6059. /* New events, just to ensure cleanup paths are correct */
  6060. litest_event(dev, EV_ABS, ABS_X, 20000);
  6061. litest_event(dev, EV_ABS, ABS_Y, 20000);
  6062. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6063. litest_dispatch(li);
  6064. }
  6065. END_TEST
  6066. START_TEST(huion_static_btn_tool_pen_no_timeout_during_usage)
  6067. {
  6068. struct litest_device *dev = litest_current_device();
  6069. struct libinput *li = dev->libinput;
  6070. int i;
  6071. bool send_btn_tool =
  6072. litest_test_param_get_bool(test_env->params, "send-btn-tool");
  6073. litest_drain_events(li);
  6074. litest_event(dev, EV_ABS, ABS_X, 20000);
  6075. litest_event(dev, EV_ABS, ABS_Y, 20000);
  6076. litest_event(dev, EV_ABS, ABS_PRESSURE, 100);
  6077. if (send_btn_tool)
  6078. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  6079. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6080. litest_drain_events(li);
  6081. /* take longer than the no-activity timeout */
  6082. for (i = 0; i < 50; i++) {
  6083. litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
  6084. litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
  6085. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6086. litest_dispatch(li);
  6087. msleep(5);
  6088. }
  6089. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6090. litest_timeout_tablet_proxout(li);
  6091. litest_dispatch(li);
  6092. litest_assert_tablet_proximity_event(li,
  6093. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  6094. litest_dispatch(li);
  6095. }
  6096. END_TEST
  6097. START_TEST(huion_static_btn_tool_pen_disable_quirk_on_prox_out)
  6098. {
  6099. struct litest_device *dev = litest_current_device();
  6100. struct libinput *li = dev->libinput;
  6101. int i;
  6102. /* test is run twice, once where the real BTN_TOOL_PEN is triggered
  6103. * during proximity out, one where the real BTN_TOOL_PEN is
  6104. * triggered after we already triggered the quirk timeout
  6105. */
  6106. bool with_timeout =
  6107. litest_test_param_get_bool(test_env->params, "btn_tool_pen_timeout");
  6108. litest_drain_events(li);
  6109. litest_event(dev, EV_ABS, ABS_X, 20000);
  6110. litest_event(dev, EV_ABS, ABS_Y, 20000);
  6111. litest_event(dev, EV_ABS, ABS_PRESSURE, 100);
  6112. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
  6113. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6114. litest_drain_events(li);
  6115. for (i = 0; i < 3; i++) {
  6116. litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
  6117. litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
  6118. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6119. litest_dispatch(li);
  6120. }
  6121. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6122. /* Wait past the timeout to expect a proximity out */
  6123. if (with_timeout) {
  6124. litest_timeout_tablet_proxout(li);
  6125. litest_assert_tablet_proximity_event(
  6126. li,
  6127. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  6128. }
  6129. litest_checkpoint("Sending BTN_TOOL_PEN 0 ");
  6130. /* Send a real prox out, expect quirk to be disabled */
  6131. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
  6132. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6133. litest_dispatch(li);
  6134. if (with_timeout) {
  6135. /* we got the proximity event above already */
  6136. litest_assert_empty_queue(li);
  6137. } else {
  6138. litest_assert_tablet_proximity_event(
  6139. li,
  6140. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  6141. }
  6142. litest_tablet_proximity_in(dev, 50, 50, NULL);
  6143. litest_dispatch(li);
  6144. litest_assert_tablet_proximity_event(li,
  6145. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  6146. for (i = 0; i < 3; i++) {
  6147. litest_tablet_motion(dev, 50 + i, 50 + i, NULL);
  6148. litest_dispatch(li);
  6149. }
  6150. litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6151. /* Expect the timeout quirk to be disabled */
  6152. litest_timeout_tablet_proxout(li);
  6153. litest_assert_empty_queue(li);
  6154. litest_with_event_frame(dev) {
  6155. litest_tablet_proximity_out(dev);
  6156. litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
  6157. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6158. }
  6159. litest_dispatch(li);
  6160. litest_assert_tablet_proximity_event(li,
  6161. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  6162. litest_assert_empty_queue(li);
  6163. }
  6164. END_TEST
  6165. START_TEST(tablet_smoothing)
  6166. {
  6167. #ifdef HAVE_LIBWACOM
  6168. struct litest_device *dev = litest_current_device();
  6169. struct libinput *li = dev->libinput;
  6170. double x, y;
  6171. struct point {
  6172. double x, y;
  6173. } coordinates[100] = { 0 };
  6174. size_t npoints = 0;
  6175. size_t idx = 0;
  6176. struct axis_replacement axes[] = {
  6177. { ABS_DISTANCE, 10 },
  6178. { ABS_PRESSURE, 0 },
  6179. { -1, -1 },
  6180. };
  6181. litest_drain_events(li);
  6182. litest_tablet_proximity_in(dev, 10, 10, axes);
  6183. litest_dispatch(li);
  6184. litest_drain_events(li);
  6185. /* Move in a straight line, collect the resulting points */
  6186. for (x = 11, y = 11; x < 50; x++, y++) {
  6187. struct libinput_event *event;
  6188. struct libinput_event_tablet_tool *tev;
  6189. struct point *p = &coordinates[npoints++];
  6190. litest_assert(npoints <= ARRAY_LENGTH(coordinates));
  6191. litest_tablet_motion(dev, x, y, axes);
  6192. litest_dispatch(li);
  6193. event = libinput_get_event(li);
  6194. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6195. p->x = libinput_event_tablet_tool_get_x(tev);
  6196. p->y = libinput_event_tablet_tool_get_y(tev);
  6197. libinput_event_destroy(event);
  6198. }
  6199. litest_tablet_proximity_out(dev);
  6200. litest_timeout_tablet_proxout(li);
  6201. litest_tablet_proximity_in(dev, 10, 10, axes);
  6202. litest_dispatch(li);
  6203. litest_drain_events(li);
  6204. /* Move in a wobbly line, collect every second point */
  6205. for (x = 11, y = 11; x < 50; x++, y++) {
  6206. struct libinput_event *event;
  6207. struct libinput_event_tablet_tool *tev;
  6208. double ex, ey;
  6209. struct point *p = &coordinates[idx++];
  6210. litest_assert(idx <= npoints);
  6211. /* point off position */
  6212. litest_tablet_motion(dev, x - 2, y + 1, axes);
  6213. litest_dispatch(li);
  6214. event = libinput_get_event(li);
  6215. litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6216. libinput_event_destroy(event);
  6217. /* same position as before */
  6218. litest_tablet_motion(dev, x, y, axes);
  6219. litest_dispatch(li);
  6220. event = libinput_get_event(li);
  6221. tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6222. ex = libinput_event_tablet_tool_get_x(tev);
  6223. ey = libinput_event_tablet_tool_get_y(tev);
  6224. litest_assert_double_eq(ex, p->x);
  6225. litest_assert_double_eq(ey, p->y);
  6226. libinput_event_destroy(event);
  6227. }
  6228. #endif
  6229. }
  6230. END_TEST
  6231. START_TEST(tablet_eraser_button_disabled)
  6232. {
  6233. struct litest_device *dev = litest_current_device();
  6234. struct libinput *li = dev->libinput;
  6235. struct axis_replacement axes[] = {
  6236. { ABS_DISTANCE, 10 },
  6237. { ABS_PRESSURE, 0 },
  6238. { -1, -1 },
  6239. };
  6240. struct axis_replacement tip_down_axes[] = {
  6241. { ABS_DISTANCE, 0 },
  6242. { ABS_PRESSURE, 30 },
  6243. { -1, -1 },
  6244. };
  6245. struct libinput_event *ev;
  6246. struct libinput_event_tablet_tool *tev;
  6247. struct libinput_tablet_tool *tool, *pen;
  6248. bool with_tip_down =
  6249. litest_test_param_get_bool(test_env->params, "with-tip-down");
  6250. bool configure_while_out_of_prox =
  6251. litest_test_param_get_bool(test_env->params,
  6252. "configure-while-out-of-prox");
  6253. bool down_when_in_prox =
  6254. litest_test_param_get_bool(test_env->params, "down-when-in-prox");
  6255. bool down_when_out_of_prox =
  6256. litest_test_param_get_bool(test_env->params, "down-when-out-of-prox");
  6257. bool with_motion_events =
  6258. litest_test_param_get_bool(test_env->params, "with-motion-events");
  6259. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
  6260. return LITEST_NOT_APPLICABLE;
  6261. /* Device forces BTN_TOOL_PEN on tip */
  6262. if (with_tip_down && dev->which == LITEST_WACOM_ISDV4_524C_PEN)
  6263. return LITEST_NOT_APPLICABLE;
  6264. litest_log_group("Prox in/out to disable proximity timer") {
  6265. litest_tablet_proximity_in(dev, 25, 25, axes);
  6266. litest_tablet_proximity_out(dev);
  6267. litest_timeout_tablet_proxout(li);
  6268. litest_checkpoint(
  6269. "Eraser prox in/out to force-disable config on broken tablets");
  6270. litest_tablet_set_tool_type(dev, BTN_TOOL_RUBBER);
  6271. litest_tablet_proximity_in(dev, 25, 25, axes);
  6272. litest_tablet_proximity_out(dev);
  6273. litest_timeout_tablet_proxout(li);
  6274. }
  6275. litest_drain_events(li);
  6276. litest_log_group("Proximity in for pen") {
  6277. litest_tablet_set_tool_type(dev, BTN_TOOL_PEN);
  6278. litest_tablet_proximity_in(dev, 20, 20, axes);
  6279. litest_dispatch(li);
  6280. _destroy_(libinput_event) *ev = libinput_get_event(li);
  6281. tev = litest_is_proximity_event(
  6282. ev,
  6283. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  6284. tool = libinput_event_tablet_tool_get_tool(tev);
  6285. litest_assert_enum_eq(libinput_tablet_tool_get_type(tool),
  6286. LIBINPUT_TABLET_TOOL_TYPE_PEN);
  6287. pen = libinput_tablet_tool_ref(tool);
  6288. }
  6289. if (!libinput_tablet_tool_config_eraser_button_get_modes(tool)) {
  6290. libinput_tablet_tool_unref(tool);
  6291. return LITEST_NOT_APPLICABLE;
  6292. }
  6293. unsigned int expected_button = BTN_STYLUS3;
  6294. if (!libinput_tablet_tool_has_button(pen, BTN_STYLUS))
  6295. expected_button = BTN_STYLUS;
  6296. else if (!libinput_tablet_tool_has_button(pen, BTN_STYLUS2))
  6297. expected_button = BTN_STYLUS2;
  6298. else if (!libinput_tablet_tool_has_button(pen, BTN_STYLUS3))
  6299. expected_button = BTN_STYLUS3;
  6300. litest_checkpoint("expected button from now on: %s (%d)",
  6301. libevdev_event_code_get_name(EV_KEY, expected_button),
  6302. expected_button);
  6303. if (!configure_while_out_of_prox) {
  6304. litest_log_group("Configuring eraser button while in of proximity") {
  6305. auto status =
  6306. libinput_tablet_tool_config_eraser_button_set_mode(
  6307. tool,
  6308. LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON);
  6309. if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
  6310. return LITEST_NOT_APPLICABLE;
  6311. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  6312. }
  6313. }
  6314. litest_log_group("Prox out to apply changed settings") {
  6315. litest_tablet_proximity_out(dev);
  6316. litest_timeout_tablet_proxout(li);
  6317. litest_drain_events(li);
  6318. }
  6319. if (configure_while_out_of_prox) {
  6320. litest_log_group("Configuring eraser button while out of proximity") {
  6321. auto status =
  6322. libinput_tablet_tool_config_eraser_button_set_mode(
  6323. tool,
  6324. LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON);
  6325. if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
  6326. return LITEST_NOT_APPLICABLE;
  6327. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  6328. }
  6329. }
  6330. litest_mark_test_start();
  6331. if (down_when_in_prox) {
  6332. litest_log_group("Prox in with eraser, expecting eraser button event") {
  6333. litest_tablet_set_tool_type(dev, BTN_TOOL_RUBBER);
  6334. litest_tablet_proximity_in(dev, 10, 10, axes);
  6335. litest_wait_for_event(li);
  6336. ev = libinput_get_event(li);
  6337. tev = litest_is_proximity_event(
  6338. ev,
  6339. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  6340. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
  6341. pen);
  6342. libinput_event_destroy(ev);
  6343. litest_drain_events_of_type(li,
  6344. LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6345. ev = libinput_get_event(li);
  6346. tev = litest_is_tablet_event(ev,
  6347. LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  6348. litest_assert_enum_eq(
  6349. libinput_event_tablet_tool_get_button_state(tev),
  6350. LIBINPUT_BUTTON_STATE_PRESSED);
  6351. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
  6352. expected_button);
  6353. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
  6354. pen);
  6355. libinput_event_destroy(ev);
  6356. }
  6357. } else {
  6358. litest_tablet_proximity_in(dev, 10, 10, axes);
  6359. }
  6360. litest_drain_events(li);
  6361. if (with_motion_events) {
  6362. for (int i = 0; i < 3; i++) {
  6363. litest_tablet_motion(dev, 11 + i, 11 + i, axes);
  6364. litest_dispatch(li);
  6365. }
  6366. ev = libinput_get_event(li);
  6367. do {
  6368. tev = litest_is_tablet_event(ev,
  6369. LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6370. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
  6371. pen);
  6372. libinput_event_destroy(ev);
  6373. ev = libinput_get_event(li);
  6374. } while (ev);
  6375. }
  6376. if (with_tip_down) {
  6377. litest_tablet_tip_down(dev, 11, 11, tip_down_axes);
  6378. litest_dispatch(li);
  6379. litest_assert_tablet_tip_event(li, LIBINPUT_TABLET_TOOL_TIP_DOWN);
  6380. if (with_motion_events) {
  6381. for (int i = 0; i < 3; i++) {
  6382. litest_tablet_motion(dev,
  6383. 11 + i,
  6384. 11 + i,
  6385. tip_down_axes);
  6386. litest_dispatch(li);
  6387. }
  6388. ev = libinput_get_event(li);
  6389. do {
  6390. tev = litest_is_tablet_event(
  6391. ev,
  6392. LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6393. litest_assert_ptr_eq(
  6394. libinput_event_tablet_tool_get_tool(tev),
  6395. pen);
  6396. libinput_event_destroy(ev);
  6397. ev = libinput_get_event(li);
  6398. } while (ev);
  6399. }
  6400. }
  6401. /* Make sure the button still works as-is */
  6402. if (libinput_tablet_tool_has_button(pen, BTN_STYLUS)) {
  6403. litest_log_group("Testing BTN_STYLUS") {
  6404. litest_event(dev, EV_KEY, BTN_STYLUS, 1);
  6405. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6406. litest_dispatch(li);
  6407. litest_event(dev, EV_KEY, BTN_STYLUS, 0);
  6408. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6409. litest_dispatch(li);
  6410. litest_assert_tablet_button_event(
  6411. li,
  6412. BTN_STYLUS,
  6413. LIBINPUT_BUTTON_STATE_PRESSED);
  6414. litest_assert_tablet_button_event(
  6415. li,
  6416. BTN_STYLUS,
  6417. LIBINPUT_BUTTON_STATE_RELEASED);
  6418. }
  6419. }
  6420. litest_dispatch(li);
  6421. if (!down_when_in_prox) {
  6422. litest_log_group("Prox out for the pen ...") {
  6423. litest_with_event_frame(dev) {
  6424. litest_tablet_set_tool_type(dev, BTN_TOOL_PEN);
  6425. if (with_tip_down)
  6426. litest_tablet_tip_up(dev, 11, 11, axes);
  6427. litest_tablet_proximity_out(dev);
  6428. }
  6429. litest_dispatch(li);
  6430. }
  6431. litest_log_group("...and prox in for the eraser") {
  6432. litest_with_event_frame(dev) {
  6433. litest_tablet_set_tool_type(dev, BTN_TOOL_RUBBER);
  6434. if (with_tip_down) {
  6435. litest_tablet_tip_down(dev,
  6436. 12,
  6437. 12,
  6438. tip_down_axes);
  6439. litest_tablet_proximity_in(dev,
  6440. 12,
  6441. 12,
  6442. tip_down_axes);
  6443. } else {
  6444. litest_tablet_proximity_in(dev, 12, 12, axes);
  6445. }
  6446. }
  6447. litest_dispatch(li);
  6448. }
  6449. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6450. litest_log_group("Expect button event") {
  6451. ev = libinput_get_event(li);
  6452. tev = litest_is_tablet_event(ev,
  6453. LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  6454. litest_assert_enum_eq(
  6455. libinput_event_tablet_tool_get_button_state(tev),
  6456. LIBINPUT_BUTTON_STATE_PRESSED);
  6457. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
  6458. expected_button);
  6459. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
  6460. pen);
  6461. libinput_event_destroy(ev);
  6462. }
  6463. }
  6464. if (!down_when_out_of_prox) {
  6465. litest_log_group("Prox out for the eraser...") {
  6466. litest_with_event_frame(dev) {
  6467. if (with_tip_down)
  6468. litest_tablet_tip_up(dev, 11, 11, axes);
  6469. litest_tablet_proximity_out(dev);
  6470. }
  6471. litest_dispatch(li);
  6472. }
  6473. litest_log_group("...and prox in for the pen") {
  6474. litest_with_event_frame(dev) {
  6475. litest_tablet_set_tool_type(dev, BTN_TOOL_PEN);
  6476. if (with_tip_down) {
  6477. litest_tablet_tip_down(dev,
  6478. 12,
  6479. 12,
  6480. tip_down_axes);
  6481. litest_tablet_proximity_in(dev,
  6482. 12,
  6483. 12,
  6484. tip_down_axes);
  6485. } else {
  6486. litest_tablet_proximity_in(dev, 12, 12, axes);
  6487. }
  6488. }
  6489. litest_dispatch(li);
  6490. }
  6491. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6492. litest_log_group("Expect button event") {
  6493. ev = libinput_get_event(li);
  6494. tev = litest_is_tablet_event(ev,
  6495. LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  6496. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
  6497. expected_button);
  6498. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
  6499. pen);
  6500. libinput_event_destroy(ev);
  6501. }
  6502. }
  6503. litest_log_group("Real prox out for the %s",
  6504. down_when_out_of_prox ? "eraser" : "pen") {
  6505. litest_with_event_frame(dev) {
  6506. if (with_tip_down)
  6507. litest_tablet_tip_up(dev, 12, 12, axes);
  6508. litest_tablet_proximity_out(dev);
  6509. }
  6510. litest_dispatch(li);
  6511. litest_timeout_tablet_proxout(li);
  6512. }
  6513. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6514. if (down_when_out_of_prox) {
  6515. litest_log_group("Expect button release") {
  6516. ev = libinput_get_event(li);
  6517. tev = litest_is_tablet_event(ev,
  6518. LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  6519. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
  6520. expected_button);
  6521. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
  6522. pen);
  6523. libinput_event_destroy(ev);
  6524. }
  6525. }
  6526. if (with_tip_down)
  6527. litest_assert_tablet_tip_event(li, LIBINPUT_TABLET_TOOL_TIP_UP);
  6528. litest_log_group("Expect final prox out for the pen") {
  6529. ev = libinput_get_event(li);
  6530. tev = litest_is_proximity_event(
  6531. ev,
  6532. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
  6533. tool = libinput_event_tablet_tool_get_tool(tev);
  6534. litest_assert_ptr_eq(pen, tool);
  6535. libinput_event_destroy(ev);
  6536. }
  6537. libinput_tablet_tool_unref(pen);
  6538. }
  6539. END_TEST
  6540. START_TEST(tablet_eraser_button_different_buttons)
  6541. {
  6542. struct litest_device *dev = litest_current_device();
  6543. struct libinput *li = dev->libinput;
  6544. struct axis_replacement axes[] = {
  6545. { ABS_DISTANCE, 10 },
  6546. { ABS_PRESSURE, 0 },
  6547. { -1, -1 },
  6548. };
  6549. _unref_(libinput_tablet_tool) *pen = NULL;
  6550. uint32_t eraser_button_mapping =
  6551. litest_test_param_get_i32(test_env->params, "eraser-button-mapping");
  6552. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
  6553. return LITEST_NOT_APPLICABLE;
  6554. litest_log_group("Prox in/out to disable proximity timer") {
  6555. litest_tablet_proximity_in(dev, 25, 25, axes);
  6556. litest_tablet_proximity_out(dev);
  6557. litest_timeout_tablet_proxout(li);
  6558. litest_checkpoint(
  6559. "Eraser prox in/out to force-disable config on broken tablets");
  6560. litest_tablet_set_tool_type(dev, BTN_TOOL_RUBBER);
  6561. litest_tablet_proximity_in(dev, 25, 25, axes);
  6562. litest_tablet_proximity_out(dev);
  6563. litest_timeout_tablet_proxout(li);
  6564. }
  6565. litest_drain_events(li);
  6566. litest_log_group("Proximity in for pen") {
  6567. litest_tablet_set_tool_type(dev, BTN_TOOL_PEN);
  6568. litest_tablet_proximity_in(dev, 20, 20, axes);
  6569. litest_dispatch(li);
  6570. _destroy_(libinput_event) *ev = libinput_get_event(li);
  6571. auto tev = litest_is_proximity_event(
  6572. ev,
  6573. LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  6574. pen = libinput_event_tablet_tool_get_tool(tev);
  6575. litest_assert_enum_eq(libinput_tablet_tool_get_type(pen),
  6576. LIBINPUT_TABLET_TOOL_TYPE_PEN);
  6577. pen = libinput_tablet_tool_ref(pen);
  6578. }
  6579. if (!libinput_tablet_tool_config_eraser_button_get_modes(pen))
  6580. return LITEST_NOT_APPLICABLE;
  6581. auto status = libinput_tablet_tool_config_eraser_button_set_mode(
  6582. pen,
  6583. LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON);
  6584. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  6585. status = libinput_tablet_tool_config_eraser_button_set_button(
  6586. pen,
  6587. eraser_button_mapping);
  6588. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  6589. litest_log_group("Prox out to apply changed settings") {
  6590. litest_tablet_proximity_out(dev);
  6591. litest_timeout_tablet_proxout(li);
  6592. litest_drain_events(li);
  6593. }
  6594. litest_mark_test_start();
  6595. litest_tablet_proximity_in(dev, 10, 10, axes);
  6596. litest_drain_events(li);
  6597. /* Make sure the button still works as-is */
  6598. if (libinput_tablet_tool_has_button(pen, eraser_button_mapping)) {
  6599. litest_log_group("Testing button on pen") {
  6600. litest_event(dev, EV_KEY, eraser_button_mapping, 1);
  6601. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6602. litest_dispatch(li);
  6603. litest_event(dev, EV_KEY, eraser_button_mapping, 0);
  6604. litest_event(dev, EV_SYN, SYN_REPORT, 0);
  6605. litest_dispatch(li);
  6606. litest_assert_tablet_button_event(
  6607. li,
  6608. eraser_button_mapping,
  6609. LIBINPUT_BUTTON_STATE_PRESSED);
  6610. litest_assert_tablet_button_event(
  6611. li,
  6612. eraser_button_mapping,
  6613. LIBINPUT_BUTTON_STATE_RELEASED);
  6614. }
  6615. }
  6616. litest_dispatch(li);
  6617. litest_log_group("Prox out for the pen ...") {
  6618. litest_with_event_frame(dev) {
  6619. litest_tablet_set_tool_type(dev, BTN_TOOL_PEN);
  6620. litest_tablet_proximity_out(dev);
  6621. }
  6622. litest_dispatch(li);
  6623. }
  6624. litest_log_group("...and prox in for the eraser") {
  6625. litest_with_event_frame(dev) {
  6626. litest_tablet_set_tool_type(dev, BTN_TOOL_RUBBER);
  6627. litest_tablet_proximity_in(dev, 12, 12, axes);
  6628. }
  6629. litest_dispatch(li);
  6630. }
  6631. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6632. litest_log_group("Expect button event") {
  6633. _destroy_(libinput_event) *ev = libinput_get_event(li);
  6634. auto tev =
  6635. litest_is_tablet_event(ev, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  6636. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tev),
  6637. LIBINPUT_BUTTON_STATE_PRESSED);
  6638. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
  6639. eraser_button_mapping);
  6640. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), pen);
  6641. }
  6642. litest_log_group("Prox out for the eraser...") {
  6643. litest_with_event_frame(dev) {
  6644. litest_tablet_proximity_out(dev);
  6645. }
  6646. litest_dispatch(li);
  6647. }
  6648. litest_log_group("...and prox in for the pen") {
  6649. litest_with_event_frame(dev) {
  6650. litest_tablet_set_tool_type(dev, BTN_TOOL_PEN);
  6651. litest_tablet_proximity_in(dev, 12, 12, axes);
  6652. }
  6653. litest_dispatch(li);
  6654. }
  6655. litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
  6656. litest_log_group("Expect button event") {
  6657. _destroy_(libinput_event) *ev = libinput_get_event(li);
  6658. auto tev =
  6659. litest_is_tablet_event(ev, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
  6660. litest_assert_enum_eq(libinput_event_tablet_tool_get_button_state(tev),
  6661. LIBINPUT_BUTTON_STATE_RELEASED);
  6662. litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
  6663. eraser_button_mapping);
  6664. litest_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), pen);
  6665. }
  6666. }
  6667. END_TEST
  6668. START_TEST(tablet_eraser_button_invalid_buttons)
  6669. {
  6670. struct litest_device *dev = litest_current_device();
  6671. struct libinput *li = dev->libinput;
  6672. struct axis_replacement axes[] = {
  6673. { ABS_DISTANCE, 10 },
  6674. { ABS_PRESSURE, 0 },
  6675. { -1, -1 },
  6676. };
  6677. uint32_t eraser_button_mapping =
  6678. litest_test_param_get_i32(test_env->params, "eraser-button-mapping");
  6679. if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
  6680. return LITEST_NOT_APPLICABLE;
  6681. litest_drain_events(li);
  6682. litest_tablet_proximity_in(dev, 20, 20, axes);
  6683. litest_dispatch(li);
  6684. _destroy_(libinput_event) *ev = libinput_get_event(li);
  6685. auto tev =
  6686. litest_is_proximity_event(ev, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
  6687. auto tool = libinput_event_tablet_tool_get_tool(tev);
  6688. if (!libinput_tablet_tool_config_eraser_button_get_modes(tool))
  6689. return LITEST_NOT_APPLICABLE;
  6690. auto status = libinput_tablet_tool_config_eraser_button_set_button(
  6691. tool,
  6692. eraser_button_mapping);
  6693. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
  6694. }
  6695. END_TEST
  6696. START_TEST(tablet_eraser_button_config_after_device_removal)
  6697. {
  6698. _litest_context_destroy_ struct libinput *li = litest_create_context();
  6699. struct litest_device *tablet = litest_add_device(li, LITEST_ELAN_TABLET);
  6700. struct axis_replacement axes[] = {
  6701. { ABS_DISTANCE, 10 },
  6702. { ABS_PRESSURE, 0 },
  6703. { -1, -1 },
  6704. };
  6705. litest_drain_events(li);
  6706. litest_tablet_set_tool_type(tablet, BTN_TOOL_RUBBER);
  6707. litest_tablet_proximity_in(tablet, 10, 10, axes);
  6708. litest_dispatch(li);
  6709. auto event = libinput_get_event(li);
  6710. auto tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
  6711. auto tool = libinput_event_tablet_tool_get_tool(tev);
  6712. libinput_tablet_tool_ref(tool);
  6713. libinput_event_destroy(event);
  6714. litest_device_destroy(tablet);
  6715. litest_drain_events(li);
  6716. /* Tool isn't associated with a device but config should take effect anyway */
  6717. auto status = libinput_tablet_tool_config_eraser_button_set_mode(
  6718. tool,
  6719. LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON);
  6720. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  6721. status =
  6722. libinput_tablet_tool_config_eraser_button_set_button(tool, BTN_STYLUS2);
  6723. litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
  6724. litest_assert_enum_eq(libinput_tablet_tool_config_eraser_button_get_mode(tool),
  6725. LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON);
  6726. litest_assert_int_eq(libinput_tablet_tool_config_eraser_button_get_button(tool),
  6727. (unsigned)BTN_STYLUS2);
  6728. litest_drain_events(li);
  6729. libinput_tablet_tool_unref(tool);
  6730. }
  6731. END_TEST
  6732. TEST_COLLECTION(tablet)
  6733. {
  6734. /* clang-format off */
  6735. litest_add(tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
  6736. litest_add(tool_user_data, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
  6737. litest_add(tool_capability, LITEST_TABLET, LITEST_ANY);
  6738. litest_add_no_device(tool_capabilities);
  6739. litest_add(tool_type, LITEST_TABLET, LITEST_FORCED_PROXOUT);
  6740. litest_add(tool_in_prox_before_start, LITEST_TABLET, LITEST_TOTEM);
  6741. litest_add(tool_direct_switch_skip_tool_update, LITEST_TABLET, LITEST_ANY);
  6742. litest_add(tool_direct_switch_with_forced_proxout, LITEST_TABLET, LITEST_ANY);
  6743. /* Tablets hold back the proximity until the first event from the
  6744. * kernel, the totem sends it immediately */
  6745. litest_add(tool_in_prox_before_start, LITEST_TABLET, LITEST_TOTEM);
  6746. litest_add(tool_unique, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
  6747. litest_add(tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
  6748. litest_add(tool_id, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
  6749. litest_with_parameters(params, "tool_id", 'I', 3,
  6750. litest_named_i32(0x823, "GripPen"),
  6751. litest_named_i32(0x4802, "ClassicPen"),
  6752. litest_named_i32(0x100902, "AirbrushPen")) {
  6753. litest_add_parametrized_for_device(tool_name, LITEST_WACOM_CINTIQ_PRO16_PEN, params);
  6754. }
  6755. litest_add_for_device(tool_no_name, LITEST_HUION_TABLET);
  6756. litest_add(serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
  6757. litest_add(invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
  6758. litest_add_no_device(tools_with_serials);
  6759. litest_add_no_device(tools_without_serials);
  6760. litest_add_for_device(tool_delayed_serial, LITEST_WACOM_HID4800_PEN);
  6761. litest_add_no_device(proximity_out_on_delete);
  6762. litest_add(button_down_up, LITEST_TABLET, LITEST_ANY);
  6763. litest_add(button_seat_count, LITEST_TABLET, LITEST_ANY);
  6764. litest_add_no_device(button_up_on_delete);
  6765. litest_add(motion, LITEST_TABLET, LITEST_ANY);
  6766. litest_add(motion_event_state, LITEST_TABLET, LITEST_ANY);
  6767. litest_add_for_device(motion_outside_bounds, LITEST_WACOM_CINTIQ_24HD_PEN);
  6768. litest_add(tilt_available, LITEST_TABLET|LITEST_TILT, LITEST_ANY);
  6769. litest_add(tilt_not_available, LITEST_TABLET, LITEST_TILT);
  6770. litest_add(tilt_x, LITEST_TABLET|LITEST_TILT, LITEST_ANY);
  6771. litest_add(tilt_y, LITEST_TABLET|LITEST_TILT, LITEST_ANY);
  6772. litest_with_parameters(params, "tilt", 'I', 3, litest_named_i32(TILT_MINIMUM, "minimum"),
  6773. litest_named_i32(TILT_CENTER, "center"),
  6774. litest_named_i32(TILT_MAXIMUM, "maximum")) {
  6775. litest_add_parametrized(tilt_fixed_points, LITEST_TABLET|LITEST_TILT, LITEST_ANY, params);
  6776. }
  6777. litest_add(pad_buttons_ignored, LITEST_TABLET, LITEST_TOTEM);
  6778. litest_add_for_device(stylus_buttons, LITEST_WACOM_CINTIQ_PRO16_PEN);
  6779. litest_add(mouse_tool, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY);
  6780. litest_add(mouse_buttons, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY);
  6781. litest_add(mouse_rotation, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY);
  6782. litest_add(mouse_wheel, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_WHEEL);
  6783. litest_add(airbrush_tool, LITEST_TABLET, LITEST_ANY);
  6784. litest_add(airbrush_slider, LITEST_TABLET, LITEST_ANY);
  6785. litest_add(artpen_tool, LITEST_TABLET, LITEST_ANY);
  6786. litest_add(artpen_rotation, LITEST_TABLET, LITEST_ANY);
  6787. litest_add(tablet_time_usec, LITEST_TABLET, LITEST_ANY);
  6788. litest_add(tablet_pressure_distance_exclusive, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
  6789. /* The totem doesn't need calibration */
  6790. litest_add(tablet_calibration_has_matrix, LITEST_TABLET, LITEST_TOTEM|LITEST_PRECALIBRATED);
  6791. litest_add(tablet_calibration_set_matrix, LITEST_TABLET, LITEST_TOTEM|LITEST_PRECALIBRATED);
  6792. litest_add(tablet_calibration_set_matrix_delta, LITEST_TABLET, LITEST_TOTEM|LITEST_PRECALIBRATED);
  6793. litest_add(tablet_area_has_rectangle, LITEST_TABLET, LITEST_ANY);
  6794. litest_add(tablet_area_set_rectangle_invalid, LITEST_TABLET, LITEST_ANY);
  6795. litest_with_parameters(params,
  6796. "axis", 's', 2, "vertical", "horizontal",
  6797. "direction", 's', 2, "down", "up") {
  6798. litest_add_parametrized(tablet_area_set_rectangle, LITEST_TABLET, LITEST_ANY, params);
  6799. }
  6800. litest_add(tablet_area_set_rectangle_move_outside, LITEST_TABLET, LITEST_ANY);
  6801. litest_add(tablet_area_set_rectangle_move_outside_to_inside, LITEST_TABLET, LITEST_ANY);
  6802. litest_add(tablet_area_set_rectangle_move_in_margin, LITEST_TABLET, LITEST_ANY);
  6803. litest_add(tablet_area_set_rectangle_while_outside, LITEST_TABLET, LITEST_ANY);
  6804. litest_add(tablet_pressure_min_max, LITEST_TABLET, LITEST_ANY);
  6805. /* Tests for pressure offset with distance */
  6806. litest_add_for_device(tablet_pressure_range, LITEST_WACOM_INTUOS5_PEN);
  6807. litest_add_for_device(tablet_pressure_offset_set, LITEST_WACOM_INTUOS5_PEN);
  6808. litest_add_for_device(tablet_pressure_offset_decrease, LITEST_WACOM_INTUOS5_PEN);
  6809. litest_add_for_device(tablet_pressure_offset_increase, LITEST_WACOM_INTUOS5_PEN);
  6810. litest_add_for_device(tablet_pressure_offset_exceed_threshold, LITEST_WACOM_INTUOS5_PEN);
  6811. litest_add_for_device(tablet_pressure_offset_none_for_zero_distance, LITEST_WACOM_INTUOS5_PEN);
  6812. litest_add_for_device(tablet_pressure_offset_none_for_small_distance, LITEST_WACOM_INTUOS5_PEN);
  6813. /* Tests for pressure offset without distance */
  6814. litest_add_for_device(tablet_pressure_range, LITEST_WACOM_HID4800_PEN);
  6815. litest_add_for_device(tablet_pressure_offset_set, LITEST_WACOM_HID4800_PEN);
  6816. litest_add_for_device(tablet_pressure_offset_decrease, LITEST_WACOM_HID4800_PEN);
  6817. litest_add_for_device(tablet_pressure_offset_increase, LITEST_WACOM_HID4800_PEN);
  6818. litest_add_for_device(tablet_pressure_offset_exceed_threshold, LITEST_WACOM_HID4800_PEN);
  6819. litest_with_parameters(params, "8k-to-1k", 'b', "with-range", 'b', "with-second-range", 'b')
  6820. litest_add_parametrized_for_device(tablet_pressure_across_multiple_tablets, LITEST_WACOM_CINTIQ_12WX_PEN, params);
  6821. litest_add_no_device(tablet_pressure_after_unplug);
  6822. litest_add(tablet_pressure_config, LITEST_TABLET, LITEST_TOTEM);
  6823. litest_add(tablet_pressure_config_set_minimum, LITEST_TABLET, LITEST_TOTEM);
  6824. litest_add(tablet_pressure_config_set_maximum, LITEST_TABLET, LITEST_TOTEM);
  6825. litest_add(tablet_pressure_config_set_range, LITEST_TABLET, LITEST_TOTEM);
  6826. litest_add(tablet_pressure_config_resets_offset, LITEST_TABLET, LITEST_TOTEM);
  6827. litest_add_for_device(tablet_pressure_config_01_does_not_reset_offset, LITEST_WACOM_HID4800_PEN);
  6828. litest_add_for_device(tablet_distance_range, LITEST_WACOM_INTUOS5_PEN);
  6829. litest_add(relative_no_profile, LITEST_TABLET, LITEST_ANY);
  6830. litest_add(relative_no_delta_prox_in, LITEST_TABLET, LITEST_ANY);
  6831. litest_add(relative_delta, LITEST_TABLET, LITEST_ANY);
  6832. litest_add(relative_no_delta_on_tip, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6833. litest_add(relative_calibration, LITEST_TABLET, LITEST_PRECALIBRATED);
  6834. litest_add(touch_arbitration, LITEST_TABLET, LITEST_ANY);
  6835. litest_add(touch_arbitration_stop_touch, LITEST_TABLET, LITEST_ANY);
  6836. litest_add(touch_arbitration_suspend_touch_device, LITEST_TOUCH, LITEST_ANY);
  6837. litest_add(touch_arbitration_remove_touch, LITEST_TABLET, LITEST_ANY);
  6838. litest_add(touch_arbitration_remove_tablet, LITEST_TOUCH, LITEST_ANY);
  6839. litest_add(touch_arbitration_keep_ignoring, LITEST_TABLET, LITEST_ANY);
  6840. litest_add(touch_arbitration_late_touch_lift, LITEST_TABLET, LITEST_ANY);
  6841. litest_with_parameters(params, "tilt-left", 'b') {
  6842. litest_add_parametrized(touch_arbitration_outside_rect, LITEST_TABLET | LITEST_DIRECT, LITEST_ANY, params);
  6843. }
  6844. litest_add(touch_arbitration_remove_after, LITEST_TABLET | LITEST_DIRECT, LITEST_ANY);
  6845. litest_add(touch_arbitration_swap_device, LITEST_TABLET, LITEST_ANY);
  6846. litest_with_parameters(params, "send-btn-tool", 'b') {
  6847. litest_add_parametrized_for_device(huion_static_btn_tool_pen, LITEST_HUION_TABLET, params);
  6848. litest_add_parametrized_for_device(huion_static_btn_tool_pen_no_timeout_during_usage, LITEST_HUION_TABLET, params);
  6849. }
  6850. litest_with_parameters(params, "btn_tool_pen_timeout", 'b') {
  6851. litest_add_parametrized_for_device(huion_static_btn_tool_pen_disable_quirk_on_prox_out, LITEST_HUION_TABLET, params);
  6852. }
  6853. litest_add_for_device(tablet_smoothing, LITEST_WACOM_HID4800_PEN);
  6854. /* clang-format on */
  6855. }
  6856. TEST_COLLECTION(tablet_left_handed)
  6857. {
  6858. /* clang-format off */
  6859. litest_add_for_device(left_handed, LITEST_WACOM_INTUOS5_PEN);
  6860. litest_add_for_device(left_handed_tilt, LITEST_WACOM_INTUOS5_PEN);
  6861. litest_add_for_device(left_handed_mouse_rotation, LITEST_WACOM_INTUOS5_PEN);
  6862. litest_add_for_device(left_handed_artpen_rotation, LITEST_WACOM_INTUOS5_PEN);
  6863. litest_add_for_device(no_left_handed, LITEST_WACOM_CINTIQ_12WX_PEN);
  6864. litest_with_parameters(params,
  6865. "tablet_from", 'b',
  6866. "touch_from", 'b',
  6867. "tablet_to", 'b',
  6868. "touch_to", 'b') {
  6869. litest_add_parametrized(tablet_rotation_left_handed, LITEST_TABLET, LITEST_ANY, params);
  6870. litest_add_parametrized(tablet_rotation_left_handed_configuration, LITEST_TABLET, LITEST_ANY, params);
  6871. litest_add_parametrized(tablet_rotation_left_handed_while_in_prox, LITEST_TABLET, LITEST_ANY, params);
  6872. litest_add_parametrized(tablet_rotation_left_handed_while_touch_down, LITEST_TABLET, LITEST_ANY, params);
  6873. litest_add_parametrized(tablet_rotation_left_handed_add_touchpad, LITEST_TABLET, LITEST_ANY, params);
  6874. litest_add_parametrized(tablet_rotation_left_handed_add_tablet, LITEST_TOUCHPAD, LITEST_ANY, params);
  6875. }
  6876. /* clang-format on */
  6877. }
  6878. TEST_COLLECTION(tablet_eraser)
  6879. {
  6880. /* clang-format off */
  6881. litest_with_parameters(params,
  6882. "with-tip-down", 'b',
  6883. "configure-while-out-of-prox", 'b',
  6884. "down-when-in-prox", 'b',
  6885. "down-when-out-of-prox", 'b',
  6886. "with-motion-events", 'b') {
  6887. litest_add_parametrized(tablet_eraser_button_disabled, LITEST_TABLET, LITEST_TOTEM|LITEST_FORCED_PROXOUT, params);
  6888. }
  6889. litest_with_parameters(params,
  6890. "eraser-button-mapping", 'I', 4,
  6891. litest_named_i32(BTN_STYLUS),
  6892. litest_named_i32(BTN_STYLUS3),
  6893. litest_named_i32(BTN_LEFT),
  6894. litest_named_i32(BTN_BACK)){
  6895. litest_add_parametrized(tablet_eraser_button_different_buttons, LITEST_TABLET, LITEST_TOTEM|LITEST_FORCED_PROXOUT, params);
  6896. }
  6897. litest_with_parameters(params,
  6898. "eraser-button-mapping", 'I', 3,
  6899. litest_named_i32(BTN_TOUCH),
  6900. litest_named_i32(BTN_TOOL_FINGER),
  6901. litest_named_i32(KEY_A)) {
  6902. litest_add_parametrized(tablet_eraser_button_invalid_buttons, LITEST_TABLET, LITEST_TOTEM|LITEST_FORCED_PROXOUT, params);
  6903. }
  6904. litest_add_no_device(tablet_eraser_button_config_after_device_removal);
  6905. /* clang-format on */
  6906. }
  6907. TEST_COLLECTION(tablet_proximity)
  6908. {
  6909. /* clang-format off */
  6910. litest_add(proximity_out_clear_buttons, LITEST_TABLET, LITEST_FORCED_PROXOUT);
  6911. litest_add(proximity_in_out, LITEST_TABLET, LITEST_ANY);
  6912. litest_add(proximity_in_button_down, LITEST_TABLET, LITEST_ANY);
  6913. litest_add(proximity_out_button_up, LITEST_TABLET, LITEST_ANY);
  6914. litest_add(proximity_has_axes, LITEST_TABLET, LITEST_ANY);
  6915. litest_add(bad_distance_events, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
  6916. litest_add(proximity_range_enter, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
  6917. litest_add(proximity_range_in_out, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
  6918. litest_add(proximity_range_button_click, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
  6919. litest_add(proximity_range_button_press, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
  6920. litest_add(proximity_range_button_release, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
  6921. litest_add(proximity_out_slow_event, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
  6922. litest_add(proximity_out_not_during_contact, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
  6923. litest_add(proximity_out_not_during_buttonpress, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
  6924. litest_add(proximity_out_disables_forced, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM);
  6925. litest_add(proximity_out_disables_forced_after_forced, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM);
  6926. litest_add(proximity_forced_in_with_eraser_swap, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM);
  6927. /* clang-format on */
  6928. }
  6929. TEST_COLLECTION(tablet_tip)
  6930. {
  6931. /* clang-format off */
  6932. litest_add(tip_down_up, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6933. litest_add(tip_down_prox_in, LITEST_TABLET, LITEST_ANY);
  6934. litest_add(tip_up_prox_out, LITEST_TABLET, LITEST_ANY);
  6935. litest_add(tip_down_btn_change, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6936. litest_add(tip_up_btn_change, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6937. litest_add(tip_down_motion, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6938. litest_add(tip_up_motion, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6939. litest_add(tip_down_up_eraser, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6940. litest_with_parameters(params, "axis", 'I', 2, litest_named_i32(ABS_X), litest_named_i32(ABS_Y)) {
  6941. litest_add_parametrized(tip_up_motion_one_axis, LITEST_TABLET|LITEST_HOVER, LITEST_ANY, params);
  6942. }
  6943. litest_add(tip_state_proximity, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6944. litest_add(tip_state_axis, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6945. litest_add(tip_state_button, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
  6946. litest_add_no_device(tip_up_on_delete);
  6947. /* clang-format on */
  6948. }