dwl.c.orig 119 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908
  1. /*
  2. * See LICENSE file for copyright and license details.
  3. */
  4. #include <getopt.h>
  5. #include <libinput.h>
  6. #include <linux/input-event-codes.h>
  7. #include <math.h>
  8. #include <libdrm/drm_fourcc.h>
  9. #include <signal.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <sys/wait.h>
  13. #include <time.h>
  14. #include <unistd.h>
  15. #include <wayland-server-core.h>
  16. #include <wlr/backend.h>
  17. #include <wlr/backend/libinput.h>
  18. #include <wlr/interfaces/wlr_keyboard.h>
  19. #include <wlr/render/allocator.h>
  20. #include <wlr/render/wlr_renderer.h>
  21. #include <wlr/types/wlr_alpha_modifier_v1.h>
  22. #include <wlr/types/wlr_compositor.h>
  23. #include <wlr/types/wlr_cursor.h>
  24. #include <wlr/types/wlr_cursor_shape_v1.h>
  25. #include <wlr/types/wlr_data_control_v1.h>
  26. #include <wlr/types/wlr_data_device.h>
  27. #include <wlr/types/wlr_drm.h>
  28. #include <wlr/types/wlr_export_dmabuf_v1.h>
  29. #include <wlr/types/wlr_fractional_scale_v1.h>
  30. #include <wlr/types/wlr_gamma_control_v1.h>
  31. #include <wlr/types/wlr_idle_inhibit_v1.h>
  32. #include <wlr/types/wlr_idle_notify_v1.h>
  33. #include <wlr/types/wlr_input_device.h>
  34. #include <wlr/types/wlr_keyboard.h>
  35. #include <wlr/types/wlr_keyboard_group.h>
  36. #include <wlr/types/wlr_layer_shell_v1.h>
  37. #include <wlr/types/wlr_linux_dmabuf_v1.h>
  38. #include <wlr/types/wlr_output.h>
  39. #include <wlr/types/wlr_output_layout.h>
  40. #include <wlr/types/wlr_output_management_v1.h>
  41. #include <wlr/types/wlr_output_power_management_v1.h>
  42. #include <wlr/types/wlr_pointer.h>
  43. #include <wlr/types/wlr_pointer_constraints_v1.h>
  44. #include <wlr/types/wlr_presentation_time.h>
  45. #include <wlr/types/wlr_primary_selection.h>
  46. #include <wlr/types/wlr_primary_selection_v1.h>
  47. #include <wlr/types/wlr_relative_pointer_v1.h>
  48. #include <wlr/types/wlr_scene.h>
  49. #include <wlr/types/wlr_screencopy_v1.h>
  50. #include <wlr/types/wlr_seat.h>
  51. #include <wlr/types/wlr_server_decoration.h>
  52. #include <wlr/types/wlr_session_lock_v1.h>
  53. #include <wlr/types/wlr_single_pixel_buffer_v1.h>
  54. #include <wlr/types/wlr_subcompositor.h>
  55. #include <wlr/types/wlr_viewporter.h>
  56. #include <wlr/types/wlr_virtual_keyboard_v1.h>
  57. #include <wlr/types/wlr_virtual_pointer_v1.h>
  58. #include <wlr/types/wlr_xcursor_manager.h>
  59. #include <wlr/types/wlr_xdg_activation_v1.h>
  60. #include <wlr/types/wlr_xdg_decoration_v1.h>
  61. #include <wlr/types/wlr_xdg_output_v1.h>
  62. #include <wlr/types/wlr_xdg_shell.h>
  63. #include <wlr/util/box.h>
  64. #include <wlr/interfaces/wlr_buffer.h>
  65. #include <wlr/util/log.h>
  66. #include <wlr/util/region.h>
  67. #include <xkbcommon/xkbcommon.h>
  68. #ifdef XWAYLAND
  69. #include <wlr/xwayland.h>
  70. #include <xcb/xcb.h>
  71. #include <xcb/xcb_icccm.h>
  72. #endif
  73. #include "util.h"
  74. #include "drwl.h"
  75. /* macros */
  76. #define MAX(A, B) ((A) > (B) ? (A) : (B))
  77. #define MIN(A, B) ((A) < (B) ? (A) : (B))
  78. #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
  79. #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && (((C)->tags & (M)->tagset[(M)->seltags]) || C->issticky))
  80. #define LENGTH(X) (sizeof X / sizeof X[0])
  81. #define END(A) ((A) + LENGTH(A))
  82. #define TAGMASK ((1u << LENGTH(tags)) - 1)
  83. #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
  84. #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
  85. #define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad)
  86. /* enums */
  87. enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */
  88. enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
  89. enum { XDGShell, LayerShell, X11 }; /* client types */
  90. enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
  91. enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */
  92. #ifdef XWAYLAND
  93. enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
  94. NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
  95. #endif
  96. typedef union {
  97. int i;
  98. uint32_t ui;
  99. float f;
  100. const void *v;
  101. } Arg;
  102. typedef struct {
  103. unsigned int click;
  104. unsigned int mod;
  105. unsigned int button;
  106. void (*func)(const Arg *);
  107. const Arg arg;
  108. } Button;
  109. typedef struct Pertag Pertag;
  110. typedef struct Monitor Monitor;
  111. typedef struct {
  112. /* Must keep these three elements in this order */
  113. unsigned int type; /* XDGShell or X11* */
  114. struct wlr_box geom; /* layout-relative, includes border */
  115. Monitor *mon;
  116. struct wlr_scene_tree *scene;
  117. struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
  118. struct wlr_scene_tree *scene_surface;
  119. struct wl_list link;
  120. struct wl_list flink;
  121. union {
  122. struct wlr_xdg_surface *xdg;
  123. struct wlr_xwayland_surface *xwayland;
  124. } surface;
  125. struct wlr_xdg_toplevel_decoration_v1 *decoration;
  126. struct wl_listener commit;
  127. struct wl_listener map;
  128. struct wl_listener maximize;
  129. struct wl_listener unmap;
  130. struct wl_listener destroy;
  131. struct wl_listener set_title;
  132. struct wl_listener fullscreen;
  133. struct wl_listener set_decoration_mode;
  134. struct wl_listener destroy_decoration;
  135. struct wlr_box prev; /* layout-relative, includes border */
  136. struct wlr_box bounds;
  137. #ifdef XWAYLAND
  138. struct wl_listener activate;
  139. struct wl_listener associate;
  140. struct wl_listener dissociate;
  141. struct wl_listener configure;
  142. struct wl_listener set_hints;
  143. #endif
  144. unsigned int bw;
  145. uint32_t tags;
  146. int isfloating, isurgent, isfullscreen, issticky;
  147. uint32_t resize; /* configure serial of a pending resize */
  148. unsigned int kblayout_idx;
  149. } Client;
  150. typedef struct {
  151. uint32_t mod;
  152. xkb_keysym_t keysym;
  153. void (*func)(const Arg *);
  154. const Arg arg;
  155. } Key;
  156. typedef struct {
  157. struct wl_list link;
  158. struct wlr_keyboard_group *wlr_group;
  159. int nsyms;
  160. const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
  161. uint32_t mods; /* invalid if nsyms == 0 */
  162. struct wl_event_source *key_repeat_source;
  163. struct wl_listener modifiers;
  164. struct wl_listener key;
  165. struct wl_listener destroy;
  166. } KeyboardGroup;
  167. typedef struct {
  168. /* Must keep these three elements in this order */
  169. unsigned int type; /* LayerShell */
  170. struct wlr_box geom;
  171. Monitor *mon;
  172. struct wlr_scene_tree *scene;
  173. struct wlr_scene_tree *popups;
  174. struct wlr_scene_layer_surface_v1 *scene_layer;
  175. struct wl_list link;
  176. int mapped;
  177. struct wlr_layer_surface_v1 *layer_surface;
  178. struct wl_listener destroy;
  179. struct wl_listener unmap;
  180. struct wl_listener surface_commit;
  181. } LayerSurface;
  182. typedef struct {
  183. const char *symbol;
  184. void (*arrange)(Monitor *);
  185. } Layout;
  186. typedef struct {
  187. struct wlr_buffer base;
  188. struct wl_listener release;
  189. bool busy;
  190. Img *image;
  191. uint32_t data[];
  192. } Buffer;
  193. struct Monitor {
  194. struct wl_list link;
  195. struct wlr_output *wlr_output;
  196. struct wlr_scene_output *scene_output;
  197. struct wlr_scene_buffer *scene_buffer; /* bar buffer */
  198. struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */
  199. struct wl_listener frame;
  200. struct wl_listener destroy;
  201. struct wl_listener request_state;
  202. struct wl_listener destroy_lock_surface;
  203. struct wlr_session_lock_surface_v1 *lock_surface;
  204. struct wlr_box m; /* monitor area, layout-relative */
  205. struct {
  206. int width, height;
  207. int real_width, real_height; /* non-scaled */
  208. float scale;
  209. } b; /* bar area */
  210. struct wlr_box w; /* window area, layout-relative */
  211. struct wl_list layers[4]; /* LayerSurface.link */
  212. const Layout *lt[2];
  213. Pertag *pertag;
  214. unsigned int seltags;
  215. unsigned int sellt;
  216. uint32_t tagset[2];
  217. float mfact;
  218. int gamma_lut_changed;
  219. int nmaster;
  220. char ltsymbol[16];
  221. int asleep;
  222. Drwl *drw;
  223. Buffer *pool[2];
  224. int lrpad;
  225. };
  226. typedef struct {
  227. const char *name;
  228. float mfact;
  229. int nmaster;
  230. float scale;
  231. const Layout *lt;
  232. enum wl_output_transform rr;
  233. int x, y;
  234. } MonitorRule;
  235. typedef struct {
  236. struct wlr_pointer_constraint_v1 *constraint;
  237. struct wl_listener destroy;
  238. } PointerConstraint;
  239. typedef struct {
  240. const char *id;
  241. const char *title;
  242. uint32_t tags;
  243. int isfloating;
  244. int monitor;
  245. } Rule;
  246. typedef struct {
  247. struct wlr_scene_tree *scene;
  248. struct wlr_session_lock_v1 *lock;
  249. struct wl_listener new_surface;
  250. struct wl_listener unlock;
  251. struct wl_listener destroy;
  252. } SessionLock;
  253. /* function declarations */
  254. static void applybounds(Client *c, struct wlr_box *bbox);
  255. static void applyrules(Client *c);
  256. static void arrange(Monitor *m);
  257. static void arrangelayer(Monitor *m, struct wl_list *list,
  258. struct wlr_box *usable_area, int exclusive);
  259. static void arrangelayers(Monitor *m);
  260. static void autostartexec(void);
  261. static void axisnotify(struct wl_listener *listener, void *data);
  262. static bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy);
  263. static void bufdestroy(struct wlr_buffer *buffer);
  264. static bool bufdatabegin(struct wlr_buffer *buffer, uint32_t flags,
  265. void **data, uint32_t *format, size_t *stride);
  266. static void bufdataend(struct wlr_buffer *buffer);
  267. static Buffer *bufmon(Monitor *m);
  268. static void bufrelease(struct wl_listener *listener, void *data);
  269. static void buttonpress(struct wl_listener *listener, void *data);
  270. static void chvt(const Arg *arg);
  271. static void checkidleinhibitor(struct wlr_surface *exclude);
  272. static void cleanup(void);
  273. static void cleanupmon(struct wl_listener *listener, void *data);
  274. static void closemon(Monitor *m);
  275. static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
  276. static void commitnotify(struct wl_listener *listener, void *data);
  277. static void commitpopup(struct wl_listener *listener, void *data);
  278. static void createdecoration(struct wl_listener *listener, void *data);
  279. static void createidleinhibitor(struct wl_listener *listener, void *data);
  280. static void createkeyboard(struct wlr_keyboard *keyboard);
  281. static KeyboardGroup *createkeyboardgroup(void);
  282. static void createlayersurface(struct wl_listener *listener, void *data);
  283. static void createlocksurface(struct wl_listener *listener, void *data);
  284. static void createmon(struct wl_listener *listener, void *data);
  285. static void createnotify(struct wl_listener *listener, void *data);
  286. static void createpointer(struct wlr_pointer *pointer);
  287. static void createpointerconstraint(struct wl_listener *listener, void *data);
  288. static void createpopup(struct wl_listener *listener, void *data);
  289. static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint);
  290. static void cursorframe(struct wl_listener *listener, void *data);
  291. static void cursorwarptohint(void);
  292. static void destroydecoration(struct wl_listener *listener, void *data);
  293. static void destroydragicon(struct wl_listener *listener, void *data);
  294. static void destroyidleinhibitor(struct wl_listener *listener, void *data);
  295. static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
  296. static void destroylock(SessionLock *lock, int unlocked);
  297. static void destroylocksurface(struct wl_listener *listener, void *data);
  298. static void destroynotify(struct wl_listener *listener, void *data);
  299. static void destroypointerconstraint(struct wl_listener *listener, void *data);
  300. static void destroysessionlock(struct wl_listener *listener, void *data);
  301. static void destroysessionmgr(struct wl_listener *listener, void *data);
  302. static void destroykeyboardgroup(struct wl_listener *listener, void *data);
  303. static Monitor *dirtomon(enum wlr_direction dir);
  304. static void drawbar(Monitor *m);
  305. static void drawbars(void);
  306. static void focusclient(Client *c, int lift);
  307. static void focusmon(const Arg *arg);
  308. static void focusstack(const Arg *arg);
  309. static Client *focustop(Monitor *m);
  310. static void fullscreennotify(struct wl_listener *listener, void *data);
  311. static void gpureset(struct wl_listener *listener, void *data);
  312. static void handlecursoractivity(void);
  313. static int hidecursor(void *data);
  314. static void handlesig(int signo);
  315. static void incnmaster(const Arg *arg);
  316. static void inputdevice(struct wl_listener *listener, void *data);
  317. static void kblayout(KeyboardGroup *kb);
  318. static int keybinding(uint32_t mods, xkb_keysym_t sym);
  319. static void keypress(struct wl_listener *listener, void *data);
  320. static void keypressmod(struct wl_listener *listener, void *data);
  321. static int keyrepeat(void *data);
  322. static void killclient(const Arg *arg);
  323. static void locksession(struct wl_listener *listener, void *data);
  324. static void mapnotify(struct wl_listener *listener, void *data);
  325. static void maximizenotify(struct wl_listener *listener, void *data);
  326. static void monocle(Monitor *m);
  327. static void movestack(const Arg *arg);
  328. static void motionabsolute(struct wl_listener *listener, void *data);
  329. static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx,
  330. double sy, double sx_unaccel, double sy_unaccel);
  331. static void motionrelative(struct wl_listener *listener, void *data);
  332. static void moveresize(const Arg *arg);
  333. unsigned int nextocctag(int);
  334. static void outputmgrapply(struct wl_listener *listener, void *data);
  335. static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test);
  336. static void outputmgrtest(struct wl_listener *listener, void *data);
  337. static void pointerfocus(Client *c, struct wlr_surface *surface,
  338. double sx, double sy, uint32_t time);
  339. static void powermgrsetmode(struct wl_listener *listener, void *data);
  340. static void quit(const Arg *arg);
  341. static void rendermon(struct wl_listener *listener, void *data);
  342. static void requestdecorationmode(struct wl_listener *listener, void *data);
  343. static void requeststartdrag(struct wl_listener *listener, void *data);
  344. static void requestmonstate(struct wl_listener *listener, void *data);
  345. static void resize(Client *c, struct wlr_box geo, int interact);
  346. static void run(char *startup_cmd);
  347. static void setcursor(struct wl_listener *listener, void *data);
  348. static void setcursorshape(struct wl_listener *listener, void *data);
  349. static void setfloating(Client *c, int floating);
  350. static void setfullscreen(Client *c, int fullscreen);
  351. static void setsticky(Client *c, int sticky);
  352. static void setgamma(struct wl_listener *listener, void *data);
  353. static void setlayout(const Arg *arg);
  354. static void setmfact(const Arg *arg);
  355. static void setmon(Client *c, Monitor *m, uint32_t newtags);
  356. static void setpsel(struct wl_listener *listener, void *data);
  357. static void setsel(struct wl_listener *listener, void *data);
  358. static void setup(void);
  359. static void spawn(const Arg *arg);
  360. static void startdrag(struct wl_listener *listener, void *data);
  361. static int statusin(int fd, unsigned int mask, void *data);
  362. static void tag(const Arg *arg);
  363. static void tagmon(const Arg *arg);
  364. static void tile(Monitor *m);
  365. static void togglebar(const Arg *arg);
  366. static void togglefloating(const Arg *arg);
  367. static void togglesticky(const Arg *arg);
  368. static void togglefullscreen(const Arg *arg);
  369. static void toggletag(const Arg *arg);
  370. static void toggleview(const Arg *arg);
  371. static void unlocksession(struct wl_listener *listener, void *data);
  372. static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
  373. static void unmapnotify(struct wl_listener *listener, void *data);
  374. static void updatemons(struct wl_listener *listener, void *data);
  375. static void updatebar(Monitor *m);
  376. static void updatetitle(struct wl_listener *listener, void *data);
  377. static void urgent(struct wl_listener *listener, void *data);
  378. static void view(const Arg *arg);
  379. static void viewnextocctag(const Arg *argint);
  380. static void virtualkeyboard(struct wl_listener *listener, void *data);
  381. static void virtualpointer(struct wl_listener *listener, void *data);
  382. static Monitor *xytomon(double x, double y);
  383. static void xytonode(double x, double y, struct wlr_surface **psurface,
  384. Client **pc, LayerSurface **pl, double *nx, double *ny);
  385. static void zoom(const Arg *arg);
  386. static void bstack(Monitor *m);
  387. static void bstackhoriz(Monitor *m);
  388. /* variables */
  389. static const char broken[] = "broken";
  390. static pid_t child_pid = -1;
  391. static int locked;
  392. static void *exclusive_focus;
  393. static struct wl_display *dpy;
  394. static struct wl_event_loop *event_loop;
  395. static struct wlr_backend *backend;
  396. static struct wlr_scene *scene;
  397. static struct wlr_scene_tree *layers[NUM_LAYERS];
  398. static struct wlr_scene_tree *drag_icon;
  399. /* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */
  400. static const int layermap[] = { LyrBg, LyrBottom, LyrTop, LyrOverlay };
  401. static struct wlr_renderer *drw;
  402. static struct wlr_allocator *alloc;
  403. static struct wlr_compositor *compositor;
  404. static struct wlr_session *session;
  405. static struct wlr_xdg_shell *xdg_shell;
  406. static struct wlr_xdg_activation_v1 *activation;
  407. static struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr;
  408. static struct wl_list clients; /* tiling order */
  409. static struct wl_list fstack; /* focus order */
  410. static struct wlr_idle_notifier_v1 *idle_notifier;
  411. static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr;
  412. static struct wlr_layer_shell_v1 *layer_shell;
  413. static struct wlr_output_manager_v1 *output_mgr;
  414. static struct wlr_gamma_control_manager_v1 *gamma_control_mgr;
  415. static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
  416. static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
  417. static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr;
  418. static struct wlr_output_power_manager_v1 *power_mgr;
  419. static struct wlr_pointer_constraints_v1 *pointer_constraints;
  420. static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
  421. static struct wlr_pointer_constraint_v1 *active_constraint;
  422. static struct wlr_cursor *cursor;
  423. static struct wlr_xcursor_manager *cursor_mgr;
  424. static struct wl_event_source *hide_source;
  425. static bool cursor_hidden = false;
  426. static struct {
  427. enum wp_cursor_shape_device_v1_shape shape;
  428. struct wlr_surface *surface;
  429. int hotspot_x;
  430. int hotspot_y;
  431. } last_cursor;
  432. static struct wlr_scene_rect *root_bg;
  433. static struct wlr_session_lock_manager_v1 *session_lock_mgr;
  434. static struct wlr_scene_rect *locked_bg;
  435. static struct wlr_session_lock_v1 *cur_lock;
  436. static struct wl_listener lock_listener = {.notify = locksession};
  437. static struct wlr_seat *seat;
  438. static KeyboardGroup *kb_group;
  439. static unsigned int cursor_mode;
  440. static Client *grabc;
  441. static int grabcx, grabcy; /* client-relative */
  442. static struct wlr_output_layout *output_layout;
  443. static struct wlr_box sgeom;
  444. static struct wl_list mons;
  445. static Monitor *selmon;
  446. static char stext[256];
  447. static struct wl_event_source *status_event_source;
  448. static const struct wlr_buffer_impl buffer_impl = {
  449. .destroy = bufdestroy,
  450. .begin_data_ptr_access = bufdatabegin,
  451. .end_data_ptr_access = bufdataend,
  452. };
  453. static unsigned int kblayout_idx = -1;
  454. #ifdef XWAYLAND
  455. static void activatex11(struct wl_listener *listener, void *data);
  456. static void associatex11(struct wl_listener *listener, void *data);
  457. static void configurex11(struct wl_listener *listener, void *data);
  458. static void createnotifyx11(struct wl_listener *listener, void *data);
  459. static void dissociatex11(struct wl_listener *listener, void *data);
  460. static xcb_atom_t getatom(xcb_connection_t *xc, const char *name);
  461. static void sethints(struct wl_listener *listener, void *data);
  462. static void xwaylandready(struct wl_listener *listener, void *data);
  463. static struct wlr_xwayland *xwayland;
  464. static xcb_atom_t netatom[NetLast];
  465. #endif
  466. /* configuration, allows nested code to access above variables */
  467. #include "config.h"
  468. /* attempt to encapsulate suck into one file */
  469. #include "client.h"
  470. static pid_t *autostart_pids;
  471. static size_t autostart_len;
  472. struct Pertag {
  473. unsigned int curtag, prevtag; /* current and previous tag */
  474. int nmasters[TAGCOUNT + 1]; /* number of windows in master area */
  475. float mfacts[TAGCOUNT + 1]; /* mfacts per tag */
  476. unsigned int sellts[TAGCOUNT + 1]; /* selected layouts */
  477. const Layout *ltidxs[TAGCOUNT + 1][2]; /* matrix of tags and layouts indexes */
  478. };
  479. /* function implementations */
  480. void
  481. applybounds(Client *c, struct wlr_box *bbox)
  482. {
  483. /* set minimum possible */
  484. c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
  485. c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);
  486. if (c->geom.x >= bbox->x + bbox->width)
  487. c->geom.x = bbox->x + bbox->width - c->geom.width;
  488. if (c->geom.y >= bbox->y + bbox->height)
  489. c->geom.y = bbox->y + bbox->height - c->geom.height;
  490. if (c->geom.x + c->geom.width <= bbox->x)
  491. c->geom.x = bbox->x;
  492. if (c->geom.y + c->geom.height <= bbox->y)
  493. c->geom.y = bbox->y;
  494. }
  495. void
  496. applyrules(Client *c)
  497. {
  498. /* rule matching */
  499. const char *appid, *title;
  500. uint32_t newtags = 0;
  501. int i;
  502. const Rule *r;
  503. Monitor *mon = selmon, *m;
  504. c->isfloating = client_is_float_type(c);
  505. if (!(appid = client_get_appid(c)))
  506. appid = broken;
  507. if (!(title = client_get_title(c)))
  508. title = broken;
  509. for (r = rules; r < END(rules); r++) {
  510. if ((!r->title || strstr(title, r->title))
  511. && (!r->id || strstr(appid, r->id))) {
  512. c->isfloating = r->isfloating;
  513. newtags |= r->tags;
  514. i = 0;
  515. wl_list_for_each(m, &mons, link) {
  516. if (r->monitor == i++)
  517. mon = m;
  518. }
  519. }
  520. }
  521. if (mon) {
  522. c->geom.x = (mon->w.width - c->geom.width) / 2 + mon->m.x;
  523. c->geom.y = (mon->w.height - c->geom.height) / 2 + mon->m.y;
  524. }
  525. setmon(c, mon, newtags);
  526. }
  527. void
  528. arrange(Monitor *m)
  529. {
  530. Client *c;
  531. if (!m->wlr_output->enabled)
  532. return;
  533. wl_list_for_each(c, &clients, link) {
  534. if (c->mon == m) {
  535. wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m));
  536. client_set_suspended(c, !VISIBLEON(c, m));
  537. }
  538. }
  539. wlr_scene_node_set_enabled(&m->fullscreen_bg->node,
  540. (c = focustop(m)) && c->isfullscreen);
  541. strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
  542. /* We move all clients (except fullscreen and unmanaged) to LyrTile while
  543. * in floating layout to avoid "real" floating clients be always on top */
  544. wl_list_for_each(c, &clients, link) {
  545. if (c->mon != m || c->scene->node.parent == layers[LyrFS])
  546. continue;
  547. wlr_scene_node_reparent(&c->scene->node,
  548. (!m->lt[m->sellt]->arrange && c->isfloating)
  549. ? layers[LyrTile]
  550. : (m->lt[m->sellt]->arrange && c->isfloating)
  551. ? layers[LyrFloat]
  552. : c->scene->node.parent);
  553. }
  554. if (m->lt[m->sellt]->arrange)
  555. m->lt[m->sellt]->arrange(m);
  556. motionnotify(0, NULL, 0, 0, 0, 0);
  557. checkidleinhibitor(NULL);
  558. }
  559. void
  560. arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int exclusive)
  561. {
  562. LayerSurface *l;
  563. struct wlr_box full_area = m->m;
  564. wl_list_for_each(l, list, link) {
  565. struct wlr_layer_surface_v1 *layer_surface = l->layer_surface;
  566. if (exclusive != (layer_surface->current.exclusive_zone > 0))
  567. continue;
  568. wlr_scene_layer_surface_v1_configure(l->scene_layer, &full_area, usable_area);
  569. wlr_scene_node_set_position(&l->popups->node, l->scene->node.x, l->scene->node.y);
  570. l->geom.x = l->scene->node.x;
  571. l->geom.y = l->scene->node.y;
  572. }
  573. }
  574. void
  575. arrangelayers(Monitor *m)
  576. {
  577. int i;
  578. struct wlr_box usable_area = m->m;
  579. LayerSurface *l;
  580. uint32_t layers_above_shell[] = {
  581. ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
  582. ZWLR_LAYER_SHELL_V1_LAYER_TOP,
  583. };
  584. if (!m->wlr_output->enabled)
  585. return;
  586. if (m->scene_buffer->node.enabled) {
  587. usable_area.height -= m->b.real_height;
  588. usable_area.y += topbar ? m->b.real_height : 0;
  589. }
  590. /* Arrange exclusive surfaces from top->bottom */
  591. for (i = 3; i >= 0; i--)
  592. arrangelayer(m, &m->layers[i], &usable_area, 1);
  593. if (!wlr_box_equal(&usable_area, &m->w)) {
  594. m->w = usable_area;
  595. arrange(m);
  596. }
  597. /* Arrange non-exlusive surfaces from top->bottom */
  598. for (i = 3; i >= 0; i--)
  599. arrangelayer(m, &m->layers[i], &usable_area, 0);
  600. /* Find topmost keyboard interactive layer, if such a layer exists */
  601. for (i = 0; i < (int)LENGTH(layers_above_shell); i++) {
  602. wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) {
  603. if (locked || !l->layer_surface->current.keyboard_interactive || !l->mapped)
  604. continue;
  605. /* Deactivate the focused client. */
  606. focusclient(NULL, 0);
  607. exclusive_focus = l;
  608. client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
  609. return;
  610. }
  611. }
  612. }
  613. void
  614. autostartexec(void) {
  615. const char *const *p;
  616. size_t i = 0;
  617. /* count entries */
  618. for (p = autostart; *p; autostart_len++, p++)
  619. while (*++p);
  620. autostart_pids = calloc(autostart_len, sizeof(pid_t));
  621. for (p = autostart; *p; i++, p++) {
  622. if ((autostart_pids[i] = fork()) == 0) {
  623. setsid();
  624. execvp(*p, (char *const *)p);
  625. die("dwl: execvp %s:", *p);
  626. }
  627. /* skip arguments */
  628. while (*++p);
  629. }
  630. }
  631. void
  632. axisnotify(struct wl_listener *listener, void *data)
  633. {
  634. /* This event is forwarded by the cursor when a pointer emits an axis event,
  635. * for example when you move the scroll wheel. */
  636. struct wlr_pointer_axis_event *event = data;
  637. wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
  638. handlecursoractivity();
  639. /* TODO: allow usage of scroll whell for mousebindings, it can be implemented
  640. * checking the event's orientation and the delta of the event */
  641. /* Notify the client with pointer focus of the axis event. */
  642. wlr_seat_pointer_notify_axis(seat,
  643. event->time_msec, event->orientation, event->delta,
  644. event->delta_discrete, event->source, event->relative_direction);
  645. }
  646. bool
  647. baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy)
  648. {
  649. return true;
  650. }
  651. void
  652. bufdestroy(struct wlr_buffer *wlr_buffer)
  653. {
  654. Buffer *buf = wl_container_of(wlr_buffer, buf, base);
  655. if (buf->busy)
  656. wl_list_remove(&buf->release.link);
  657. drwl_image_destroy(buf->image);
  658. free(buf);
  659. }
  660. bool
  661. bufdatabegin(struct wlr_buffer *wlr_buffer, uint32_t flags,
  662. void **data, uint32_t *format, size_t *stride)
  663. {
  664. Buffer *buf = wl_container_of(wlr_buffer, buf, base);
  665. if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false;
  666. *data = buf->data;
  667. *stride = wlr_buffer->width * 4;
  668. *format = DRM_FORMAT_ARGB8888;
  669. return true;
  670. }
  671. void
  672. bufdataend(struct wlr_buffer *wlr_buffer)
  673. {
  674. }
  675. Buffer *
  676. bufmon(Monitor *m)
  677. {
  678. size_t i;
  679. Buffer *buf = NULL;
  680. for (i = 0; i < LENGTH(m->pool); i++) {
  681. if (m->pool[i]) {
  682. if (m->pool[i]->busy)
  683. continue;
  684. buf = m->pool[i];
  685. break;
  686. }
  687. buf = ecalloc(1, sizeof(Buffer) + (m->b.width * 4 * m->b.height));
  688. buf->image = drwl_image_create(NULL, m->b.width, m->b.height, buf->data);
  689. wlr_buffer_init(&buf->base, &buffer_impl, m->b.width, m->b.height);
  690. m->pool[i] = buf;
  691. break;
  692. }
  693. if (!buf)
  694. return NULL;
  695. buf->busy = true;
  696. LISTEN(&buf->base.events.release, &buf->release, bufrelease);
  697. wlr_buffer_lock(&buf->base);
  698. drwl_setimage(m->drw, buf->image);
  699. return buf;
  700. }
  701. void
  702. bufrelease(struct wl_listener *listener, void *data)
  703. {
  704. Buffer *buf = wl_container_of(listener, buf, release);
  705. buf->busy = false;
  706. wl_list_remove(&buf->release.link);
  707. }
  708. void
  709. buttonpress(struct wl_listener *listener, void *data)
  710. {
  711. unsigned int i = 0, x = 0;
  712. double cx;
  713. unsigned int click;
  714. struct wlr_pointer_button_event *event = data;
  715. struct wlr_keyboard *keyboard;
  716. struct wlr_scene_node *node;
  717. struct wlr_scene_buffer *buffer;
  718. uint32_t mods;
  719. Arg arg = {0};
  720. Client *c;
  721. const Button *b;
  722. wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
  723. handlecursoractivity();
  724. click = ClkRoot;
  725. xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
  726. if (c)
  727. click = ClkClient;
  728. switch (event->state) {
  729. case WL_POINTER_BUTTON_STATE_PRESSED:
  730. cursor_mode = CurPressed;
  731. selmon = xytomon(cursor->x, cursor->y);
  732. if (locked)
  733. break;
  734. if (!c && !exclusive_focus &&
  735. (node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) &&
  736. (buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) {
  737. cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale;
  738. do
  739. x += TEXTW(selmon, tags[i]);
  740. while (cx >= x && ++i < LENGTH(tags));
  741. if (i < LENGTH(tags)) {
  742. click = ClkTagBar;
  743. arg.ui = 1 << i;
  744. } else if (cx < x + TEXTW(selmon, selmon->ltsymbol))
  745. click = ClkLtSymbol;
  746. else if (cx > selmon->b.width - (TEXTW(selmon, stext) - selmon->lrpad + 2)) {
  747. click = ClkStatus;
  748. } else
  749. click = ClkTitle;
  750. }
  751. /* Change focus if the button was _pressed_ over a client */
  752. xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
  753. if (click == ClkClient && (!client_is_unmanaged(c) || client_wants_focus(c)))
  754. focusclient(c, 1);
  755. keyboard = wlr_seat_get_keyboard(seat);
  756. mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
  757. for (b = buttons; b < END(buttons); b++) {
  758. if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) {
  759. b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg);
  760. return;
  761. }
  762. }
  763. break;
  764. case WL_POINTER_BUTTON_STATE_RELEASED:
  765. /* If you released any buttons, we exit interactive move/resize mode. */
  766. /* TODO should reset to the pointer focus's current setcursor */
  767. if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
  768. wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
  769. cursor_mode = CurNormal;
  770. /* Drop the window off on its new monitor */
  771. selmon = xytomon(cursor->x, cursor->y);
  772. setmon(grabc, selmon, 0);
  773. return;
  774. } else {
  775. cursor_mode = CurNormal;
  776. }
  777. break;
  778. }
  779. /* If the event wasn't handled by the compositor, notify the client with
  780. * pointer focus that a button press has occurred */
  781. wlr_seat_pointer_notify_button(seat,
  782. event->time_msec, event->button, event->state);
  783. }
  784. void
  785. chvt(const Arg *arg)
  786. {
  787. wlr_session_change_vt(session, arg->ui);
  788. }
  789. void
  790. checkidleinhibitor(struct wlr_surface *exclude)
  791. {
  792. int inhibited = 0, unused_lx, unused_ly;
  793. struct wlr_idle_inhibitor_v1 *inhibitor;
  794. wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) {
  795. struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface);
  796. struct wlr_scene_tree *tree = surface->data;
  797. if (exclude != surface && (bypass_surface_visibility || (!tree
  798. || wlr_scene_node_coords(&tree->node, &unused_lx, &unused_ly)))) {
  799. inhibited = 1;
  800. break;
  801. }
  802. }
  803. wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited);
  804. }
  805. void
  806. cleanup(void)
  807. {
  808. size_t i;
  809. #ifdef XWAYLAND
  810. wlr_xwayland_destroy(xwayland);
  811. xwayland = NULL;
  812. #endif
  813. wl_display_destroy_clients(dpy);
  814. /* kill child processes */
  815. for (i = 0; i < autostart_len; i++) {
  816. if (0 < autostart_pids[i]) {
  817. kill(autostart_pids[i], SIGTERM);
  818. waitpid(autostart_pids[i], NULL, 0);
  819. }
  820. }
  821. if (child_pid > 0) {
  822. kill(-child_pid, SIGTERM);
  823. waitpid(child_pid, NULL, 0);
  824. }
  825. wlr_xcursor_manager_destroy(cursor_mgr);
  826. destroykeyboardgroup(&kb_group->destroy, NULL);
  827. /* If it's not destroyed manually it will cause a use-after-free of wlr_seat.
  828. * Destroy it until it's fixed in the wlroots side */
  829. wlr_backend_destroy(backend);
  830. wl_display_destroy(dpy);
  831. /* Destroy after the wayland display (when the monitors are already destroyed)
  832. to avoid destroying them with an invalid scene output. */
  833. wlr_scene_node_destroy(&scene->tree.node);
  834. drwl_fini();
  835. }
  836. void
  837. cleanupmon(struct wl_listener *listener, void *data)
  838. {
  839. Monitor *m = wl_container_of(listener, m, destroy);
  840. LayerSurface *l, *tmp;
  841. size_t i;
  842. /* m->layers[i] are intentionally not unlinked */
  843. for (i = 0; i < LENGTH(m->layers); i++) {
  844. wl_list_for_each_safe(l, tmp, &m->layers[i], link)
  845. wlr_layer_surface_v1_destroy(l->layer_surface);
  846. }
  847. for (i = 0; i < LENGTH(m->pool); i++)
  848. wlr_buffer_drop(&m->pool[i]->base);
  849. drwl_setimage(m->drw, NULL);
  850. drwl_destroy(m->drw);
  851. wl_list_remove(&m->destroy.link);
  852. wl_list_remove(&m->frame.link);
  853. wl_list_remove(&m->link);
  854. wl_list_remove(&m->request_state.link);
  855. m->wlr_output->data = NULL;
  856. wlr_output_layout_remove(output_layout, m->wlr_output);
  857. wlr_scene_output_destroy(m->scene_output);
  858. free(m->pertag);
  859. closemon(m);
  860. wlr_scene_node_destroy(&m->fullscreen_bg->node);
  861. wlr_scene_node_destroy(&m->scene_buffer->node);
  862. free(m);
  863. }
  864. void
  865. closemon(Monitor *m)
  866. {
  867. /* update selmon if needed and
  868. * move closed monitor's clients to the focused one */
  869. Client *c;
  870. int i = 0, nmons = wl_list_length(&mons);
  871. if (!nmons) {
  872. selmon = NULL;
  873. } else if (m == selmon) {
  874. do /* don't switch to disabled mons */
  875. selmon = wl_container_of(mons.next, selmon, link);
  876. while (!selmon->wlr_output->enabled && i++ < nmons);
  877. if (!selmon->wlr_output->enabled)
  878. selmon = NULL;
  879. }
  880. wl_list_for_each(c, &clients, link) {
  881. if (c->isfloating && c->geom.x > m->m.width)
  882. resize(c, (struct wlr_box){.x = c->geom.x - m->w.width, .y = c->geom.y,
  883. .width = c->geom.width, .height = c->geom.height}, 0);
  884. if (c->mon == m)
  885. setmon(c, selmon, c->tags);
  886. }
  887. focusclient(focustop(selmon), 1);
  888. drawbars();
  889. }
  890. void
  891. commitlayersurfacenotify(struct wl_listener *listener, void *data)
  892. {
  893. LayerSurface *l = wl_container_of(listener, l, surface_commit);
  894. struct wlr_layer_surface_v1 *layer_surface = l->layer_surface;
  895. struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->current.layer]];
  896. struct wlr_layer_surface_v1_state old_state;
  897. if (l->layer_surface->initial_commit) {
  898. wlr_fractional_scale_v1_notify_scale(layer_surface->surface, l->mon->wlr_output->scale);
  899. wlr_surface_set_preferred_buffer_scale(layer_surface->surface, (int32_t)ceilf(l->mon->wlr_output->scale));
  900. /* Temporarily set the layer's current state to pending
  901. * so that we can easily arrange it */
  902. old_state = l->layer_surface->current;
  903. l->layer_surface->current = l->layer_surface->pending;
  904. arrangelayers(l->mon);
  905. l->layer_surface->current = old_state;
  906. return;
  907. }
  908. if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped)
  909. return;
  910. l->mapped = layer_surface->surface->mapped;
  911. if (scene_layer != l->scene->node.parent) {
  912. wlr_scene_node_reparent(&l->scene->node, scene_layer);
  913. wl_list_remove(&l->link);
  914. wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link);
  915. wlr_scene_node_reparent(&l->popups->node, (layer_surface->current.layer
  916. < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer));
  917. }
  918. arrangelayers(l->mon);
  919. }
  920. void
  921. commitnotify(struct wl_listener *listener, void *data)
  922. {
  923. Client *c = wl_container_of(listener, c, commit);
  924. if (c->surface.xdg->initial_commit) {
  925. /*
  926. * Get the monitor this client will be rendered on
  927. * Note that if the user set a rule in which the client is placed on
  928. * a different monitor based on its title this will likely select
  929. * a wrong monitor.
  930. */
  931. applyrules(c);
  932. wlr_surface_set_preferred_buffer_scale(client_surface(c), (int)ceilf(c->mon->wlr_output->scale));
  933. wlr_fractional_scale_v1_notify_scale(client_surface(c), c->mon->wlr_output->scale);
  934. setmon(c, NULL, 0); /* Make sure to reapply rules in mapnotify() */
  935. wlr_xdg_toplevel_set_wm_capabilities(c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
  936. wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0);
  937. if (c->decoration)
  938. requestdecorationmode(&c->set_decoration_mode, c->decoration);
  939. return;
  940. }
  941. if (client_surface(c)->mapped && c->mon)
  942. resize(c, c->geom, (c->isfloating && !c->isfullscreen));
  943. /* mark a pending resize as completed */
  944. if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
  945. c->resize = 0;
  946. }
  947. void
  948. commitpopup(struct wl_listener *listener, void *data)
  949. {
  950. struct wlr_surface *surface = data;
  951. struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface);
  952. LayerSurface *l = NULL;
  953. Client *c = NULL;
  954. struct wlr_box box;
  955. int type = -1;
  956. if (!popup->base->initial_commit)
  957. return;
  958. type = toplevel_from_wlr_surface(popup->base->surface, &c, &l);
  959. if (!popup->parent || type < 0)
  960. return;
  961. popup->base->surface->data = wlr_scene_xdg_surface_create(
  962. popup->parent->data, popup->base);
  963. if ((l && !l->mon) || (c && !c->mon))
  964. return;
  965. box = type == LayerShell ? l->mon->m : c->mon->w;
  966. box.x -= (type == LayerShell ? l->geom.x : c->geom.x);
  967. box.y -= (type == LayerShell ? l->geom.y : c->geom.y);
  968. wlr_xdg_popup_unconstrain_from_box(popup, &box);
  969. wl_list_remove(&listener->link);
  970. }
  971. void
  972. createdecoration(struct wl_listener *listener, void *data)
  973. {
  974. struct wlr_xdg_toplevel_decoration_v1 *deco = data;
  975. Client *c = deco->toplevel->base->data;
  976. c->decoration = deco;
  977. LISTEN(&deco->events.request_mode, &c->set_decoration_mode, requestdecorationmode);
  978. LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration);
  979. requestdecorationmode(&c->set_decoration_mode, deco);
  980. }
  981. void
  982. createidleinhibitor(struct wl_listener *listener, void *data)
  983. {
  984. struct wlr_idle_inhibitor_v1 *idle_inhibitor = data;
  985. LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor);
  986. checkidleinhibitor(NULL);
  987. }
  988. void
  989. createkeyboard(struct wlr_keyboard *keyboard)
  990. {
  991. /* Set the keymap to match the group keymap */
  992. wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap);
  993. /* Add the new keyboard to the group */
  994. wlr_keyboard_group_add_keyboard(kb_group->wlr_group, keyboard);
  995. kblayout(kb_group);
  996. }
  997. KeyboardGroup *
  998. createkeyboardgroup(void)
  999. {
  1000. KeyboardGroup *group = ecalloc(1, sizeof(*group));
  1001. struct xkb_context *context;
  1002. struct xkb_keymap *keymap;
  1003. group->wlr_group = wlr_keyboard_group_create();
  1004. group->wlr_group->data = group;
  1005. /* Prepare an XKB keymap and assign it to the keyboard group. */
  1006. context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
  1007. if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules,
  1008. XKB_KEYMAP_COMPILE_NO_FLAGS)))
  1009. die("failed to compile keymap");
  1010. wlr_keyboard_set_keymap(&group->wlr_group->keyboard, keymap);
  1011. xkb_keymap_unref(keymap);
  1012. xkb_context_unref(context);
  1013. wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate, repeat_delay);
  1014. /* Set up listeners for keyboard events */
  1015. LISTEN(&group->wlr_group->keyboard.events.key, &group->key, keypress);
  1016. LISTEN(&group->wlr_group->keyboard.events.modifiers, &group->modifiers, keypressmod);
  1017. group->key_repeat_source = wl_event_loop_add_timer(event_loop, keyrepeat, group);
  1018. /* A seat can only have one keyboard, but this is a limitation of the
  1019. * Wayland protocol - not wlroots. We assign all connected keyboards to the
  1020. * same wlr_keyboard_group, which provides a single wlr_keyboard interface for
  1021. * all of them. Set this combined wlr_keyboard as the seat keyboard.
  1022. */
  1023. wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
  1024. return group;
  1025. }
  1026. void
  1027. createlayersurface(struct wl_listener *listener, void *data)
  1028. {
  1029. struct wlr_layer_surface_v1 *layer_surface = data;
  1030. LayerSurface *l;
  1031. struct wlr_surface *surface = layer_surface->surface;
  1032. struct wlr_scene_tree *scene_layer = layers[layermap[layer_surface->pending.layer]];
  1033. if (!layer_surface->output
  1034. && !(layer_surface->output = selmon ? selmon->wlr_output : NULL)) {
  1035. wlr_layer_surface_v1_destroy(layer_surface);
  1036. return;
  1037. }
  1038. l = layer_surface->data = ecalloc(1, sizeof(*l));
  1039. l->type = LayerShell;
  1040. LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify);
  1041. LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify);
  1042. LISTEN(&layer_surface->events.destroy, &l->destroy, destroylayersurfacenotify);
  1043. l->layer_surface = layer_surface;
  1044. l->mon = layer_surface->output->data;
  1045. l->scene_layer = wlr_scene_layer_surface_v1_create(scene_layer, layer_surface);
  1046. l->scene = l->scene_layer->tree;
  1047. l->popups = surface->data = wlr_scene_tree_create(layer_surface->current.layer
  1048. < ZWLR_LAYER_SHELL_V1_LAYER_TOP ? layers[LyrTop] : scene_layer);
  1049. l->scene->node.data = l->popups->node.data = l;
  1050. wl_list_insert(&l->mon->layers[layer_surface->pending.layer],&l->link);
  1051. wlr_surface_send_enter(surface, layer_surface->output);
  1052. }
  1053. void
  1054. createlocksurface(struct wl_listener *listener, void *data)
  1055. {
  1056. SessionLock *lock = wl_container_of(listener, lock, new_surface);
  1057. struct wlr_session_lock_surface_v1 *lock_surface = data;
  1058. Monitor *m = lock_surface->output->data;
  1059. struct wlr_scene_tree *scene_tree = lock_surface->surface->data
  1060. = wlr_scene_subsurface_tree_create(lock->scene, lock_surface->surface);
  1061. m->lock_surface = lock_surface;
  1062. wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y);
  1063. wlr_session_lock_surface_v1_configure(lock_surface, m->m.width, m->m.height);
  1064. LISTEN(&lock_surface->events.destroy, &m->destroy_lock_surface, destroylocksurface);
  1065. if (m == selmon)
  1066. client_notify_enter(lock_surface->surface, wlr_seat_get_keyboard(seat));
  1067. }
  1068. void
  1069. createmon(struct wl_listener *listener, void *data)
  1070. {
  1071. /* This event is raised by the backend when a new output (aka a display or
  1072. * monitor) becomes available. */
  1073. struct wlr_output *wlr_output = data;
  1074. const MonitorRule *r;
  1075. size_t i;
  1076. struct wlr_output_state state;
  1077. Monitor *m;
  1078. if (!wlr_output_init_render(wlr_output, alloc, drw))
  1079. return;
  1080. m = wlr_output->data = ecalloc(1, sizeof(*m));
  1081. m->wlr_output = wlr_output;
  1082. for (i = 0; i < LENGTH(m->layers); i++)
  1083. wl_list_init(&m->layers[i]);
  1084. wlr_output_state_init(&state);
  1085. /* Initialize monitor state using configured rules */
  1086. m->tagset[0] = m->tagset[1] = 1;
  1087. for (r = monrules; r < END(monrules); r++) {
  1088. if (!r->name || strstr(wlr_output->name, r->name)) {
  1089. m->m.x = r->x;
  1090. m->m.y = r->y;
  1091. m->mfact = r->mfact;
  1092. m->nmaster = r->nmaster;
  1093. m->lt[0] = r->lt;
  1094. m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]];
  1095. strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol));
  1096. wlr_output_state_set_scale(&state, r->scale);
  1097. wlr_output_state_set_transform(&state, r->rr);
  1098. break;
  1099. }
  1100. }
  1101. /* The mode is a tuple of (width, height, refresh rate), and each
  1102. * monitor supports only a specific set of modes. We just pick the
  1103. * monitor's preferred mode; a more sophisticated compositor would let
  1104. * the user configure it. */
  1105. wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output));
  1106. /* Set up event listeners */
  1107. LISTEN(&wlr_output->events.frame, &m->frame, rendermon);
  1108. LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon);
  1109. LISTEN(&wlr_output->events.request_state, &m->request_state, requestmonstate);
  1110. wlr_output_state_set_enabled(&state, 1);
  1111. wlr_output_commit_state(wlr_output, &state);
  1112. wlr_output_state_finish(&state);
  1113. if (!(m->drw = drwl_create()))
  1114. die("failed to create drwl context");
  1115. m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL);
  1116. m->scene_buffer->point_accepts_input = baracceptsinput;
  1117. updatebar(m);
  1118. wl_list_insert(&mons, &m->link);
  1119. drawbars();
  1120. m->pertag = calloc(1, sizeof(Pertag));
  1121. m->pertag->curtag = m->pertag->prevtag = 1;
  1122. for (i = 0; i <= TAGCOUNT; i++) {
  1123. m->pertag->nmasters[i] = m->nmaster;
  1124. m->pertag->mfacts[i] = m->mfact;
  1125. m->pertag->ltidxs[i][0] = m->lt[0];
  1126. m->pertag->ltidxs[i][1] = m->lt[1];
  1127. m->pertag->sellts[i] = m->sellt;
  1128. }
  1129. /* The xdg-protocol specifies:
  1130. *
  1131. * If the fullscreened surface is not opaque, the compositor must make
  1132. * sure that other screen content not part of the same surface tree (made
  1133. * up of subsurfaces, popups or similarly coupled surfaces) are not
  1134. * visible below the fullscreened surface.
  1135. *
  1136. */
  1137. /* updatemons() will resize and set correct position */
  1138. m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg);
  1139. wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0);
  1140. /* Adds this to the output layout in the order it was configured.
  1141. *
  1142. * The output layout utility automatically adds a wl_output global to the
  1143. * display, which Wayland clients can see to find out information about the
  1144. * output (such as DPI, scale factor, manufacturer, etc).
  1145. */
  1146. m->scene_output = wlr_scene_output_create(scene, wlr_output);
  1147. if (m->m.x == -1 && m->m.y == -1)
  1148. wlr_output_layout_add_auto(output_layout, wlr_output);
  1149. else
  1150. wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
  1151. }
  1152. void
  1153. createnotify(struct wl_listener *listener, void *data)
  1154. {
  1155. /* This event is raised when a client creates a new toplevel (application window). */
  1156. struct wlr_xdg_toplevel *toplevel = data;
  1157. Client *c = NULL;
  1158. struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
  1159. /* Allocate a Client for this surface */
  1160. c = toplevel->base->data = ecalloc(1, sizeof(*c));
  1161. c->surface.xdg = toplevel->base;
  1162. c->bw = borderpx;
  1163. c->kblayout_idx = kb ? kb->modifiers.group : 0;
  1164. LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify);
  1165. LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify);
  1166. LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify);
  1167. LISTEN(&toplevel->events.destroy, &c->destroy, destroynotify);
  1168. LISTEN(&toplevel->events.request_fullscreen, &c->fullscreen, fullscreennotify);
  1169. LISTEN(&toplevel->events.request_maximize, &c->maximize, maximizenotify);
  1170. LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle);
  1171. }
  1172. void
  1173. createpointer(struct wlr_pointer *pointer)
  1174. {
  1175. struct libinput_device *device;
  1176. if (wlr_input_device_is_libinput(&pointer->base)
  1177. && (device = wlr_libinput_get_device_handle(&pointer->base))) {
  1178. if (libinput_device_config_tap_get_finger_count(device)) {
  1179. libinput_device_config_tap_set_enabled(device, tap_to_click);
  1180. libinput_device_config_tap_set_drag_enabled(device, tap_and_drag);
  1181. libinput_device_config_tap_set_drag_lock_enabled(device, drag_lock);
  1182. libinput_device_config_tap_set_button_map(device, button_map);
  1183. }
  1184. if (libinput_device_config_scroll_has_natural_scroll(device))
  1185. libinput_device_config_scroll_set_natural_scroll_enabled(device, natural_scrolling);
  1186. if (libinput_device_config_dwt_is_available(device))
  1187. libinput_device_config_dwt_set_enabled(device, disable_while_typing);
  1188. if (libinput_device_config_left_handed_is_available(device))
  1189. libinput_device_config_left_handed_set(device, left_handed);
  1190. if (libinput_device_config_middle_emulation_is_available(device))
  1191. libinput_device_config_middle_emulation_set_enabled(device, middle_button_emulation);
  1192. if (libinput_device_config_scroll_get_methods(device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
  1193. libinput_device_config_scroll_set_method (device, scroll_method);
  1194. if (libinput_device_config_click_get_methods(device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE)
  1195. libinput_device_config_click_set_method (device, click_method);
  1196. if (libinput_device_config_send_events_get_modes(device))
  1197. libinput_device_config_send_events_set_mode(device, send_events_mode);
  1198. if (libinput_device_config_accel_is_available(device)) {
  1199. libinput_device_config_accel_set_profile(device, accel_profile);
  1200. libinput_device_config_accel_set_speed(device, accel_speed);
  1201. }
  1202. }
  1203. wlr_cursor_attach_input_device(cursor, &pointer->base);
  1204. }
  1205. void
  1206. createpointerconstraint(struct wl_listener *listener, void *data)
  1207. {
  1208. PointerConstraint *pointer_constraint = ecalloc(1, sizeof(*pointer_constraint));
  1209. pointer_constraint->constraint = data;
  1210. LISTEN(&pointer_constraint->constraint->events.destroy,
  1211. &pointer_constraint->destroy, destroypointerconstraint);
  1212. }
  1213. void
  1214. createpopup(struct wl_listener *listener, void *data)
  1215. {
  1216. /* This event is raised when a client (either xdg-shell or layer-shell)
  1217. * creates a new popup. */
  1218. struct wlr_xdg_popup *popup = data;
  1219. LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
  1220. }
  1221. void
  1222. cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)
  1223. {
  1224. if (active_constraint == constraint)
  1225. return;
  1226. if (active_constraint)
  1227. wlr_pointer_constraint_v1_send_deactivated(active_constraint);
  1228. active_constraint = constraint;
  1229. wlr_pointer_constraint_v1_send_activated(constraint);
  1230. }
  1231. void
  1232. cursorframe(struct wl_listener *listener, void *data)
  1233. {
  1234. /* This event is forwarded by the cursor when a pointer emits an frame
  1235. * event. Frame events are sent after regular pointer events to group
  1236. * multiple events together. For instance, two axis events may happen at the
  1237. * same time, in which case a frame event won't be sent in between. */
  1238. /* Notify the client with pointer focus of the frame event. */
  1239. wlr_seat_pointer_notify_frame(seat);
  1240. }
  1241. void
  1242. cursorwarptohint(void)
  1243. {
  1244. Client *c = NULL;
  1245. double sx = active_constraint->current.cursor_hint.x;
  1246. double sy = active_constraint->current.cursor_hint.y;
  1247. toplevel_from_wlr_surface(active_constraint->surface, &c, NULL);
  1248. if (c && active_constraint->current.cursor_hint.enabled) {
  1249. wlr_cursor_warp(cursor, NULL, sx + c->geom.x + c->bw, sy + c->geom.y + c->bw);
  1250. wlr_seat_pointer_warp(active_constraint->seat, sx, sy);
  1251. }
  1252. }
  1253. void
  1254. destroydecoration(struct wl_listener *listener, void *data)
  1255. {
  1256. Client *c = wl_container_of(listener, c, destroy_decoration);
  1257. c->decoration = NULL;
  1258. wl_list_remove(&c->destroy_decoration.link);
  1259. wl_list_remove(&c->set_decoration_mode.link);
  1260. }
  1261. void
  1262. destroydragicon(struct wl_listener *listener, void *data)
  1263. {
  1264. /* Focus enter isn't sent during drag, so refocus the focused node. */
  1265. focusclient(focustop(selmon), 1);
  1266. motionnotify(0, NULL, 0, 0, 0, 0);
  1267. }
  1268. void
  1269. destroyidleinhibitor(struct wl_listener *listener, void *data)
  1270. {
  1271. /* `data` is the wlr_surface of the idle inhibitor being destroyed,
  1272. * at this point the idle inhibitor is still in the list of the manager */
  1273. checkidleinhibitor(wlr_surface_get_root_surface(data));
  1274. }
  1275. void
  1276. destroylayersurfacenotify(struct wl_listener *listener, void *data)
  1277. {
  1278. LayerSurface *l = wl_container_of(listener, l, destroy);
  1279. wl_list_remove(&l->link);
  1280. wl_list_remove(&l->destroy.link);
  1281. wl_list_remove(&l->unmap.link);
  1282. wl_list_remove(&l->surface_commit.link);
  1283. wlr_scene_node_destroy(&l->scene->node);
  1284. wlr_scene_node_destroy(&l->popups->node);
  1285. free(l);
  1286. }
  1287. void
  1288. destroylock(SessionLock *lock, int unlock)
  1289. {
  1290. wlr_seat_keyboard_notify_clear_focus(seat);
  1291. if ((locked = !unlock))
  1292. goto destroy;
  1293. wlr_scene_node_set_enabled(&locked_bg->node, 0);
  1294. focusclient(focustop(selmon), 0);
  1295. motionnotify(0, NULL, 0, 0, 0, 0);
  1296. destroy:
  1297. wl_list_remove(&lock->new_surface.link);
  1298. wl_list_remove(&lock->unlock.link);
  1299. wl_list_remove(&lock->destroy.link);
  1300. wlr_scene_node_destroy(&lock->scene->node);
  1301. cur_lock = NULL;
  1302. free(lock);
  1303. }
  1304. void
  1305. destroylocksurface(struct wl_listener *listener, void *data)
  1306. {
  1307. Monitor *m = wl_container_of(listener, m, destroy_lock_surface);
  1308. struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface;
  1309. m->lock_surface = NULL;
  1310. wl_list_remove(&m->destroy_lock_surface.link);
  1311. if (lock_surface->surface != seat->keyboard_state.focused_surface)
  1312. return;
  1313. if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) {
  1314. surface = wl_container_of(cur_lock->surfaces.next, surface, link);
  1315. client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat));
  1316. } else if (!locked) {
  1317. focusclient(focustop(selmon), 1);
  1318. } else {
  1319. wlr_seat_keyboard_clear_focus(seat);
  1320. }
  1321. }
  1322. void
  1323. destroynotify(struct wl_listener *listener, void *data)
  1324. {
  1325. /* Called when the xdg_toplevel is destroyed. */
  1326. Client *c = wl_container_of(listener, c, destroy);
  1327. wl_list_remove(&c->destroy.link);
  1328. wl_list_remove(&c->set_title.link);
  1329. wl_list_remove(&c->fullscreen.link);
  1330. #ifdef XWAYLAND
  1331. if (c->type != XDGShell) {
  1332. wl_list_remove(&c->activate.link);
  1333. wl_list_remove(&c->associate.link);
  1334. wl_list_remove(&c->configure.link);
  1335. wl_list_remove(&c->dissociate.link);
  1336. wl_list_remove(&c->set_hints.link);
  1337. } else
  1338. #endif
  1339. {
  1340. wl_list_remove(&c->commit.link);
  1341. wl_list_remove(&c->map.link);
  1342. wl_list_remove(&c->unmap.link);
  1343. }
  1344. free(c);
  1345. }
  1346. void
  1347. destroypointerconstraint(struct wl_listener *listener, void *data)
  1348. {
  1349. PointerConstraint *pointer_constraint = wl_container_of(listener, pointer_constraint, destroy);
  1350. if (active_constraint == pointer_constraint->constraint) {
  1351. cursorwarptohint();
  1352. active_constraint = NULL;
  1353. }
  1354. wl_list_remove(&pointer_constraint->destroy.link);
  1355. free(pointer_constraint);
  1356. }
  1357. void
  1358. destroysessionlock(struct wl_listener *listener, void *data)
  1359. {
  1360. SessionLock *lock = wl_container_of(listener, lock, destroy);
  1361. destroylock(lock, 0);
  1362. }
  1363. void
  1364. destroysessionmgr(struct wl_listener *listener, void *data)
  1365. {
  1366. wl_list_remove(&lock_listener.link);
  1367. wl_list_remove(&listener->link);
  1368. }
  1369. void
  1370. destroykeyboardgroup(struct wl_listener *listener, void *data)
  1371. {
  1372. KeyboardGroup *group = wl_container_of(listener, group, destroy);
  1373. wl_event_source_remove(group->key_repeat_source);
  1374. wlr_keyboard_group_destroy(group->wlr_group);
  1375. wl_list_remove(&group->key.link);
  1376. wl_list_remove(&group->modifiers.link);
  1377. wl_list_remove(&group->destroy.link);
  1378. free(group);
  1379. }
  1380. Monitor *
  1381. dirtomon(enum wlr_direction dir)
  1382. {
  1383. struct wlr_output *next;
  1384. if (!wlr_output_layout_get(output_layout, selmon->wlr_output))
  1385. return selmon;
  1386. if ((next = wlr_output_layout_adjacent_output(output_layout,
  1387. dir, selmon->wlr_output, selmon->m.x, selmon->m.y)))
  1388. return next->data;
  1389. if ((next = wlr_output_layout_farthest_output(output_layout,
  1390. dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT),
  1391. selmon->wlr_output, selmon->m.x, selmon->m.y)))
  1392. return next->data;
  1393. return selmon;
  1394. }
  1395. void
  1396. drawbar(Monitor *m)
  1397. {
  1398. int x, w, tw = 0;
  1399. int boxs = m->drw->font->height / 9;
  1400. int boxw = m->drw->font->height / 6 + 2;
  1401. uint32_t i, occ = 0, urg = 0;
  1402. Client *c;
  1403. Buffer *buf;
  1404. if (!m->scene_buffer->node.enabled)
  1405. return;
  1406. if (!(buf = bufmon(m)))
  1407. return;
  1408. /* draw status first so it can be overdrawn by tags later */
  1409. if (m == selmon) { /* status is only drawn on selected monitor */
  1410. drwl_setscheme(m->drw, colors[SchemeNorm]);
  1411. tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */
  1412. drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0);
  1413. }
  1414. wl_list_for_each(c, &clients, link) {
  1415. if (c->mon != m)
  1416. continue;
  1417. occ |= c->tags;
  1418. if (c->isurgent)
  1419. urg |= c->tags;
  1420. }
  1421. x = 0;
  1422. c = focustop(m);
  1423. for (i = 0; i < LENGTH(tags); i++) {
  1424. w = TEXTW(m, tags[i]);
  1425. drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
  1426. drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i);
  1427. if (occ & 1 << i)
  1428. drwl_rect(m->drw, x + boxs, boxs, boxw, boxw,
  1429. m == selmon && c && c->tags & 1 << i,
  1430. urg & 1 << i);
  1431. x += w;
  1432. }
  1433. w = TEXTW(m, m->ltsymbol);
  1434. drwl_setscheme(m->drw, colors[SchemeNorm]);
  1435. x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0);
  1436. if ((w = m->b.width - tw - x) > m->b.height) {
  1437. if (c) {
  1438. drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]);
  1439. drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0);
  1440. if (c && c->isfloating)
  1441. drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0);
  1442. } else {
  1443. drwl_setscheme(m->drw, colors[SchemeNorm]);
  1444. drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1);
  1445. }
  1446. }
  1447. wlr_scene_buffer_set_dest_size(m->scene_buffer,
  1448. m->b.real_width, m->b.real_height);
  1449. wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x,
  1450. m->m.y + (topbar ? 0 : m->m.height - m->b.real_height));
  1451. wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base);
  1452. wlr_buffer_unlock(&buf->base);
  1453. }
  1454. void
  1455. drawbars(void)
  1456. {
  1457. Monitor *m = NULL;
  1458. wl_list_for_each(m, &mons, link)
  1459. drawbar(m);
  1460. }
  1461. void
  1462. focusclient(Client *c, int lift)
  1463. {
  1464. /* Copied from wlroots/types/wlr_keyboard_group.c */
  1465. struct keyboard_group_device {
  1466. struct wlr_keyboard *keyboard;
  1467. struct wl_listener key;
  1468. struct wl_listener modifiers;
  1469. struct wl_listener keymap;
  1470. struct wl_listener repeat_info;
  1471. struct wl_listener destroy;
  1472. struct wl_list link; // wlr_keyboard_group.devices
  1473. };
  1474. struct wlr_surface *old = seat->keyboard_state.focused_surface;
  1475. int unused_lx, unused_ly, old_client_type;
  1476. Client *old_c = NULL;
  1477. LayerSurface *old_l = NULL;
  1478. struct keyboard_group_device *device;
  1479. struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat);
  1480. struct wlr_keyboard_group *group = kb ? wlr_keyboard_group_from_wlr_keyboard(kb) : NULL;
  1481. if (locked)
  1482. return;
  1483. /* Raise client in stacking order if requested */
  1484. if (c && lift)
  1485. wlr_scene_node_raise_to_top(&c->scene->node);
  1486. if (c && client_surface(c) == old)
  1487. return;
  1488. if ((old_client_type = toplevel_from_wlr_surface(old, &old_c, &old_l)) == XDGShell) {
  1489. struct wlr_xdg_popup *popup, *tmp;
  1490. wl_list_for_each_safe(popup, tmp, &old_c->surface.xdg->popups, link)
  1491. wlr_xdg_popup_destroy(popup);
  1492. }
  1493. /* Put the new client atop the focus stack and select its monitor */
  1494. if (c && !client_is_unmanaged(c)) {
  1495. wl_list_remove(&c->flink);
  1496. wl_list_insert(&fstack, &c->flink);
  1497. selmon = c->mon;
  1498. c->isurgent = 0;
  1499. client_restack_surface(c);
  1500. /* Don't change border color if there is an exclusive focus or we are
  1501. * handling a drag operation */
  1502. if (!exclusive_focus && !seat->drag)
  1503. client_set_border_color(c, (float[])COLOR(colors[SchemeSel][ColBorder]));
  1504. }
  1505. /* Deactivate old client if focus is changing */
  1506. if (old && (!c || client_surface(c) != old)) {
  1507. /* If an overlay is focused, don't focus or activate the client,
  1508. * but only update its position in fstack to render its border with its color
  1509. * and focus it after the overlay is closed. */
  1510. if (old_client_type == LayerShell && wlr_scene_node_coords(
  1511. &old_l->scene->node, &unused_lx, &unused_ly)
  1512. && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
  1513. return;
  1514. } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) {
  1515. return;
  1516. /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg
  1517. * and probably other clients */
  1518. } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
  1519. client_set_border_color(old_c, (float[])COLOR(colors[SchemeNorm][ColBorder]));
  1520. client_activate_surface(old, 0);
  1521. }
  1522. }
  1523. drawbars();
  1524. /* Update keyboard layout */
  1525. if (group) {
  1526. // Update the first real device, because kb or group->kb is not a real
  1527. // keyboard and its effective layout gets overwritten
  1528. device = wl_container_of(group->devices.next, device, link);
  1529. wlr_keyboard_notify_modifiers(device->keyboard,
  1530. device->keyboard->modifiers.depressed,
  1531. device->keyboard->modifiers.latched,
  1532. device->keyboard->modifiers.locked,
  1533. c ? c->kblayout_idx : 0
  1534. );
  1535. }
  1536. if (!c) {
  1537. /* With no client, all we have left is to clear focus */
  1538. wlr_seat_keyboard_notify_clear_focus(seat);
  1539. return;
  1540. }
  1541. /* Change cursor surface */
  1542. motionnotify(0, NULL, 0, 0, 0, 0);
  1543. /* Have a client, so focus its top-level wlr_surface */
  1544. client_notify_enter(client_surface(c), kb);
  1545. /* Activate the new client */
  1546. client_activate_surface(client_surface(c), 1);
  1547. }
  1548. void
  1549. focusmon(const Arg *arg)
  1550. {
  1551. int i = 0, nmons = wl_list_length(&mons);
  1552. if (nmons) {
  1553. do /* don't switch to disabled mons */
  1554. selmon = dirtomon(arg->i);
  1555. while (!selmon->wlr_output->enabled && i++ < nmons);
  1556. }
  1557. focusclient(focustop(selmon), 1);
  1558. }
  1559. void
  1560. focusstack(const Arg *arg)
  1561. {
  1562. /* Focus the next or previous client (in tiling order) on selmon */
  1563. Client *c, *sel = focustop(selmon);
  1564. if (!sel || (sel->isfullscreen && !client_has_children(sel)))
  1565. return;
  1566. if (arg->i > 0) {
  1567. wl_list_for_each(c, &sel->link, link) {
  1568. if (&c->link == &clients)
  1569. continue; /* wrap past the sentinel node */
  1570. if (VISIBLEON(c, selmon))
  1571. break; /* found it */
  1572. }
  1573. } else {
  1574. wl_list_for_each_reverse(c, &sel->link, link) {
  1575. if (&c->link == &clients)
  1576. continue; /* wrap past the sentinel node */
  1577. if (VISIBLEON(c, selmon))
  1578. break; /* found it */
  1579. }
  1580. }
  1581. /* If only one client is visible on selmon, then c == sel */
  1582. focusclient(c, 1);
  1583. }
  1584. /* We probably should change the name of this, it sounds like
  1585. * will focus the topmost client of this mon, when actually will
  1586. * only return that client */
  1587. Client *
  1588. focustop(Monitor *m)
  1589. {
  1590. Client *c;
  1591. wl_list_for_each(c, &fstack, flink) {
  1592. if (VISIBLEON(c, m))
  1593. return c;
  1594. }
  1595. return NULL;
  1596. }
  1597. void
  1598. fullscreennotify(struct wl_listener *listener, void *data)
  1599. {
  1600. Client *c = wl_container_of(listener, c, fullscreen);
  1601. setfullscreen(c, client_wants_fullscreen(c));
  1602. }
  1603. void
  1604. gpureset(struct wl_listener *listener, void *data)
  1605. {
  1606. struct wlr_renderer *old_drw = drw;
  1607. struct wlr_allocator *old_alloc = alloc;
  1608. struct Monitor *m;
  1609. if (!(drw = wlr_renderer_autocreate(backend)))
  1610. die("couldn't recreate renderer");
  1611. if (!(alloc = wlr_allocator_autocreate(backend, drw)))
  1612. die("couldn't recreate allocator");
  1613. LISTEN_STATIC(&drw->events.lost, gpureset);
  1614. wlr_compositor_set_renderer(compositor, drw);
  1615. wl_list_for_each(m, &mons, link) {
  1616. wlr_output_init_render(m->wlr_output, alloc, drw);
  1617. }
  1618. wlr_allocator_destroy(old_alloc);
  1619. wlr_renderer_destroy(old_drw);
  1620. }
  1621. void
  1622. handlesig(int signo)
  1623. {
  1624. if (signo == SIGCHLD) {
  1625. siginfo_t in;
  1626. /* wlroots expects to reap the XWayland process itself, so we
  1627. * use WNOWAIT to keep the child waitable until we know it's not
  1628. * XWayland.
  1629. */
  1630. while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
  1631. #ifdef XWAYLAND
  1632. && (!xwayland || in.si_pid != xwayland->server->pid)
  1633. #endif
  1634. ) {
  1635. pid_t *p, *lim;
  1636. waitpid(in.si_pid, NULL, 0);
  1637. if (in.si_pid == child_pid)
  1638. child_pid = -1;
  1639. if (!(p = autostart_pids))
  1640. continue;
  1641. lim = &p[autostart_len];
  1642. for (; p < lim; p++) {
  1643. if (*p == in.si_pid) {
  1644. *p = -1;
  1645. break;
  1646. }
  1647. }
  1648. }
  1649. } else if (signo == SIGINT || signo == SIGTERM) {
  1650. quit(NULL);
  1651. }
  1652. }
  1653. void
  1654. handlecursoractivity(void)
  1655. {
  1656. wl_event_source_timer_update(hide_source, cursor_timeout * 1000);
  1657. if (!cursor_hidden)
  1658. return;
  1659. cursor_hidden = false;
  1660. if (last_cursor.shape)
  1661. wlr_cursor_set_xcursor(cursor, cursor_mgr,
  1662. wlr_cursor_shape_v1_name(last_cursor.shape));
  1663. else
  1664. wlr_cursor_set_surface(cursor, last_cursor.surface,
  1665. last_cursor.hotspot_x, last_cursor.hotspot_y);
  1666. }
  1667. int
  1668. hidecursor(void *data)
  1669. {
  1670. wlr_cursor_unset_image(cursor);
  1671. cursor_hidden = true;
  1672. return 1;
  1673. }
  1674. void
  1675. incnmaster(const Arg *arg)
  1676. {
  1677. if (!arg || !selmon)
  1678. return;
  1679. selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
  1680. arrange(selmon);
  1681. }
  1682. void
  1683. inputdevice(struct wl_listener *listener, void *data)
  1684. {
  1685. /* This event is raised by the backend when a new input device becomes
  1686. * available. */
  1687. struct wlr_input_device *device = data;
  1688. uint32_t caps;
  1689. switch (device->type) {
  1690. case WLR_INPUT_DEVICE_KEYBOARD:
  1691. createkeyboard(wlr_keyboard_from_input_device(device));
  1692. break;
  1693. case WLR_INPUT_DEVICE_POINTER:
  1694. createpointer(wlr_pointer_from_input_device(device));
  1695. break;
  1696. default:
  1697. /* TODO handle other input device types */
  1698. break;
  1699. }
  1700. /* We need to let the wlr_seat know what our capabilities are, which is
  1701. * communiciated to the client. In dwl we always have a cursor, even if
  1702. * there are no pointer devices, so we always include that capability. */
  1703. /* TODO do we actually require a cursor? */
  1704. caps = WL_SEAT_CAPABILITY_POINTER;
  1705. if (!wl_list_empty(&kb_group->wlr_group->devices))
  1706. caps |= WL_SEAT_CAPABILITY_KEYBOARD;
  1707. wlr_seat_set_capabilities(seat, caps);
  1708. }
  1709. void
  1710. kblayout(KeyboardGroup *kb)
  1711. {
  1712. FILE *f;
  1713. Client *c;
  1714. unsigned int idx = kb->wlr_group->keyboard.modifiers.group;
  1715. // If layout did not change, do nothing
  1716. if (kblayout_idx == idx)
  1717. return;
  1718. kblayout_idx = idx;
  1719. // Update client layout
  1720. if ((c = focustop(selmon)))
  1721. c->kblayout_idx = kblayout_idx;
  1722. // Save current layout to kblayout_file
  1723. if (*kblayout_file && (f = fopen(kblayout_file, "w"))) {
  1724. fputs(xkb_keymap_layout_get_name(kb->wlr_group->keyboard.keymap,
  1725. idx), f);
  1726. fclose(f);
  1727. }
  1728. // Run kblayout_cmd
  1729. if (kblayout_cmd[0] && fork() == 0) {
  1730. execvp(kblayout_cmd[0], (char *const *)kblayout_cmd);
  1731. die("dwl: execvp %s failed:", kblayout_cmd[0]);
  1732. }
  1733. }
  1734. int
  1735. keybinding(uint32_t mods, xkb_keysym_t sym)
  1736. {
  1737. /*
  1738. * Here we handle compositor keybindings. This is when the compositor is
  1739. * processing keys, rather than passing them on to the client for its own
  1740. * processing.
  1741. */
  1742. const Key *k;
  1743. for (k = keys; k < END(keys); k++) {
  1744. if (CLEANMASK(mods) == CLEANMASK(k->mod)
  1745. && sym == k->keysym && k->func) {
  1746. k->func(&k->arg);
  1747. return 1;
  1748. }
  1749. }
  1750. return 0;
  1751. }
  1752. void
  1753. keypress(struct wl_listener *listener, void *data)
  1754. {
  1755. int i;
  1756. /* This event is raised when a key is pressed or released. */
  1757. KeyboardGroup *group = wl_container_of(listener, group, key);
  1758. struct wlr_keyboard_key_event *event = data;
  1759. /* Translate libinput keycode -> xkbcommon */
  1760. uint32_t keycode = event->keycode + 8;
  1761. /* Get a list of keysyms based on the keymap for this keyboard */
  1762. const xkb_keysym_t *syms;
  1763. int nsyms = xkb_state_key_get_syms(
  1764. group->wlr_group->keyboard.xkb_state, keycode, &syms);
  1765. int handled = 0;
  1766. uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
  1767. wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
  1768. /* On _press_ if there is no active screen locker,
  1769. * attempt to process a compositor keybinding. */
  1770. if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
  1771. for (i = 0; i < nsyms; i++)
  1772. handled = keybinding(mods, syms[i]) || handled;
  1773. }
  1774. if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) {
  1775. group->mods = mods;
  1776. group->keysyms = syms;
  1777. group->nsyms = nsyms;
  1778. wl_event_source_timer_update(group->key_repeat_source,
  1779. group->wlr_group->keyboard.repeat_info.delay);
  1780. } else {
  1781. group->nsyms = 0;
  1782. wl_event_source_timer_update(group->key_repeat_source, 0);
  1783. }
  1784. if (handled)
  1785. return;
  1786. wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
  1787. /* Pass unhandled keycodes along to the client. */
  1788. wlr_seat_keyboard_notify_key(seat, event->time_msec,
  1789. event->keycode, event->state);
  1790. }
  1791. void
  1792. keypressmod(struct wl_listener *listener, void *data)
  1793. {
  1794. /* This event is raised when a modifier key, such as shift or alt, is
  1795. * pressed. We simply communicate this to the client. */
  1796. KeyboardGroup *group = wl_container_of(listener, group, modifiers);
  1797. wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
  1798. /* Send modifiers to the client. */
  1799. wlr_seat_keyboard_notify_modifiers(seat,
  1800. &group->wlr_group->keyboard.modifiers);
  1801. kblayout(group);
  1802. }
  1803. int
  1804. keyrepeat(void *data)
  1805. {
  1806. KeyboardGroup *group = data;
  1807. int i;
  1808. if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0)
  1809. return 0;
  1810. wl_event_source_timer_update(group->key_repeat_source,
  1811. 1000 / group->wlr_group->keyboard.repeat_info.rate);
  1812. for (i = 0; i < group->nsyms; i++)
  1813. keybinding(group->mods, group->keysyms[i]);
  1814. return 0;
  1815. }
  1816. void
  1817. killclient(const Arg *arg)
  1818. {
  1819. Client *sel = focustop(selmon);
  1820. if (sel)
  1821. client_send_close(sel);
  1822. }
  1823. void
  1824. locksession(struct wl_listener *listener, void *data)
  1825. {
  1826. struct wlr_session_lock_v1 *session_lock = data;
  1827. SessionLock *lock;
  1828. wlr_scene_node_set_enabled(&locked_bg->node, 1);
  1829. if (cur_lock) {
  1830. wlr_session_lock_v1_destroy(session_lock);
  1831. return;
  1832. }
  1833. lock = session_lock->data = ecalloc(1, sizeof(*lock));
  1834. focusclient(NULL, 0);
  1835. lock->scene = wlr_scene_tree_create(layers[LyrBlock]);
  1836. cur_lock = lock->lock = session_lock;
  1837. locked = 1;
  1838. LISTEN(&session_lock->events.new_surface, &lock->new_surface, createlocksurface);
  1839. LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock);
  1840. LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession);
  1841. wlr_session_lock_v1_send_locked(session_lock);
  1842. }
  1843. void
  1844. mapnotify(struct wl_listener *listener, void *data)
  1845. {
  1846. /* Called when the surface is mapped, or ready to display on-screen. */
  1847. Client *p = NULL;
  1848. Client *w, *c = wl_container_of(listener, c, map);
  1849. Monitor *m;
  1850. int i;
  1851. /* Create scene tree for this client and its border */
  1852. c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]);
  1853. wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell);
  1854. c->scene_surface = c->type == XDGShell
  1855. ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg)
  1856. : wlr_scene_subsurface_tree_create(c->scene, client_surface(c));
  1857. c->scene->node.data = c->scene_surface->node.data = c;
  1858. client_get_geometry(c, &c->geom);
  1859. /* Handle unmanaged clients first so we can return prior create borders */
  1860. if (client_is_unmanaged(c)) {
  1861. /* Unmanaged clients always are floating */
  1862. wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]);
  1863. wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
  1864. if (client_wants_focus(c)) {
  1865. focusclient(c, 1);
  1866. exclusive_focus = c;
  1867. }
  1868. goto unset_fullscreen;
  1869. }
  1870. for (i = 0; i < 4; i++) {
  1871. c->border[i] = wlr_scene_rect_create(c->scene, 0, 0,
  1872. (float[])COLOR(colors[c->isurgent ? SchemeUrg : SchemeNorm][ColBorder]));
  1873. c->border[i]->node.data = c;
  1874. }
  1875. /* Initialize client geometry with room for border */
  1876. client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
  1877. c->geom.width += 2 * c->bw;
  1878. c->geom.height += 2 * c->bw;
  1879. /* Insert this client into client lists. */
  1880. wl_list_insert(&clients, &c->link);
  1881. wl_list_insert(&fstack, &c->flink);
  1882. /* Set initial monitor, tags, floating status, and focus:
  1883. * we always consider floating, clients that have parent and thus
  1884. * we set the same tags and monitor than its parent, if not
  1885. * try to apply rules for them */
  1886. if ((p = client_get_parent(c))) {
  1887. c->isfloating = 1;
  1888. if (p->mon) {
  1889. c->geom.x = (p->mon->w.width - c->geom.width) / 2 + p->mon->m.x;
  1890. c->geom.y = (p->mon->w.height - c->geom.height) / 2 + p->mon->m.y;
  1891. }
  1892. setmon(c, p->mon, p->tags);
  1893. } else {
  1894. applyrules(c);
  1895. }
  1896. drawbars();
  1897. unset_fullscreen:
  1898. m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
  1899. wl_list_for_each(w, &clients, link) {
  1900. if (w != c && w != p && w->isfullscreen && m == w->mon && (w->tags & c->tags))
  1901. setfullscreen(w, 0);
  1902. }
  1903. }
  1904. void
  1905. maximizenotify(struct wl_listener *listener, void *data)
  1906. {
  1907. /* This event is raised when a client would like to maximize itself,
  1908. * typically because the user clicked on the maximize button on
  1909. * client-side decorations. dwl doesn't support maximization, but
  1910. * to conform to xdg-shell protocol we still must send a configure.
  1911. * Since xdg-shell protocol v5 we should ignore request of unsupported
  1912. * capabilities, just schedule a empty configure when the client uses <5
  1913. * protocol version
  1914. * wlr_xdg_surface_schedule_configure() is used to send an empty reply. */
  1915. Client *c = wl_container_of(listener, c, maximize);
  1916. if (c->surface.xdg->initialized
  1917. && wl_resource_get_version(c->surface.xdg->toplevel->resource)
  1918. < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
  1919. wlr_xdg_surface_schedule_configure(c->surface.xdg);
  1920. }
  1921. void
  1922. monocle(Monitor *m)
  1923. {
  1924. Client *c;
  1925. int n = 0;
  1926. wl_list_for_each(c, &clients, link) {
  1927. if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
  1928. continue;
  1929. resize(c, m->w, 0);
  1930. n++;
  1931. }
  1932. if (n)
  1933. snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n);
  1934. if ((c = focustop(m)))
  1935. wlr_scene_node_raise_to_top(&c->scene->node);
  1936. }
  1937. void
  1938. movestack(const Arg *arg)
  1939. {
  1940. Client *c, *sel = focustop(selmon);
  1941. if (!sel) {
  1942. return;
  1943. }
  1944. if (wl_list_length(&clients) <= 1) {
  1945. return;
  1946. }
  1947. if (arg->i > 0) {
  1948. wl_list_for_each(c, &sel->link, link) {
  1949. if (VISIBLEON(c, selmon) || &c->link == &clients) {
  1950. break; /* found it */
  1951. }
  1952. }
  1953. } else {
  1954. wl_list_for_each_reverse(c, &sel->link, link) {
  1955. if (VISIBLEON(c, selmon) || &c->link == &clients) {
  1956. break; /* found it */
  1957. }
  1958. }
  1959. /* backup one client */
  1960. c = wl_container_of(c->link.prev, c, link);
  1961. }
  1962. wl_list_remove(&sel->link);
  1963. wl_list_insert(&c->link, &sel->link);
  1964. arrange(selmon);
  1965. }
  1966. void
  1967. motionabsolute(struct wl_listener *listener, void *data)
  1968. {
  1969. /* This event is forwarded by the cursor when a pointer emits an _absolute_
  1970. * motion event, from 0..1 on each axis. This happens, for example, when
  1971. * wlroots is running under a Wayland window rather than KMS+DRM, and you
  1972. * move the mouse over the window. You could enter the window from any edge,
  1973. * so we have to warp the mouse there. There is also some hardware which
  1974. * emits these events. */
  1975. struct wlr_pointer_motion_absolute_event *event = data;
  1976. double lx, ly, dx, dy;
  1977. if (!event->time_msec) /* this is 0 with virtual pointers */
  1978. wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y);
  1979. wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly);
  1980. dx = lx - cursor->x;
  1981. dy = ly - cursor->y;
  1982. motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy);
  1983. }
  1984. void
  1985. motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
  1986. double dx_unaccel, double dy_unaccel)
  1987. {
  1988. double sx = 0, sy = 0, sx_confined, sy_confined;
  1989. Client *c = NULL, *w = NULL;
  1990. LayerSurface *l = NULL;
  1991. struct wlr_surface *surface = NULL;
  1992. struct wlr_pointer_constraint_v1 *constraint;
  1993. /* Find the client under the pointer and send the event along. */
  1994. xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
  1995. if (cursor_mode == CurPressed && !seat->drag
  1996. && surface != seat->pointer_state.focused_surface
  1997. && toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) {
  1998. c = w;
  1999. surface = seat->pointer_state.focused_surface;
  2000. sx = cursor->x - (l ? l->geom.x : w->geom.x);
  2001. sy = cursor->y - (l ? l->geom.y : w->geom.y);
  2002. }
  2003. /* time is 0 in internal calls meant to restore pointer focus. */
  2004. if (time) {
  2005. wlr_relative_pointer_manager_v1_send_relative_motion(
  2006. relative_pointer_mgr, seat, (uint64_t)time * 1000,
  2007. dx, dy, dx_unaccel, dy_unaccel);
  2008. wl_list_for_each(constraint, &pointer_constraints->constraints, link)
  2009. cursorconstrain(constraint);
  2010. if (active_constraint && cursor_mode != CurResize && cursor_mode != CurMove) {
  2011. toplevel_from_wlr_surface(active_constraint->surface, &c, NULL);
  2012. if (c && active_constraint->surface == seat->pointer_state.focused_surface) {
  2013. sx = cursor->x - c->geom.x - c->bw;
  2014. sy = cursor->y - c->geom.y - c->bw;
  2015. if (wlr_region_confine(&active_constraint->region, sx, sy,
  2016. sx + dx, sy + dy, &sx_confined, &sy_confined)) {
  2017. dx = sx_confined - sx;
  2018. dy = sy_confined - sy;
  2019. }
  2020. if (active_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED)
  2021. return;
  2022. }
  2023. }
  2024. wlr_cursor_move(cursor, device, dx, dy);
  2025. wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
  2026. handlecursoractivity();
  2027. /* Update selmon (even while dragging a window) */
  2028. if (sloppyfocus)
  2029. selmon = xytomon(cursor->x, cursor->y);
  2030. }
  2031. /* Update drag icon's position */
  2032. wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
  2033. /* If we are currently grabbing the mouse, handle and return */
  2034. if (cursor_mode == CurMove) {
  2035. /* Move the grabbed client to the new position. */
  2036. resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy,
  2037. .width = grabc->geom.width, .height = grabc->geom.height}, 1);
  2038. return;
  2039. } else if (cursor_mode == CurResize) {
  2040. resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
  2041. .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
  2042. return;
  2043. }
  2044. /* If there's no client surface under the cursor, set the cursor image to a
  2045. * default. This is what makes the cursor image appear when you move it
  2046. * off of a client or over its border. */
  2047. if (!surface && !seat->drag && !cursor_hidden)
  2048. wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
  2049. pointerfocus(c, surface, sx, sy, time);
  2050. }
  2051. void
  2052. motionrelative(struct wl_listener *listener, void *data)
  2053. {
  2054. /* This event is forwarded by the cursor when a pointer emits a _relative_
  2055. * pointer motion event (i.e. a delta) */
  2056. struct wlr_pointer_motion_event *event = data;
  2057. /* The cursor doesn't move unless we tell it to. The cursor automatically
  2058. * handles constraining the motion to the output layout, as well as any
  2059. * special configuration applied for the specific input device which
  2060. * generated the event. You can pass NULL for the device if you want to move
  2061. * the cursor around without any input. */
  2062. motionnotify(event->time_msec, &event->pointer->base, event->delta_x, event->delta_y,
  2063. event->unaccel_dx, event->unaccel_dy);
  2064. }
  2065. void
  2066. moveresize(const Arg *arg)
  2067. {
  2068. if (cursor_mode != CurNormal && cursor_mode != CurPressed)
  2069. return;
  2070. xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
  2071. if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
  2072. return;
  2073. /* Float the window and tell motionnotify to grab it */
  2074. setfloating(grabc, 1);
  2075. switch (cursor_mode = arg->ui) {
  2076. case CurMove:
  2077. grabcx = (int)round(cursor->x) - grabc->geom.x;
  2078. grabcy = (int)round(cursor->y) - grabc->geom.y;
  2079. wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
  2080. break;
  2081. case CurResize:
  2082. /* Doesn't work for X11 output - the next absolute motion event
  2083. * returns the cursor to where it started */
  2084. wlr_cursor_warp_closest(cursor, NULL,
  2085. grabc->geom.x + grabc->geom.width,
  2086. grabc->geom.y + grabc->geom.height);
  2087. wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
  2088. break;
  2089. }
  2090. }
  2091. unsigned int
  2092. nextocctag(int direction)
  2093. {
  2094. unsigned int seltag = selmon->tagset[selmon->seltags];
  2095. unsigned int occ = 0, i;
  2096. Client *c;
  2097. wl_list_for_each(c, &clients, link)
  2098. occ |= c->tags;
  2099. for (i=0; i<TAGCOUNT; i++) {
  2100. seltag = (direction > 0) ?
  2101. (seltag == (1u << (TAGCOUNT - 1)) ? 1u : seltag << 1) :
  2102. (seltag == 1 ? (1u << (TAGCOUNT - 1)) : seltag >> 1);
  2103. if (seltag & occ)
  2104. break;
  2105. }
  2106. return seltag & TAGMASK;
  2107. }
  2108. void
  2109. outputmgrapply(struct wl_listener *listener, void *data)
  2110. {
  2111. struct wlr_output_configuration_v1 *config = data;
  2112. outputmgrapplyortest(config, 0);
  2113. }
  2114. void
  2115. outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
  2116. {
  2117. /*
  2118. * Called when a client such as wlr-randr requests a change in output
  2119. * configuration. This is only one way that the layout can be changed,
  2120. * so any Monitor information should be updated by updatemons() after an
  2121. * output_layout.change event, not here.
  2122. */
  2123. struct wlr_output_configuration_head_v1 *config_head;
  2124. int ok = 1;
  2125. wl_list_for_each(config_head, &config->heads, link) {
  2126. struct wlr_output *wlr_output = config_head->state.output;
  2127. Monitor *m = wlr_output->data;
  2128. struct wlr_output_state state;
  2129. /* Ensure displays previously disabled by wlr-output-power-management-v1
  2130. * are properly handled*/
  2131. m->asleep = 0;
  2132. wlr_output_state_init(&state);
  2133. wlr_output_state_set_enabled(&state, config_head->state.enabled);
  2134. if (!config_head->state.enabled)
  2135. goto apply_or_test;
  2136. if (config_head->state.mode)
  2137. wlr_output_state_set_mode(&state, config_head->state.mode);
  2138. else
  2139. wlr_output_state_set_custom_mode(&state,
  2140. config_head->state.custom_mode.width,
  2141. config_head->state.custom_mode.height,
  2142. config_head->state.custom_mode.refresh);
  2143. wlr_output_state_set_transform(&state, config_head->state.transform);
  2144. wlr_output_state_set_scale(&state, config_head->state.scale);
  2145. wlr_output_state_set_adaptive_sync_enabled(&state,
  2146. config_head->state.adaptive_sync_enabled);
  2147. apply_or_test:
  2148. ok &= test ? wlr_output_test_state(wlr_output, &state)
  2149. : wlr_output_commit_state(wlr_output, &state);
  2150. /* Don't move monitors if position wouldn't change, this to avoid
  2151. * wlroots marking the output as manually configured.
  2152. * wlr_output_layout_add does not like disabled outputs */
  2153. if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y))
  2154. wlr_output_layout_add(output_layout, wlr_output,
  2155. config_head->state.x, config_head->state.y);
  2156. wlr_output_state_finish(&state);
  2157. }
  2158. if (ok)
  2159. wlr_output_configuration_v1_send_succeeded(config);
  2160. else
  2161. wlr_output_configuration_v1_send_failed(config);
  2162. wlr_output_configuration_v1_destroy(config);
  2163. /* https://codeberg.org/dwl/dwl/issues/577 */
  2164. updatemons(NULL, NULL);
  2165. }
  2166. void
  2167. outputmgrtest(struct wl_listener *listener, void *data)
  2168. {
  2169. struct wlr_output_configuration_v1 *config = data;
  2170. outputmgrapplyortest(config, 1);
  2171. }
  2172. void
  2173. pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
  2174. uint32_t time)
  2175. {
  2176. struct timespec now;
  2177. if (surface != seat->pointer_state.focused_surface &&
  2178. sloppyfocus && time && c && !client_is_unmanaged(c))
  2179. focusclient(c, 0);
  2180. /* If surface is NULL, clear pointer focus */
  2181. if (!surface) {
  2182. wlr_seat_pointer_notify_clear_focus(seat);
  2183. return;
  2184. }
  2185. if (!time) {
  2186. clock_gettime(CLOCK_MONOTONIC, &now);
  2187. time = now.tv_sec * 1000 + now.tv_nsec / 1000000;
  2188. }
  2189. /* Let the client know that the mouse cursor has entered one
  2190. * of its surfaces, and make keyboard focus follow if desired.
  2191. * wlroots makes this a no-op if surface is already focused */
  2192. wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
  2193. wlr_seat_pointer_notify_motion(seat, time, sx, sy);
  2194. }
  2195. void
  2196. powermgrsetmode(struct wl_listener *listener, void *data)
  2197. {
  2198. struct wlr_output_power_v1_set_mode_event *event = data;
  2199. struct wlr_output_state state = {0};
  2200. Monitor *m = event->output->data;
  2201. if (!m)
  2202. return;
  2203. m->gamma_lut_changed = 1; /* Reapply gamma LUT when re-enabling the ouput */
  2204. wlr_output_state_set_enabled(&state, event->mode);
  2205. wlr_output_commit_state(m->wlr_output, &state);
  2206. m->asleep = !event->mode;
  2207. }
  2208. void
  2209. quit(const Arg *arg)
  2210. {
  2211. wl_display_terminate(dpy);
  2212. }
  2213. void
  2214. rendermon(struct wl_listener *listener, void *data)
  2215. {
  2216. /* This function is called every time an output is ready to display a frame,
  2217. * generally at the output's refresh rate (e.g. 60Hz). */
  2218. Monitor *m = wl_container_of(listener, m, frame);
  2219. Client *c;
  2220. struct wlr_output_state pending = {0};
  2221. struct wlr_gamma_control_v1 *gamma_control;
  2222. struct timespec now;
  2223. /* Render if no XDG clients have an outstanding resize and are visible on
  2224. * this monitor. */
  2225. wl_list_for_each(c, &clients, link) {
  2226. if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
  2227. goto skip;
  2228. }
  2229. /*
  2230. * HACK: The "correct" way to set the gamma is to commit it together with
  2231. * the rest of the state in one go, but to do that we would need to rewrite
  2232. * wlr_scene_output_commit() in order to add the gamma to the pending
  2233. * state before committing, instead try to commit the gamma in one frame,
  2234. * and commit the rest of the state in the next one (or in the same frame if
  2235. * the gamma can not be committed).
  2236. */
  2237. if (m->gamma_lut_changed) {
  2238. gamma_control
  2239. = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output);
  2240. m->gamma_lut_changed = 0;
  2241. if (!wlr_gamma_control_v1_apply(gamma_control, &pending))
  2242. goto commit;
  2243. if (!wlr_output_test_state(m->wlr_output, &pending)) {
  2244. wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
  2245. goto commit;
  2246. }
  2247. wlr_output_commit_state(m->wlr_output, &pending);
  2248. wlr_output_schedule_frame(m->wlr_output);
  2249. } else {
  2250. commit:
  2251. wlr_scene_output_commit(m->scene_output, NULL);
  2252. }
  2253. skip:
  2254. /* Let clients know a frame has been rendered */
  2255. clock_gettime(CLOCK_MONOTONIC, &now);
  2256. wlr_scene_output_send_frame_done(m->scene_output, &now);
  2257. wlr_output_state_finish(&pending);
  2258. }
  2259. void
  2260. requestdecorationmode(struct wl_listener *listener, void *data)
  2261. {
  2262. Client *c = wl_container_of(listener, c, set_decoration_mode);
  2263. if (c->surface.xdg->initialized)
  2264. wlr_xdg_toplevel_decoration_v1_set_mode(c->decoration,
  2265. WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
  2266. }
  2267. void
  2268. requeststartdrag(struct wl_listener *listener, void *data)
  2269. {
  2270. struct wlr_seat_request_start_drag_event *event = data;
  2271. if (wlr_seat_validate_pointer_grab_serial(seat, event->origin,
  2272. event->serial))
  2273. wlr_seat_start_pointer_drag(seat, event->drag, event->serial);
  2274. else
  2275. wlr_data_source_destroy(event->drag->source);
  2276. }
  2277. void
  2278. requestmonstate(struct wl_listener *listener, void *data)
  2279. {
  2280. struct wlr_output_event_request_state *event = data;
  2281. wlr_output_commit_state(event->output, event->state);
  2282. updatemons(NULL, NULL);
  2283. }
  2284. void
  2285. resize(Client *c, struct wlr_box geo, int interact)
  2286. {
  2287. struct wlr_box *bbox;
  2288. struct wlr_box clip;
  2289. if (!c->mon || !client_surface(c)->mapped)
  2290. return;
  2291. bbox = interact ? &sgeom : &c->mon->w;
  2292. client_set_bounds(c, geo.width, geo.height);
  2293. c->geom = geo;
  2294. applybounds(c, bbox);
  2295. /* Update scene-graph, including borders */
  2296. wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
  2297. wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
  2298. wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
  2299. wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw);
  2300. wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw);
  2301. wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw);
  2302. wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
  2303. wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
  2304. wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
  2305. /* this is a no-op if size hasn't changed */
  2306. c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
  2307. c->geom.height - 2 * c->bw);
  2308. client_get_clip(c, &clip);
  2309. wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
  2310. }
  2311. void
  2312. run(char *startup_cmd)
  2313. {
  2314. /* Add a Unix socket to the Wayland display. */
  2315. const char *socket = wl_display_add_socket_auto(dpy);
  2316. if (!socket)
  2317. die("startup: display_add_socket_auto");
  2318. setenv("WAYLAND_DISPLAY", socket, 1);
  2319. /* Start the backend. This will enumerate outputs and inputs, become the DRM
  2320. * master, etc */
  2321. if (!wlr_backend_start(backend))
  2322. die("startup: backend_start");
  2323. /* Now that the socket exists and the backend is started, run the startup command */
  2324. autostartexec();
  2325. if (startup_cmd) {
  2326. if ((child_pid = fork()) < 0)
  2327. die("startup: fork:");
  2328. if (child_pid == 0) {
  2329. close(STDIN_FILENO);
  2330. setsid();
  2331. execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL);
  2332. die("startup: execl:");
  2333. }
  2334. }
  2335. drawbars();
  2336. /* At this point the outputs are initialized, choose initial selmon based on
  2337. * cursor position, and set default cursor image */
  2338. selmon = xytomon(cursor->x, cursor->y);
  2339. /* TODO hack to get cursor to display in its initial location (100, 100)
  2340. * instead of (0, 0) and then jumping. still may not be fully
  2341. * initialized, as the image/coordinates are not transformed for the
  2342. * monitor when displayed here */
  2343. wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y);
  2344. wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
  2345. handlecursoractivity();
  2346. /* Run the Wayland event loop. This does not return until you exit the
  2347. * compositor. Starting the backend rigged up all of the necessary event
  2348. * loop configuration to listen to libinput events, DRM events, generate
  2349. * frame events at the refresh rate, and so on. */
  2350. wl_display_run(dpy);
  2351. }
  2352. void
  2353. setcursor(struct wl_listener *listener, void *data)
  2354. {
  2355. /* This event is raised by the seat when a client provides a cursor image */
  2356. struct wlr_seat_pointer_request_set_cursor_event *event = data;
  2357. /* If we're "grabbing" the cursor, don't use the client's image, we will
  2358. * restore it after "grabbing" sending a leave event, followed by a enter
  2359. * event, which will result in the client requesting set the cursor surface */
  2360. if (cursor_mode != CurNormal && cursor_mode != CurPressed)
  2361. return;
  2362. /* This can be sent by any client, so we check to make sure this one is
  2363. * actually has pointer focus first. If so, we can tell the cursor to
  2364. * use the provided surface as the cursor image. It will set the
  2365. * hardware cursor on the output that it's currently on and continue to
  2366. * do so as the cursor moves between outputs. */
  2367. if (event->seat_client == seat->pointer_state.focused_client) {
  2368. last_cursor.shape = 0;
  2369. last_cursor.surface = event->surface;
  2370. last_cursor.hotspot_x = event->hotspot_x;
  2371. last_cursor.hotspot_y = event->hotspot_y;
  2372. if (!cursor_hidden)
  2373. wlr_cursor_set_surface(cursor, event->surface,
  2374. event->hotspot_x, event->hotspot_y);
  2375. }
  2376. }
  2377. void
  2378. setcursorshape(struct wl_listener *listener, void *data)
  2379. {
  2380. struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
  2381. if (cursor_mode != CurNormal && cursor_mode != CurPressed)
  2382. return;
  2383. /* This can be sent by any client, so we check to make sure this one is
  2384. * actually has pointer focus first. If so, we can tell the cursor to
  2385. * use the provided cursor shape. */
  2386. if (event->seat_client == seat->pointer_state.focused_client) {
  2387. last_cursor.shape = event->shape;
  2388. last_cursor.surface = NULL;
  2389. if (!cursor_hidden)
  2390. wlr_cursor_set_xcursor(cursor, cursor_mgr,
  2391. wlr_cursor_shape_v1_name(event->shape));
  2392. }
  2393. }
  2394. void
  2395. setfloating(Client *c, int floating)
  2396. {
  2397. Client *p = client_get_parent(c);
  2398. c->isfloating = floating;
  2399. /* If in floating layout do not change the client's layer */
  2400. if (!c->mon || !client_surface(c)->mapped || !c->mon->lt[c->mon->sellt]->arrange)
  2401. return;
  2402. wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
  2403. (p && p->isfullscreen) ? LyrFS
  2404. : c->isfloating ? LyrFloat : LyrTile]);
  2405. arrange(c->mon);
  2406. drawbars();
  2407. }
  2408. void
  2409. setfullscreen(Client *c, int fullscreen)
  2410. {
  2411. c->isfullscreen = fullscreen;
  2412. if (!c->mon || !client_surface(c)->mapped)
  2413. return;
  2414. c->bw = fullscreen ? 0 : borderpx;
  2415. client_set_fullscreen(c, fullscreen);
  2416. wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen
  2417. ? LyrFS : c->isfloating ? LyrFloat : LyrTile]);
  2418. if (fullscreen) {
  2419. c->prev = c->geom;
  2420. resize(c, c->mon->m, 0);
  2421. } else {
  2422. /* restore previous size instead of arrange for floating windows since
  2423. * client positions are set by the user and cannot be recalculated */
  2424. resize(c, c->prev, 0);
  2425. }
  2426. arrange(c->mon);
  2427. drawbars();
  2428. }
  2429. void
  2430. setgamma(struct wl_listener *listener, void *data)
  2431. {
  2432. struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
  2433. Monitor *m = event->output->data;
  2434. if (!m)
  2435. return;
  2436. m->gamma_lut_changed = 1;
  2437. wlr_output_schedule_frame(m->wlr_output);
  2438. }
  2439. void
  2440. setsticky(Client *c, int sticky)
  2441. {
  2442. if(sticky && !c->issticky) {
  2443. c->issticky = 1;
  2444. } else if(!sticky && c->issticky) {
  2445. c->issticky = 0;
  2446. arrange(c->mon);
  2447. }
  2448. }
  2449. void
  2450. setlayout(const Arg *arg)
  2451. {
  2452. if (!selmon)
  2453. return;
  2454. if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
  2455. selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
  2456. if (arg && arg->v)
  2457. selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
  2458. strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol));
  2459. arrange(selmon);
  2460. drawbar(selmon);
  2461. }
  2462. /* arg > 1.0 will set mfact absolutely */
  2463. void
  2464. setmfact(const Arg *arg)
  2465. {
  2466. float f;
  2467. if (!arg || !selmon || !selmon->lt[selmon->sellt]->arrange)
  2468. return;
  2469. f = arg->f < 1.0f ? arg->f + selmon->mfact : arg->f - 1.0f;
  2470. if (f < 0.1 || f > 0.9)
  2471. return;
  2472. selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
  2473. arrange(selmon);
  2474. }
  2475. void
  2476. setmon(Client *c, Monitor *m, uint32_t newtags)
  2477. {
  2478. Monitor *oldmon = c->mon;
  2479. if (oldmon == m)
  2480. return;
  2481. c->mon = m;
  2482. c->prev = c->geom;
  2483. /* Scene graph sends surface leave/enter events on move and resize */
  2484. if (oldmon)
  2485. arrange(oldmon);
  2486. if (m) {
  2487. /* Make sure window actually overlaps with the monitor */
  2488. resize(c, c->geom, 0);
  2489. c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
  2490. setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */
  2491. setfloating(c, c->isfloating);
  2492. }
  2493. focusclient(focustop(selmon), 1);
  2494. }
  2495. void
  2496. setpsel(struct wl_listener *listener, void *data)
  2497. {
  2498. /* This event is raised by the seat when a client wants to set the selection,
  2499. * usually when the user copies something. wlroots allows compositors to
  2500. * ignore such requests if they so choose, but in dwl we always honor
  2501. */
  2502. struct wlr_seat_request_set_primary_selection_event *event = data;
  2503. wlr_seat_set_primary_selection(seat, event->source, event->serial);
  2504. }
  2505. void
  2506. setsel(struct wl_listener *listener, void *data)
  2507. {
  2508. /* This event is raised by the seat when a client wants to set the selection,
  2509. * usually when the user copies something. wlroots allows compositors to
  2510. * ignore such requests if they so choose, but in dwl we always honor
  2511. */
  2512. struct wlr_seat_request_set_selection_event *event = data;
  2513. wlr_seat_set_selection(seat, event->source, event->serial);
  2514. }
  2515. void
  2516. setup(void)
  2517. {
  2518. int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE};
  2519. struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig};
  2520. sigemptyset(&sa.sa_mask);
  2521. for (i = 0; i < (int)LENGTH(sig); i++)
  2522. sigaction(sig[i], &sa, NULL);
  2523. wlr_log_init(log_level, NULL);
  2524. /* The Wayland display is managed by libwayland. It handles accepting
  2525. * clients from the Unix socket, manging Wayland globals, and so on. */
  2526. dpy = wl_display_create();
  2527. event_loop = wl_display_get_event_loop(dpy);
  2528. /* The backend is a wlroots feature which abstracts the underlying input and
  2529. * output hardware. The autocreate option will choose the most suitable
  2530. * backend based on the current environment, such as opening an X11 window
  2531. * if an X11 server is running. */
  2532. if (!(backend = wlr_backend_autocreate(event_loop, &session)))
  2533. die("couldn't create backend");
  2534. /* Initialize the scene graph used to lay out windows */
  2535. scene = wlr_scene_create();
  2536. root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor);
  2537. for (i = 0; i < NUM_LAYERS; i++)
  2538. layers[i] = wlr_scene_tree_create(&scene->tree);
  2539. drag_icon = wlr_scene_tree_create(&scene->tree);
  2540. wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node);
  2541. /* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user
  2542. * can also specify a renderer using the WLR_RENDERER env var.
  2543. * The renderer is responsible for defining the various pixel formats it
  2544. * supports for shared memory, this configures that for clients. */
  2545. if (!(drw = wlr_renderer_autocreate(backend)))
  2546. die("couldn't create renderer");
  2547. LISTEN_STATIC(&drw->events.lost, gpureset);
  2548. /* Create shm, drm and linux_dmabuf interfaces by ourselves.
  2549. * The simplest way is call:
  2550. * wlr_renderer_init_wl_display(drw);
  2551. * but we need to create manually the linux_dmabuf interface to integrate it
  2552. * with wlr_scene. */
  2553. wlr_renderer_init_wl_shm(drw, dpy);
  2554. if (wlr_renderer_get_texture_formats(drw, WLR_BUFFER_CAP_DMABUF)) {
  2555. wlr_drm_create(dpy, drw);
  2556. wlr_scene_set_linux_dmabuf_v1(scene,
  2557. wlr_linux_dmabuf_v1_create_with_renderer(dpy, 5, drw));
  2558. }
  2559. /* Autocreates an allocator for us.
  2560. * The allocator is the bridge between the renderer and the backend. It
  2561. * handles the buffer creation, allowing wlroots to render onto the
  2562. * screen */
  2563. if (!(alloc = wlr_allocator_autocreate(backend, drw)))
  2564. die("couldn't create allocator");
  2565. /* This creates some hands-off wlroots interfaces. The compositor is
  2566. * necessary for clients to allocate surfaces and the data device manager
  2567. * handles the clipboard. Each of these wlroots interfaces has room for you
  2568. * to dig your fingers in and play with their behavior if you want. Note that
  2569. * the clients cannot set the selection directly without compositor approval,
  2570. * see the setsel() function. */
  2571. compositor = wlr_compositor_create(dpy, 6, drw);
  2572. wlr_subcompositor_create(dpy);
  2573. wlr_data_device_manager_create(dpy);
  2574. wlr_export_dmabuf_manager_v1_create(dpy);
  2575. wlr_screencopy_manager_v1_create(dpy);
  2576. wlr_data_control_manager_v1_create(dpy);
  2577. wlr_primary_selection_v1_device_manager_create(dpy);
  2578. wlr_viewporter_create(dpy);
  2579. wlr_single_pixel_buffer_manager_v1_create(dpy);
  2580. wlr_fractional_scale_manager_v1_create(dpy, 1);
  2581. wlr_presentation_create(dpy, backend);
  2582. wlr_alpha_modifier_v1_create(dpy);
  2583. /* Initializes the interface used to implement urgency hints */
  2584. activation = wlr_xdg_activation_v1_create(dpy);
  2585. LISTEN_STATIC(&activation->events.request_activate, urgent);
  2586. gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy);
  2587. LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma);
  2588. power_mgr = wlr_output_power_manager_v1_create(dpy);
  2589. LISTEN_STATIC(&power_mgr->events.set_mode, powermgrsetmode);
  2590. /* Creates an output layout, which a wlroots utility for working with an
  2591. * arrangement of screens in a physical layout. */
  2592. output_layout = wlr_output_layout_create(dpy);
  2593. LISTEN_STATIC(&output_layout->events.change, updatemons);
  2594. wlr_xdg_output_manager_v1_create(dpy, output_layout);
  2595. /* Configure a listener to be notified when new outputs are available on the
  2596. * backend. */
  2597. wl_list_init(&mons);
  2598. LISTEN_STATIC(&backend->events.new_output, createmon);
  2599. /* Set up our client lists, the xdg-shell and the layer-shell. The xdg-shell is a
  2600. * Wayland protocol which is used for application windows. For more
  2601. * detail on shells, refer to the article:
  2602. *
  2603. * https://drewdevault.com/2018/07/29/Wayland-shells.html
  2604. */
  2605. wl_list_init(&clients);
  2606. wl_list_init(&fstack);
  2607. xdg_shell = wlr_xdg_shell_create(dpy, 6);
  2608. LISTEN_STATIC(&xdg_shell->events.new_toplevel, createnotify);
  2609. LISTEN_STATIC(&xdg_shell->events.new_popup, createpopup);
  2610. layer_shell = wlr_layer_shell_v1_create(dpy, 3);
  2611. LISTEN_STATIC(&layer_shell->events.new_surface, createlayersurface);
  2612. idle_notifier = wlr_idle_notifier_v1_create(dpy);
  2613. idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy);
  2614. LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor);
  2615. session_lock_mgr = wlr_session_lock_manager_v1_create(dpy);
  2616. wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener);
  2617. LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr);
  2618. locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height,
  2619. (float [4]){0.1f, 0.1f, 0.1f, 1.0f});
  2620. wlr_scene_node_set_enabled(&locked_bg->node, 0);
  2621. /* Use decoration protocols to negotiate server-side decorations */
  2622. wlr_server_decoration_manager_set_default_mode(
  2623. wlr_server_decoration_manager_create(dpy),
  2624. WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
  2625. xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy);
  2626. LISTEN_STATIC(&xdg_decoration_mgr->events.new_toplevel_decoration, createdecoration);
  2627. pointer_constraints = wlr_pointer_constraints_v1_create(dpy);
  2628. LISTEN_STATIC(&pointer_constraints->events.new_constraint, createpointerconstraint);
  2629. relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy);
  2630. /*
  2631. * Creates a cursor, which is a wlroots utility for tracking the cursor
  2632. * image shown on screen.
  2633. */
  2634. cursor = wlr_cursor_create();
  2635. wlr_cursor_attach_output_layout(cursor, output_layout);
  2636. /* Creates an xcursor manager, another wlroots utility which loads up
  2637. * Xcursor themes to source cursor images from and makes sure that cursor
  2638. * images are available at all scale factors on the screen (necessary for
  2639. * HiDPI support). Scaled cursors will be loaded with each output. */
  2640. cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
  2641. setenv("XCURSOR_SIZE", "24", 1);
  2642. /*
  2643. * wlr_cursor *only* displays an image on screen. It does not move around
  2644. * when the pointer moves. However, we can attach input devices to it, and
  2645. * it will generate aggregate events for all of them. In these events, we
  2646. * can choose how we want to process them, forwarding them to clients and
  2647. * moving the cursor around. More detail on this process is described in
  2648. * https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html
  2649. *
  2650. * And more comments are sprinkled throughout the notify functions above.
  2651. */
  2652. LISTEN_STATIC(&cursor->events.motion, motionrelative);
  2653. LISTEN_STATIC(&cursor->events.motion_absolute, motionabsolute);
  2654. LISTEN_STATIC(&cursor->events.button, buttonpress);
  2655. LISTEN_STATIC(&cursor->events.axis, axisnotify);
  2656. LISTEN_STATIC(&cursor->events.frame, cursorframe);
  2657. cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1);
  2658. LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape);
  2659. hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy),
  2660. hidecursor, cursor);
  2661. /*
  2662. * Configures a seat, which is a single "seat" at which a user sits and
  2663. * operates the computer. This conceptually includes up to one keyboard,
  2664. * pointer, touch, and drawing tablet device. We also rig up a listener to
  2665. * let us know when new input devices are available on the backend.
  2666. */
  2667. LISTEN_STATIC(&backend->events.new_input, inputdevice);
  2668. virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy);
  2669. LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard);
  2670. virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(dpy);
  2671. LISTEN_STATIC(&virtual_pointer_mgr->events.new_virtual_pointer, virtualpointer);
  2672. seat = wlr_seat_create(dpy, "seat0");
  2673. LISTEN_STATIC(&seat->events.request_set_cursor, setcursor);
  2674. LISTEN_STATIC(&seat->events.request_set_selection, setsel);
  2675. LISTEN_STATIC(&seat->events.request_set_primary_selection, setpsel);
  2676. LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag);
  2677. LISTEN_STATIC(&seat->events.start_drag, startdrag);
  2678. kb_group = createkeyboardgroup();
  2679. wl_list_init(&kb_group->destroy.link);
  2680. output_mgr = wlr_output_manager_v1_create(dpy);
  2681. LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);
  2682. LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);
  2683. drwl_init();
  2684. status_event_source = wl_event_loop_add_fd(wl_display_get_event_loop(dpy),
  2685. STDIN_FILENO, WL_EVENT_READABLE, statusin, NULL);
  2686. /* Make sure XWayland clients don't connect to the parent X server,
  2687. * e.g when running in the x11 backend or the wayland backend and the
  2688. * compositor has Xwayland support */
  2689. unsetenv("DISPLAY");
  2690. #ifdef XWAYLAND
  2691. /*
  2692. * Initialise the XWayland X server.
  2693. * It will be started when the first X client is started.
  2694. */
  2695. if ((xwayland = wlr_xwayland_create(dpy, compositor, 1))) {
  2696. LISTEN_STATIC(&xwayland->events.ready, xwaylandready);
  2697. LISTEN_STATIC(&xwayland->events.new_surface, createnotifyx11);
  2698. setenv("DISPLAY", xwayland->display_name, 1);
  2699. } else {
  2700. fprintf(stderr, "failed to setup XWayland X server, continuing without it\n");
  2701. }
  2702. #endif
  2703. }
  2704. void
  2705. spawn(const Arg *arg)
  2706. {
  2707. if (fork() == 0) {
  2708. close(STDIN_FILENO);
  2709. dup2(STDERR_FILENO, STDOUT_FILENO);
  2710. setsid();
  2711. execvp(((char **)arg->v)[0], (char **)arg->v);
  2712. die("dwl: execvp %s failed:", ((char **)arg->v)[0]);
  2713. }
  2714. }
  2715. void
  2716. startdrag(struct wl_listener *listener, void *data)
  2717. {
  2718. struct wlr_drag *drag = data;
  2719. if (!drag->icon)
  2720. return;
  2721. drag->icon->data = &wlr_scene_drag_icon_create(drag_icon, drag->icon)->node;
  2722. LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon);
  2723. }
  2724. int
  2725. statusin(int fd, unsigned int mask, void *data)
  2726. {
  2727. char status[1024];
  2728. ssize_t n;
  2729. if (mask & WL_EVENT_ERROR)
  2730. die("status in event error");
  2731. if (mask & WL_EVENT_HANGUP)
  2732. wl_event_source_remove(status_event_source);
  2733. n = read(fd, status, sizeof(status) - 1);
  2734. if (n < 0 && errno != EWOULDBLOCK)
  2735. die("read:");
  2736. status[n] = '\0';
  2737. status[strcspn(status, "\n")] = '\0';
  2738. strncpy(stext, status, sizeof(stext));
  2739. drawbars();
  2740. return 0;
  2741. }
  2742. void
  2743. tag(const Arg *arg)
  2744. {
  2745. Client *sel = focustop(selmon);
  2746. if (!sel || (arg->ui & TAGMASK) == 0)
  2747. return;
  2748. sel->tags = arg->ui & TAGMASK;
  2749. focusclient(focustop(selmon), 1);
  2750. arrange(selmon);
  2751. drawbars();
  2752. }
  2753. void
  2754. tagmon(const Arg *arg)
  2755. {
  2756. Client *sel = focustop(selmon);
  2757. if (sel)
  2758. setmon(sel, dirtomon(arg->i), 0);
  2759. }
  2760. void
  2761. tile(Monitor *m)
  2762. {
  2763. unsigned int mw, my, ty;
  2764. int i, n = 0;
  2765. Client *c;
  2766. wl_list_for_each(c, &clients, link)
  2767. if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
  2768. n++;
  2769. if (n == 0)
  2770. return;
  2771. if (n > m->nmaster)
  2772. mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0;
  2773. else
  2774. mw = m->w.width;
  2775. i = my = ty = 0;
  2776. wl_list_for_each(c, &clients, link) {
  2777. if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
  2778. continue;
  2779. if (i < m->nmaster) {
  2780. resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
  2781. .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
  2782. my += c->geom.height;
  2783. } else {
  2784. resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
  2785. .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
  2786. ty += c->geom.height;
  2787. }
  2788. i++;
  2789. }
  2790. }
  2791. void
  2792. togglebar(const Arg *arg)
  2793. {
  2794. wlr_scene_node_set_enabled(&selmon->scene_buffer->node,
  2795. !selmon->scene_buffer->node.enabled);
  2796. arrangelayers(selmon);
  2797. }
  2798. void
  2799. togglefloating(const Arg *arg)
  2800. {
  2801. Client *sel = focustop(selmon);
  2802. /* return if fullscreen */
  2803. if (sel && !sel->isfullscreen)
  2804. setfloating(sel, !sel->isfloating);
  2805. }
  2806. void
  2807. togglefullscreen(const Arg *arg)
  2808. {
  2809. Client *sel = focustop(selmon);
  2810. if (sel)
  2811. setfullscreen(sel, !sel->isfullscreen);
  2812. }
  2813. void
  2814. togglesticky(const Arg *arg)
  2815. {
  2816. Client *c = focustop(selmon);
  2817. if(!c)
  2818. return;
  2819. setsticky(c, !c->issticky);
  2820. }
  2821. void
  2822. toggletag(const Arg *arg)
  2823. {
  2824. uint32_t newtags;
  2825. Client *sel = focustop(selmon);
  2826. if (!sel || !(newtags = sel->tags ^ (arg->ui & TAGMASK)))
  2827. return;
  2828. sel->tags = newtags;
  2829. focusclient(focustop(selmon), 1);
  2830. arrange(selmon);
  2831. drawbars();
  2832. }
  2833. void
  2834. toggleview(const Arg *arg)
  2835. {
  2836. uint32_t newtagset;
  2837. size_t i;
  2838. if (!(newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0))
  2839. return;
  2840. if (newtagset == (uint32_t)~0) {
  2841. selmon->pertag->prevtag = selmon->pertag->curtag;
  2842. selmon->pertag->curtag = 0;
  2843. }
  2844. /* test if the user did not select the same tag */
  2845. if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
  2846. selmon->pertag->prevtag = selmon->pertag->curtag;
  2847. for (i = 0; !(newtagset & 1 << i); i++) ;
  2848. selmon->pertag->curtag = i + 1;
  2849. }
  2850. /* apply settings for this view */
  2851. selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
  2852. selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
  2853. selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
  2854. selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
  2855. selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
  2856. selmon->tagset[selmon->seltags] = newtagset;
  2857. focusclient(focustop(selmon), 1);
  2858. arrange(selmon);
  2859. drawbars();
  2860. }
  2861. void
  2862. unlocksession(struct wl_listener *listener, void *data)
  2863. {
  2864. SessionLock *lock = wl_container_of(listener, lock, unlock);
  2865. destroylock(lock, 1);
  2866. }
  2867. void
  2868. unmaplayersurfacenotify(struct wl_listener *listener, void *data)
  2869. {
  2870. LayerSurface *l = wl_container_of(listener, l, unmap);
  2871. l->mapped = 0;
  2872. wlr_scene_node_set_enabled(&l->scene->node, 0);
  2873. if (l == exclusive_focus)
  2874. exclusive_focus = NULL;
  2875. if (l->layer_surface->output && (l->mon = l->layer_surface->output->data))
  2876. arrangelayers(l->mon);
  2877. if (l->layer_surface->surface == seat->keyboard_state.focused_surface)
  2878. focusclient(focustop(selmon), 1);
  2879. motionnotify(0, NULL, 0, 0, 0, 0);
  2880. }
  2881. void
  2882. unmapnotify(struct wl_listener *listener, void *data)
  2883. {
  2884. /* Called when the surface is unmapped, and should no longer be shown. */
  2885. Client *c = wl_container_of(listener, c, unmap);
  2886. if (c == grabc) {
  2887. cursor_mode = CurNormal;
  2888. grabc = NULL;
  2889. }
  2890. if (client_is_unmanaged(c)) {
  2891. if (c == exclusive_focus) {
  2892. exclusive_focus = NULL;
  2893. focusclient(focustop(selmon), 1);
  2894. }
  2895. } else {
  2896. wl_list_remove(&c->link);
  2897. setmon(c, NULL, 0);
  2898. wl_list_remove(&c->flink);
  2899. }
  2900. wlr_scene_node_destroy(&c->scene->node);
  2901. drawbars();
  2902. motionnotify(0, NULL, 0, 0, 0, 0);
  2903. }
  2904. void
  2905. updatemons(struct wl_listener *listener, void *data)
  2906. {
  2907. /*
  2908. * Called whenever the output layout changes: adding or removing a
  2909. * monitor, changing an output's mode or position, etc. This is where
  2910. * the change officially happens and we update geometry, window
  2911. * positions, focus, and the stored configuration in wlroots'
  2912. * output-manager implementation.
  2913. */
  2914. struct wlr_output_configuration_v1 *config
  2915. = wlr_output_configuration_v1_create();
  2916. Client *c;
  2917. struct wlr_output_configuration_head_v1 *config_head;
  2918. Monitor *m;
  2919. /* First remove from the layout the disabled monitors */
  2920. wl_list_for_each(m, &mons, link) {
  2921. if (m->wlr_output->enabled || m->asleep)
  2922. continue;
  2923. config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
  2924. config_head->state.enabled = 0;
  2925. /* Remove this output from the layout to avoid cursor enter inside it */
  2926. wlr_output_layout_remove(output_layout, m->wlr_output);
  2927. closemon(m);
  2928. m->m = m->w = (struct wlr_box){0};
  2929. }
  2930. /* Insert outputs that need to */
  2931. wl_list_for_each(m, &mons, link) {
  2932. if (m->wlr_output->enabled
  2933. && !wlr_output_layout_get(output_layout, m->wlr_output))
  2934. wlr_output_layout_add_auto(output_layout, m->wlr_output);
  2935. }
  2936. /* Now that we update the output layout we can get its box */
  2937. wlr_output_layout_get_box(output_layout, NULL, &sgeom);
  2938. wlr_scene_node_set_position(&root_bg->node, sgeom.x, sgeom.y);
  2939. wlr_scene_rect_set_size(root_bg, sgeom.width, sgeom.height);
  2940. /* Make sure the clients are hidden when dwl is locked */
  2941. wlr_scene_node_set_position(&locked_bg->node, sgeom.x, sgeom.y);
  2942. wlr_scene_rect_set_size(locked_bg, sgeom.width, sgeom.height);
  2943. wl_list_for_each(m, &mons, link) {
  2944. if (!m->wlr_output->enabled)
  2945. continue;
  2946. config_head = wlr_output_configuration_head_v1_create(config, m->wlr_output);
  2947. /* Get the effective monitor geometry to use for surfaces */
  2948. wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m);
  2949. m->w = m->m;
  2950. wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y);
  2951. wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y);
  2952. wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height);
  2953. if (m->lock_surface) {
  2954. struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data;
  2955. wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y);
  2956. wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, m->m.height);
  2957. }
  2958. /* Calculate the effective monitor geometry to use for clients */
  2959. arrangelayers(m);
  2960. /* Don't move clients to the left output when plugging monitors */
  2961. arrange(m);
  2962. /* make sure fullscreen clients have the right size */
  2963. if ((c = focustop(m)) && c->isfullscreen)
  2964. resize(c, m->m, 0);
  2965. /* Try to re-set the gamma LUT when updating monitors,
  2966. * it's only really needed when enabling a disabled output, but meh. */
  2967. m->gamma_lut_changed = 1;
  2968. config_head->state.x = m->m.x;
  2969. config_head->state.y = m->m.y;
  2970. if (!selmon) {
  2971. selmon = m;
  2972. }
  2973. }
  2974. if (selmon && selmon->wlr_output->enabled) {
  2975. wl_list_for_each(c, &clients, link) {
  2976. if (!c->mon && client_surface(c)->mapped)
  2977. setmon(c, selmon, c->tags);
  2978. }
  2979. focusclient(focustop(selmon), 1);
  2980. if (selmon->lock_surface) {
  2981. client_notify_enter(selmon->lock_surface->surface,
  2982. wlr_seat_get_keyboard(seat));
  2983. client_activate_surface(selmon->lock_surface->surface, 1);
  2984. }
  2985. }
  2986. if (stext[0] == '\0')
  2987. strncpy(stext, "dwl-"VERSION, sizeof(stext));
  2988. wl_list_for_each(m, &mons, link) {
  2989. updatebar(m);
  2990. drawbar(m);
  2991. }
  2992. /* FIXME: figure out why the cursor image is at 0,0 after turning all
  2993. * the monitors on.
  2994. * Move the cursor image where it used to be. It does not generate a
  2995. * wl_pointer.motion event for the clients, it's only the image what it's
  2996. * at the wrong position after all. */
  2997. wlr_cursor_move(cursor, NULL, 0, 0);
  2998. wlr_output_manager_v1_set_configuration(output_mgr, config);
  2999. }
  3000. void
  3001. updatebar(Monitor *m)
  3002. {
  3003. size_t i;
  3004. int rw, rh;
  3005. char fontattrs[12];
  3006. wlr_output_transformed_resolution(m->wlr_output, &rw, &rh);
  3007. m->b.width = rw;
  3008. m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale);
  3009. wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0);
  3010. for (i = 0; i < LENGTH(m->pool); i++)
  3011. if (m->pool[i]) {
  3012. wlr_buffer_drop(&m->pool[i]->base);
  3013. m->pool[i] = NULL;
  3014. }
  3015. if (m->b.scale == m->wlr_output->scale && m->drw)
  3016. return;
  3017. drwl_font_destroy(m->drw->font);
  3018. snprintf(fontattrs, sizeof(fontattrs), "dpi=%.2f", 96. * m->wlr_output->scale);
  3019. if (!(drwl_font_create(m->drw, LENGTH(fonts), fonts, fontattrs)))
  3020. die("Could not load font");
  3021. m->b.scale = m->wlr_output->scale;
  3022. m->lrpad = m->drw->font->height;
  3023. m->b.height = m->drw->font->height + 2;
  3024. m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale);
  3025. }
  3026. void
  3027. updatetitle(struct wl_listener *listener, void *data)
  3028. {
  3029. Client *c = wl_container_of(listener, c, set_title);
  3030. if (c == focustop(c->mon))
  3031. drawbars();
  3032. }
  3033. void
  3034. urgent(struct wl_listener *listener, void *data)
  3035. {
  3036. struct wlr_xdg_activation_v1_request_activate_event *event = data;
  3037. Client *c = NULL;
  3038. toplevel_from_wlr_surface(event->surface, &c, NULL);
  3039. if (!c || c == focustop(selmon))
  3040. return;
  3041. c->isurgent = 1;
  3042. drawbars();
  3043. if (client_surface(c)->mapped)
  3044. client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder]));
  3045. }
  3046. void
  3047. view(const Arg *arg)
  3048. {
  3049. size_t i, tmptag;
  3050. if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
  3051. return;
  3052. selmon->seltags ^= 1; /* toggle sel tagset */
  3053. if (arg->ui & ~0) {
  3054. selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
  3055. selmon->pertag->prevtag = selmon->pertag->curtag;
  3056. if (arg->ui == TAGMASK)
  3057. selmon->pertag->curtag = 0;
  3058. else {
  3059. for (i = 0; !(arg->ui & 1 << i); i++) ;
  3060. selmon->pertag->curtag = i + 1;
  3061. }
  3062. } else {
  3063. tmptag = selmon->pertag->prevtag;
  3064. selmon->pertag->prevtag = selmon->pertag->curtag;
  3065. selmon->pertag->curtag = tmptag;
  3066. }
  3067. selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
  3068. selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
  3069. selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
  3070. selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
  3071. selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
  3072. focusclient(focustop(selmon), 1);
  3073. arrange(selmon);
  3074. drawbars();
  3075. }
  3076. void
  3077. viewnextocctag(const Arg *arg)
  3078. {
  3079. unsigned int tmp;
  3080. if ((tmp = nextocctag(arg->i)) == selmon->tagset[selmon->seltags])
  3081. return;
  3082. view(&(const Arg){.ui = tmp});
  3083. }
  3084. void
  3085. virtualkeyboard(struct wl_listener *listener, void *data)
  3086. {
  3087. struct wlr_virtual_keyboard_v1 *kb = data;
  3088. /* virtual keyboards shouldn't share keyboard group */
  3089. KeyboardGroup *group = createkeyboardgroup();
  3090. /* Set the keymap to match the group keymap */
  3091. wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap);
  3092. LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, destroykeyboardgroup);
  3093. /* Add the new keyboard to the group */
  3094. wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard);
  3095. }
  3096. void
  3097. virtualpointer(struct wl_listener *listener, void *data)
  3098. {
  3099. struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
  3100. struct wlr_input_device *device = &event->new_pointer->pointer.base;
  3101. wlr_cursor_attach_input_device(cursor, device);
  3102. if (event->suggested_output)
  3103. wlr_cursor_map_input_to_output(cursor, device, event->suggested_output);
  3104. handlecursoractivity();
  3105. }
  3106. Monitor *
  3107. xytomon(double x, double y)
  3108. {
  3109. struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
  3110. return o ? o->data : NULL;
  3111. }
  3112. void
  3113. xytonode(double x, double y, struct wlr_surface **psurface,
  3114. Client **pc, LayerSurface **pl, double *nx, double *ny)
  3115. {
  3116. struct wlr_scene_node *node, *pnode;
  3117. struct wlr_surface *surface = NULL;
  3118. struct wlr_scene_surface *scene_surface = NULL;
  3119. Client *c = NULL;
  3120. LayerSurface *l = NULL;
  3121. int layer;
  3122. for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
  3123. if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
  3124. continue;
  3125. if (node->type == WLR_SCENE_NODE_BUFFER) {
  3126. scene_surface = wlr_scene_surface_try_from_buffer(
  3127. wlr_scene_buffer_from_node(node));
  3128. if (!scene_surface) continue;
  3129. surface = scene_surface->surface;
  3130. }
  3131. /* Walk the tree to find a node that knows the client */
  3132. for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
  3133. c = pnode->data;
  3134. if (c && c->type == LayerShell) {
  3135. c = NULL;
  3136. l = pnode->data;
  3137. }
  3138. }
  3139. if (psurface) *psurface = surface;
  3140. if (pc) *pc = c;
  3141. if (pl) *pl = l;
  3142. }
  3143. void
  3144. zoom(const Arg *arg)
  3145. {
  3146. Client *c, *sel = focustop(selmon);
  3147. if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating)
  3148. return;
  3149. /* Search for the first tiled window that is not sel, marking sel as
  3150. * NULL if we pass it along the way */
  3151. wl_list_for_each(c, &clients, link) {
  3152. if (VISIBLEON(c, selmon) && !c->isfloating) {
  3153. if (c != sel)
  3154. break;
  3155. sel = NULL;
  3156. }
  3157. }
  3158. /* Return if no other tiled window was found */
  3159. if (&c->link == &clients)
  3160. return;
  3161. /* If we passed sel, move c to the front; otherwise, move sel to the
  3162. * front */
  3163. if (!sel)
  3164. sel = c;
  3165. wl_list_remove(&sel->link);
  3166. wl_list_insert(&clients, &sel->link);
  3167. focusclient(sel, 1);
  3168. arrange(selmon);
  3169. }
  3170. #ifdef XWAYLAND
  3171. void
  3172. activatex11(struct wl_listener *listener, void *data)
  3173. {
  3174. Client *c = wl_container_of(listener, c, activate);
  3175. /* Only "managed" windows can be activated */
  3176. if (!client_is_unmanaged(c))
  3177. wlr_xwayland_surface_activate(c->surface.xwayland, 1);
  3178. }
  3179. void
  3180. associatex11(struct wl_listener *listener, void *data)
  3181. {
  3182. Client *c = wl_container_of(listener, c, associate);
  3183. LISTEN(&client_surface(c)->events.map, &c->map, mapnotify);
  3184. LISTEN(&client_surface(c)->events.unmap, &c->unmap, unmapnotify);
  3185. }
  3186. void
  3187. configurex11(struct wl_listener *listener, void *data)
  3188. {
  3189. Client *c = wl_container_of(listener, c, configure);
  3190. struct wlr_xwayland_surface_configure_event *event = data;
  3191. /* TODO: figure out if there is another way to do this */
  3192. if (!c->mon) {
  3193. wlr_xwayland_surface_configure(c->surface.xwayland,
  3194. event->x, event->y, event->width, event->height);
  3195. return;
  3196. }
  3197. if (c->isfloating || client_is_unmanaged(c))
  3198. resize(c, (struct wlr_box){.x = event->x, .y = event->y,
  3199. .width = event->width + c->bw * 2, .height = event->height + c->bw * 2}, 0);
  3200. else
  3201. arrange(c->mon);
  3202. }
  3203. void
  3204. createnotifyx11(struct wl_listener *listener, void *data)
  3205. {
  3206. struct wlr_xwayland_surface *xsurface = data;
  3207. Client *c;
  3208. /* Allocate a Client for this surface */
  3209. c = xsurface->data = ecalloc(1, sizeof(*c));
  3210. c->surface.xwayland = xsurface;
  3211. c->type = X11;
  3212. c->bw = client_is_unmanaged(c) ? 0 : borderpx;
  3213. /* Listen to the various events it can emit */
  3214. LISTEN(&xsurface->events.associate, &c->associate, associatex11);
  3215. LISTEN(&xsurface->events.destroy, &c->destroy, destroynotify);
  3216. LISTEN(&xsurface->events.dissociate, &c->dissociate, dissociatex11);
  3217. LISTEN(&xsurface->events.request_activate, &c->activate, activatex11);
  3218. LISTEN(&xsurface->events.request_configure, &c->configure, configurex11);
  3219. LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify);
  3220. LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints);
  3221. LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle);
  3222. }
  3223. void
  3224. dissociatex11(struct wl_listener *listener, void *data)
  3225. {
  3226. Client *c = wl_container_of(listener, c, dissociate);
  3227. wl_list_remove(&c->map.link);
  3228. wl_list_remove(&c->unmap.link);
  3229. }
  3230. xcb_atom_t
  3231. getatom(xcb_connection_t *xc, const char *name)
  3232. {
  3233. xcb_atom_t atom = 0;
  3234. xcb_intern_atom_reply_t *reply;
  3235. xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xc, 0, strlen(name), name);
  3236. if ((reply = xcb_intern_atom_reply(xc, cookie, NULL)))
  3237. atom = reply->atom;
  3238. free(reply);
  3239. return atom;
  3240. }
  3241. void
  3242. sethints(struct wl_listener *listener, void *data)
  3243. {
  3244. Client *c = wl_container_of(listener, c, set_hints);
  3245. struct wlr_surface *surface = client_surface(c);
  3246. if (c == focustop(selmon))
  3247. return;
  3248. c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints);
  3249. drawbars();
  3250. if (c->isurgent && surface && surface->mapped)
  3251. client_set_border_color(c, (float[])COLOR(colors[SchemeUrg][ColBorder]));
  3252. }
  3253. void
  3254. xwaylandready(struct wl_listener *listener, void *data)
  3255. {
  3256. struct wlr_xcursor *xcursor;
  3257. xcb_connection_t *xc = xcb_connect(xwayland->display_name, NULL);
  3258. int err = xcb_connection_has_error(xc);
  3259. if (err) {
  3260. fprintf(stderr, "xcb_connect to X server failed with code %d\n. Continuing with degraded functionality.\n", err);
  3261. return;
  3262. }
  3263. /* Collect atoms we are interested in. If getatom returns 0, we will
  3264. * not detect that window type. */
  3265. netatom[NetWMWindowTypeDialog] = getatom(xc, "_NET_WM_WINDOW_TYPE_DIALOG");
  3266. netatom[NetWMWindowTypeSplash] = getatom(xc, "_NET_WM_WINDOW_TYPE_SPLASH");
  3267. netatom[NetWMWindowTypeToolbar] = getatom(xc, "_NET_WM_WINDOW_TYPE_TOOLBAR");
  3268. netatom[NetWMWindowTypeUtility] = getatom(xc, "_NET_WM_WINDOW_TYPE_UTILITY");
  3269. /* assign the one and only seat */
  3270. wlr_xwayland_set_seat(xwayland, seat);
  3271. /* Set the default XWayland cursor to match the rest of dwl. */
  3272. if ((xcursor = wlr_xcursor_manager_get_xcursor(cursor_mgr, "default", 1)))
  3273. wlr_xwayland_set_cursor(xwayland,
  3274. xcursor->images[0]->buffer, xcursor->images[0]->width * 4,
  3275. xcursor->images[0]->width, xcursor->images[0]->height,
  3276. xcursor->images[0]->hotspot_x, xcursor->images[0]->hotspot_y);
  3277. xcb_disconnect(xc);
  3278. }
  3279. #endif
  3280. int
  3281. main(int argc, char *argv[])
  3282. {
  3283. char *startup_cmd = NULL;
  3284. int c;
  3285. while ((c = getopt(argc, argv, "s:hdv")) != -1) {
  3286. if (c == 's')
  3287. startup_cmd = optarg;
  3288. else if (c == 'd')
  3289. log_level = WLR_DEBUG;
  3290. else if (c == 'v')
  3291. die("dwl " VERSION);
  3292. else
  3293. goto usage;
  3294. }
  3295. if (optind < argc)
  3296. goto usage;
  3297. /* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */
  3298. if (!getenv("XDG_RUNTIME_DIR"))
  3299. die("XDG_RUNTIME_DIR must be set");
  3300. setup();
  3301. run(startup_cmd);
  3302. cleanup();
  3303. return EXIT_SUCCESS;
  3304. usage:
  3305. die("Usage: %s [-v] [-d] [-s startup command]", argv[0]);
  3306. }
  3307. static void
  3308. bstack(Monitor *m)
  3309. {
  3310. int w, h, mh, mx, tx, ty, tw;
  3311. int i, n = 0;
  3312. Client *c;
  3313. wl_list_for_each(c, &clients, link)
  3314. if (VISIBLEON(c, m) && !c->isfloating)
  3315. n++;
  3316. if (n == 0)
  3317. return;
  3318. if (n > m->nmaster) {
  3319. mh = (int)round(m->nmaster ? m->mfact * m->w.height : 0);
  3320. tw = m->w.width / (n - m->nmaster);
  3321. ty = m->w.y + mh;
  3322. } else {
  3323. mh = m->w.height;
  3324. tw = m->w.width;
  3325. ty = m->w.y;
  3326. }
  3327. i = mx = 0;
  3328. tx = m-> w.x;
  3329. wl_list_for_each(c, &clients, link) {
  3330. if (!VISIBLEON(c, m) || c->isfloating)
  3331. continue;
  3332. if (i < m->nmaster) {
  3333. w = (m->w.width - mx) / (MIN(n, m->nmaster) - i);
  3334. resize(c, (struct wlr_box) { .x = m->w.x + mx, .y = m->w.y, .width = w, .height = mh }, 0);
  3335. mx += c->geom.width;
  3336. } else {
  3337. h = m->w.height - mh;
  3338. resize(c, (struct wlr_box) { .x = tx, .y = ty, .width = tw, .height = h }, 0);
  3339. if (tw != m->w.width)
  3340. tx += c->geom.width;
  3341. }
  3342. i++;
  3343. }
  3344. }
  3345. static void
  3346. bstackhoriz(Monitor *m) {
  3347. int w, mh, mx, tx, ty, th;
  3348. int i, n = 0;
  3349. Client *c;
  3350. wl_list_for_each(c, &clients, link)
  3351. if (VISIBLEON(c, m) && !c->isfloating)
  3352. n ++;
  3353. if (n == 0)
  3354. return;
  3355. if (n > m->nmaster) {
  3356. mh = (int)round(m->nmaster ? m->mfact * m->w.height : 0);
  3357. th = (m->w.height - mh) / (n - m->nmaster);
  3358. ty = m->w.y + mh;
  3359. } else {
  3360. th = mh = m->w.height;
  3361. ty = m->w.y;
  3362. }
  3363. i = mx = 0;
  3364. tx = m-> w.x;
  3365. wl_list_for_each(c, &clients, link) {
  3366. if (!VISIBLEON(c,m) || c->isfloating)
  3367. continue;
  3368. if (i < m->nmaster) {
  3369. w = (m->w.width - mx) / (MIN(n, m->nmaster) - i);
  3370. resize(c, (struct wlr_box) { .x = m->w.x + mx, .y = m->w.y, .width = w, .height = mh }, 0);
  3371. mx += c->geom.width;
  3372. } else {
  3373. resize(c, (struct wlr_box) { .x = tx, .y = ty, .width = m->w.width, .height = th }, 0);
  3374. if (th != m->w.height)
  3375. ty += c->geom.height;
  3376. }
  3377. i++;
  3378. }
  3379. }