Show More
The requested changes are too big and content was truncated. Show full diff
| @@ -0,0 +1,20 | |||
|
|
1 | syntax: glob | |
|
|
2 | swindle | |
|
|
3 | smsg/smsg | |
|
|
4 | *.o | |
|
|
5 | *-protocol.c | |
|
|
6 | *-protocol.h | |
|
|
7 | smsg/*-protocol.c | |
|
|
8 | smsg/*-protocol.h | |
|
|
9 | result | |
|
|
10 | result-* | |
|
|
11 | .direnv/ | |
|
|
12 | .vscode/ | |
|
|
13 | .idea/ | |
|
|
14 | .cache/ | |
|
|
15 | compile_commands.json | |
|
|
16 | tags | |
|
|
17 | *.swp | |
|
|
18 | *.swo | |
|
|
19 | *~ | |
|
|
20 | include/lua5.4/* | |
| This diff has been collapsed as it changes many lines, (693 lines changed) Show them Hide them | |||
| @@ -0,0 +1,693 | |||
|
|
1 | swindle - wayland compositor base wlroots | |
|
|
2 | ||
|
|
3 | Copyright Β© 2026 kantiankant | |
|
|
4 | ||
|
|
5 | See also the files licenses/LICENSE.dwl, licenses/LICENSE.tinywl, | |
|
|
6 | licenses/LICENSE.dwm, licenses/LICENSE.sway, and licenses/LICENSE.mangowm | |
|
|
7 | ||
|
|
8 | This program is free software: you can redistribute it and/or modify | |
|
|
9 | it under the terms of the GNU General Public License as published by | |
|
|
10 | the Free Software Foundation, either version 3 of the License, or | |
|
|
11 | (at your option) any later version. | |
|
|
12 | ||
|
|
13 | This program is distributed in the hope that it will be useful, | |
|
|
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
|
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
|
16 | GNU General Public License for more details. | |
|
|
17 | ||
|
|
18 | ---- | |
|
|
19 | ||
|
|
20 | GNU GENERAL PUBLIC LICENSE | |
|
|
21 | Version 3, 29 June 2007 | |
|
|
22 | ||
|
|
23 | Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> | |
|
|
24 | Everyone is permitted to copy and distribute verbatim copies | |
|
|
25 | of this license document, but changing it is not allowed. | |
|
|
26 | ||
|
|
27 | Preamble | |
|
|
28 | ||
|
|
29 | The GNU General Public License is a free, copyleft license for | |
|
|
30 | software and other kinds of works. | |
|
|
31 | ||
|
|
32 | The licenses for most software and other practical works are designed | |
|
|
33 | to take away your freedom to share and change the works. By contrast, | |
|
|
34 | the GNU General Public License is intended to guarantee your freedom to | |
|
|
35 | share and change all versions of a program--to make sure it remains free | |
|
|
36 | software for all its users. We, the Free Software Foundation, use the | |
|
|
37 | GNU General Public License for most of our software; it applies also to | |
|
|
38 | any other work released this way by its authors. You can apply it to | |
|
|
39 | your programs, too. | |
|
|
40 | ||
|
|
41 | When we speak of free software, we are referring to freedom, not | |
|
|
42 | price. Our General Public Licenses are designed to make sure that you | |
|
|
43 | have the freedom to distribute copies of free software (and charge for | |
|
|
44 | them if you wish), that you receive source code or can get it if you | |
|
|
45 | want it, that you can change the software or use pieces of it in new | |
|
|
46 | free programs, and that you know you can do these things. | |
|
|
47 | ||
|
|
48 | To protect your rights, we need to prevent others from denying you | |
|
|
49 | these rights or asking you to surrender the rights. Therefore, you have | |
|
|
50 | certain responsibilities if you distribute copies of the software, or if | |
|
|
51 | you modify it: responsibilities to respect the freedom of others. | |
|
|
52 | ||
|
|
53 | For example, if you distribute copies of such a program, whether | |
|
|
54 | gratis or for a fee, you must pass on to the recipients the same | |
|
|
55 | freedoms that you received. You must make sure that they, too, receive | |
|
|
56 | or can get the source code. And you must show them these terms so they | |
|
|
57 | know their rights. | |
|
|
58 | ||
|
|
59 | Developers that use the GNU GPL protect your rights with two steps: | |
|
|
60 | (1) assert copyright on the software, and (2) offer you this License | |
|
|
61 | giving you legal permission to copy, distribute and/or modify it. | |
|
|
62 | ||
|
|
63 | For the developers' and authors' protection, the GPL clearly explains | |
|
|
64 | that there is no warranty for this free software. For both users' and | |
|
|
65 | authors' sake, the GPL requires that modified versions be marked as | |
|
|
66 | changed, so that their problems will not be attributed erroneously to | |
|
|
67 | authors of previous versions. | |
|
|
68 | ||
|
|
69 | Some devices are designed to deny users access to install or run | |
|
|
70 | modified versions of the software inside them, although the manufacturer | |
|
|
71 | can do so. This is fundamentally incompatible with the aim of | |
|
|
72 | protecting users' freedom to change the software. The systematic | |
|
|
73 | pattern of such abuse occurs in the area of products for individuals to | |
|
|
74 | use, which is precisely where it is most unacceptable. Therefore, we | |
|
|
75 | have designed this version of the GPL to prohibit the practice for those | |
|
|
76 | products. If such problems arise substantially in other domains, we | |
|
|
77 | stand ready to extend this provision to those domains in future versions | |
|
|
78 | of the GPL, as needed to protect the freedom of users. | |
|
|
79 | ||
|
|
80 | Finally, every program is threatened constantly by software patents. | |
|
|
81 | States should not allow patents to restrict development and use of | |
|
|
82 | software on general-purpose computers, but in those that do, we wish to | |
|
|
83 | avoid the special danger that patents applied to a free program could | |
|
|
84 | make it effectively proprietary. To prevent this, the GPL assures that | |
|
|
85 | patents cannot be used to render the program non-free. | |
|
|
86 | ||
|
|
87 | The precise terms and conditions for copying, distribution and | |
|
|
88 | modification follow. | |
|
|
89 | ||
|
|
90 | TERMS AND CONDITIONS | |
|
|
91 | ||
|
|
92 | 1. Definitions. | |
|
|
93 | ||
|
|
94 | "This License" refers to version 3 of the GNU General Public License. | |
|
|
95 | ||
|
|
96 | "Copyright" also means copyright-like laws that apply to other kinds of | |
|
|
97 | works, such as semiconductor masks. | |
|
|
98 | ||
|
|
99 | "The Program" refers to any copyrightable work licensed under this | |
|
|
100 | License. Each licensee is addressed as "you". "Licensees" and | |
|
|
101 | "recipients" may be individuals or organizations. | |
|
|
102 | ||
|
|
103 | To "modify" a work means to copy from or adapt all or part of the work | |
|
|
104 | in a fashion requiring copyright permission, other than the making of an | |
|
|
105 | exact copy. The resulting work is called a "modified version" of the | |
|
|
106 | earlier work or a work "based on" the earlier work. | |
|
|
107 | ||
|
|
108 | A "covered work" means either the unmodified Program or a work based | |
|
|
109 | on the Program. | |
|
|
110 | ||
|
|
111 | To "propagate" a work means to do anything with it that, without | |
|
|
112 | permission, would make you directly or secondarily liable for | |
|
|
113 | infringement under applicable copyright law, except executing it on a | |
|
|
114 | computer or modifying a private copy. Propagation includes copying, | |
|
|
115 | distribution (with or without modification), making available to the | |
|
|
116 | public, and in some countries other activities as well. | |
|
|
117 | ||
|
|
118 | To "convey" a work means any kind of propagation that enables other | |
|
|
119 | parties to make or receive copies. Mere interaction with a user through | |
|
|
120 | a computer network, with no transfer of a copy, is not conveying. | |
|
|
121 | ||
|
|
122 | An interactive user interface displays "Appropriate Legal Notices" | |
|
|
123 | to the extent that it includes a convenient and prominently visible | |
|
|
124 | feature that (1) displays an appropriate copyright notice, and (2) | |
|
|
125 | tells the user that there is no warranty for the work (except to the | |
|
|
126 | extent that warranties are provided), that licensees may convey the | |
|
|
127 | work under this License, and how to view a copy of this License. If | |
|
|
128 | the interface presents a list of user commands or options, such as a | |
|
|
129 | menu, a prominent item in the list meets this criterion. | |
|
|
130 | ||
|
|
131 | 1. Source Code. | |
|
|
132 | ||
|
|
133 | The "source code" for a work means the preferred form of the work | |
|
|
134 | for making modifications to it. "Object code" means any non-source | |
|
|
135 | form of a work. | |
|
|
136 | ||
|
|
137 | A "Standard Interface" means an interface that either is an official | |
|
|
138 | standard defined by a recognized standards body, or, in the case of | |
|
|
139 | interfaces specified for a particular programming language, one that | |
|
|
140 | is widely used among developers working in that language. | |
|
|
141 | ||
|
|
142 | The "System Libraries" of an executable work include anything, other | |
|
|
143 | than the work as a whole, that (a) is included in the normal form of | |
|
|
144 | packaging a Major Component, but which is not part of that Major | |
|
|
145 | Component, and (b) serves only to enable use of the work with that | |
|
|
146 | Major Component, or to implement a Standard Interface for which an | |
|
|
147 | implementation is available to the public in source code form. A | |
|
|
148 | "Major Component", in this context, means a major essential component | |
|
|
149 | (kernel, window system, and so on) of the specific operating system | |
|
|
150 | (if any) on which the executable work runs, or a compiler used to | |
|
|
151 | produce the work, or an object code interpreter used to run it. | |
|
|
152 | ||
|
|
153 | The "Corresponding Source" for a work in object code form means all | |
|
|
154 | the source code needed to generate, install, and (for an executable | |
|
|
155 | work) run the object code and to modify the work, including scripts to | |
|
|
156 | control those activities. However, it does not include the work's | |
|
|
157 | System Libraries, or general-purpose tools or generally available free | |
|
|
158 | programs which are used unmodified in performing those activities but | |
|
|
159 | which are not part of the work. For example, Corresponding Source | |
|
|
160 | includes interface definition files associated with source files for | |
|
|
161 | the work, and the source code for shared libraries and dynamically | |
|
|
162 | linked subprograms that the work is specifically designed to require, | |
|
|
163 | such as by intimate data communication or control flow between those | |
|
|
164 | subprograms and other parts of the work. | |
|
|
165 | ||
|
|
166 | The Corresponding Source need not include anything that users | |
|
|
167 | can regenerate automatically from other parts of the Corresponding | |
|
|
168 | Source. | |
|
|
169 | ||
|
|
170 | The Corresponding Source for a work in source code form is that | |
|
|
171 | same work. | |
|
|
172 | ||
|
|
173 | 2. Basic Permissions. | |
|
|
174 | ||
|
|
175 | All rights granted under this License are granted for the term of | |
|
|
176 | copyright on the Program, and are irrevocable provided the stated | |
|
|
177 | conditions are met. This License explicitly affirms your unlimited | |
|
|
178 | permission to run the unmodified Program. The output from running a | |
|
|
179 | covered work is covered by this License only if the output, given its | |
|
|
180 | content, constitutes a covered work. This License acknowledges your | |
|
|
181 | rights of fair use or other equivalent, as provided by copyright law. | |
|
|
182 | ||
|
|
183 | You may make, run and propagate covered works that you do not | |
|
|
184 | convey, without conditions so long as your license otherwise remains | |
|
|
185 | in force. You may convey covered works to others for the sole purpose | |
|
|
186 | of having them make modifications exclusively for you, or provide you | |
|
|
187 | with facilities for running those works, provided that you comply with | |
|
|
188 | the terms of this License in conveying all material for which you do | |
|
|
189 | not control copyright. Those thus making or running the covered works | |
|
|
190 | for you must do so exclusively on your behalf, under your direction | |
|
|
191 | and control, on terms that prohibit them from making any copies of | |
|
|
192 | your copyrighted material outside their relationship with you. | |
|
|
193 | ||
|
|
194 | Conveying under any other circumstances is permitted solely under | |
|
|
195 | the conditions stated below. Sublicensing is not allowed; section 10 | |
|
|
196 | makes it unnecessary. | |
|
|
197 | ||
|
|
198 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. | |
|
|
199 | ||
|
|
200 | No covered work shall be deemed part of an effective technological | |
|
|
201 | measure under any applicable law fulfilling obligations under article | |
|
|
202 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or | |
|
|
203 | similar laws prohibiting or restricting circumvention of such | |
|
|
204 | measures. | |
|
|
205 | ||
|
|
206 | When you convey a covered work, you waive any legal power to forbid | |
|
|
207 | circumvention of technological measures to the extent such circumvention | |
|
|
208 | is effected by exercising rights under this License with respect to | |
|
|
209 | the covered work, and you disclaim any intention to limit operation or | |
|
|
210 | modification of the work as a means of enforcing, against the work's | |
|
|
211 | users, your or third parties' legal rights to forbid circumvention of | |
|
|
212 | technological measures. | |
|
|
213 | ||
|
|
214 | 4. Conveying Verbatim Copies. | |
|
|
215 | ||
|
|
216 | You may convey verbatim copies of the Program's source code as you | |
|
|
217 | receive it, in any medium, provided that you conspicuously and | |
|
|
218 | appropriately publish on each copy an appropriate copyright notice; | |
|
|
219 | keep intact all notices stating that this License and any | |
|
|
220 | non-permissive terms added in accord with section 7 apply to the code; | |
|
|
221 | keep intact all notices of the absence of any warranty; and give all | |
|
|
222 | recipients a copy of this License along with the Program. | |
|
|
223 | ||
|
|
224 | You may charge any price or no price for each copy that you convey, | |
|
|
225 | and you may offer support or warranty protection for a fee. | |
|
|
226 | ||
|
|
227 | 5. Conveying Modified Source Versions. | |
|
|
228 | ||
|
|
229 | You may convey a work based on the Program, or the modifications to | |
|
|
230 | produce it from the Program, in the form of source code under the | |
|
|
231 | terms of section 4, provided that you also meet all of these conditions: | |
|
|
232 | ||
|
|
233 | a) The work must carry prominent notices stating that you modified | |
|
|
234 | it, and giving a relevant date. | |
|
|
235 | ||
|
|
236 | b) The work must carry prominent notices stating that it is | |
|
|
237 | released under this License and any conditions added under section | |
|
|
238 | 7. This requirement modifies the requirement in section 4 to | |
|
|
239 | "keep intact all notices". | |
|
|
240 | ||
|
|
241 | c) You must license the entire work, as a whole, under this | |
|
|
242 | License to anyone who comes into possession of a copy. This | |
|
|
243 | License will therefore apply, along with any applicable section 7 | |
|
|
244 | additional terms, to the whole of the work, and all its parts, | |
|
|
245 | regardless of how they are packaged. This License gives no | |
|
|
246 | permission to license the work in any other way, but it does not | |
|
|
247 | invalidate such permission if you have separately received it. | |
|
|
248 | ||
|
|
249 | d) If the work has interactive user interfaces, each must display | |
|
|
250 | Appropriate Legal Notices; however, if the Program has interactive | |
|
|
251 | interfaces that do not display Appropriate Legal Notices, your | |
|
|
252 | work need not make them do so. | |
|
|
253 | ||
|
|
254 | A compilation of a covered work with other separate and independent | |
|
|
255 | works, which are not by their nature extensions of the covered work, | |
|
|
256 | and which are not combined with it such as to form a larger program, | |
|
|
257 | in or on a volume of a storage or distribution medium, is called an | |
|
|
258 | "aggregate" if the compilation and its resulting copyright are not | |
|
|
259 | used to limit the access or legal rights of the compilation's users | |
|
|
260 | beyond what the individual works permit. Inclusion of a covered work | |
|
|
261 | in an aggregate does not cause this License to apply to the other | |
|
|
262 | parts of the aggregate. | |
|
|
263 | ||
|
|
264 | 6. Conveying Non-Source Forms. | |
|
|
265 | ||
|
|
266 | You may convey a covered work in object code form under the terms | |
|
|
267 | of sections 4 and 5, provided that you also convey the | |
|
|
268 | machine-readable Corresponding Source under the terms of this License, | |
|
|
269 | in one of these ways: | |
|
|
270 | ||
|
|
271 | a) Convey the object code in, or embodied in, a physical product | |
|
|
272 | (including a physical distribution medium), accompanied by the | |
|
|
273 | Corresponding Source fixed on a durable physical medium | |
|
|
274 | customarily used for software interchange. | |
|
|
275 | ||
|
|
276 | b) Convey the object code in, or embodied in, a physical product | |
|
|
277 | (including a physical distribution medium), accompanied by a | |
|
|
278 | written offer, valid for at least three years and valid for as | |
|
|
279 | long as you offer spare parts or customer support for that product | |
|
|
280 | model, to give anyone who possesses the object code either (1) a | |
|
|
281 | copy of the Corresponding Source for all the software in the | |
|
|
282 | product that is covered by this License, on a durable physical | |
|
|
283 | medium customarily used for software interchange, for a price no | |
|
|
284 | more than your reasonable cost of physically performing this | |
|
|
285 | conveying of source, or (2) access to copy the | |
|
|
286 | Corresponding Source from a network server at no charge. | |
|
|
287 | ||
|
|
288 | c) Convey individual copies of the object code with a copy of the | |
|
|
289 | written offer to provide the Corresponding Source. This | |
|
|
290 | alternative is allowed only occasionally and noncommercially, and | |
|
|
291 | only if you received the object code with such an offer, in accord | |
|
|
292 | with subsection 6b. | |
|
|
293 | ||
|
|
294 | d) Convey the object code by offering access from a designated | |
|
|
295 | place (gratis or for a charge), and offer equivalent access to the | |
|
|
296 | Corresponding Source in the same way through the same place at no | |
|
|
297 | further charge. You need not require recipients to copy the | |
|
|
298 | Corresponding Source along with the object code. If the place to | |
|
|
299 | copy the object code is a network server, the Corresponding Source | |
|
|
300 | may be on a different server (operated by you or a third party) | |
|
|
301 | that supports equivalent copying facilities, provided you maintain | |
|
|
302 | clear directions next to the object code saying where to find the | |
|
|
303 | Corresponding Source. Regardless of what server hosts the | |
|
|
304 | Corresponding Source, you remain obligated to ensure that it is | |
|
|
305 | available for as long as needed to satisfy these requirements. | |
|
|
306 | ||
|
|
307 | e) Convey the object code using peer-to-peer transmission, provided | |
|
|
308 | you inform other peers where the object code and Corresponding | |
|
|
309 | Source of the work are being offered to the general public at no | |
|
|
310 | charge under subsection 6d. | |
|
|
311 | ||
|
|
312 | A separable portion of the object code, whose source code is excluded | |
|
|
313 | from the Corresponding Source as a System Library, need not be | |
|
|
314 | included in conveying the object code work. | |
|
|
315 | ||
|
|
316 | A "User Product" is either (1) a "consumer product", which means any | |
|
|
317 | tangible personal property which is normally used for personal, family, | |
|
|
318 | or household purposes, or (2) anything designed or sold for incorporation | |
|
|
319 | into a dwelling. In determining whether a product is a consumer product, | |
|
|
320 | doubtful cases shall be resolved in favor of coverage. For a particular | |
|
|
321 | product received by a particular user, "normally used" refers to a | |
|
|
322 | typical or common use of that class of product, regardless of the status | |
|
|
323 | of the particular user or of the way in which the particular user | |
|
|
324 | actually uses, or expects or is expected to use, the product. A product | |
|
|
325 | is a consumer product regardless of whether the product has substantial | |
|
|
326 | commercial, industrial or non-consumer uses, unless such uses represent | |
|
|
327 | the only significant mode of use of the product. | |
|
|
328 | ||
|
|
329 | "Installation Information" for a User Product means any methods, | |
|
|
330 | procedures, authorization keys, or other information required to install | |
|
|
331 | and execute modified versions of a covered work in that User Product from | |
|
|
332 | a modified version of its Corresponding Source. The information must | |
|
|
333 | suffice to ensure that the continued functioning of the modified object | |
|
|
334 | code is in no case prevented or interfered with solely because | |
|
|
335 | modification has been made. | |
|
|
336 | ||
|
|
337 | If you convey an object code work under this section in, or with, or | |
|
|
338 | specifically for use in, a User Product, and the conveying occurs as | |
|
|
339 | part of a transaction in which the right of possession and use of the | |
|
|
340 | User Product is transferred to the recipient in perpetuity or for a | |
|
|
341 | fixed term (regardless of how the transaction is characterized), the | |
|
|
342 | Corresponding Source conveyed under this section must be accompanied | |
|
|
343 | by the Installation Information. But this requirement does not apply | |
|
|
344 | if neither you nor any third party retains the ability to install | |
|
|
345 | modified object code on the User Product (for example, the work has | |
|
|
346 | been installed in ROM). | |
|
|
347 | ||
|
|
348 | The requirement to provide Installation Information does not include a | |
|
|
349 | requirement to continue to provide support service, warranty, or updates | |
|
|
350 | for a work that has been modified or installed by the recipient, or for | |
|
|
351 | the User Product in which it has been modified or installed. Access to a | |
|
|
352 | network may be denied when the modification itself materially and | |
|
|
353 | adversely affects the operation of the network or violates the rules and | |
|
|
354 | protocols for communication across the network. | |
|
|
355 | ||
|
|
356 | Corresponding Source conveyed, and Installation Information provided, | |
|
|
357 | in accord with this section must be in a format that is publicly | |
|
|
358 | documented (and with an implementation available to the public in | |
|
|
359 | source code form), and must require no special password or key for | |
|
|
360 | unpacking, reading or copying. | |
|
|
361 | ||
|
|
362 | 7. Additional Terms. | |
|
|
363 | ||
|
|
364 | "Additional permissions" are terms that supplement the terms of this | |
|
|
365 | License by making exceptions from one or more of its conditions. | |
|
|
366 | Additional permissions that are applicable to the entire Program shall | |
|
|
367 | be treated as though they were included in this License, to the extent | |
|
|
368 | that they are valid under applicable law. If additional permissions | |
|
|
369 | apply only to part of the Program, that part may be used separately | |
|
|
370 | under those permissions, but the entire Program remains governed by | |
|
|
371 | this License without regard to the additional permissions. | |
|
|
372 | ||
|
|
373 | When you convey a copy of a covered work, you may at your option | |
|
|
374 | remove any additional permissions from that copy, or from any part of | |
|
|
375 | it. (Additional permissions may be written to require their own | |
|
|
376 | removal in certain cases when you modify the work.) You may place | |
|
|
377 | additional permissions on material, added by you to a covered work, | |
|
|
378 | for which you have or can give appropriate copyright permission. | |
|
|
379 | ||
|
|
380 | Notwithstanding any other provision of this License, for material you | |
|
|
381 | add to a covered work, you may (if authorized by the copyright holders of | |
|
|
382 | that material) supplement the terms of this License with terms: | |
|
|
383 | ||
|
|
384 | a) Disclaiming warranty or limiting liability differently from the | |
|
|
385 | terms of sections 15 and 16 of this License; or | |
|
|
386 | ||
|
|
387 | b) Requiring preservation of specified reasonable legal notices or | |
|
|
388 | author attributions in that material or in the Appropriate Legal | |
|
|
389 | Notices displayed by works containing it; or | |
|
|
390 | ||
|
|
391 | c) Prohibiting misrepresentation of the origin of that material, or | |
|
|
392 | requiring that modified versions of such material be marked in | |
|
|
393 | reasonable ways as different from the original version; or | |
|
|
394 | ||
|
|
395 | d) Limiting the use for publicity purposes of names of licensors or | |
|
|
396 | authors of the material; or | |
|
|
397 | ||
|
|
398 | e) Declining to grant rights under trademark law for use of some | |
|
|
399 | trade names, trademarks, or service marks; or | |
|
|
400 | ||
|
|
401 | f) Requiring indemnification of licensors and authors of that | |
|
|
402 | material by anyone who conveys the material (or modified versions of | |
|
|
403 | it) with contractual assumptions of liability to the recipient, for | |
|
|
404 | any liability that these contractual assumptions directly impose on | |
|
|
405 | those licensors and authors. | |
|
|
406 | ||
|
|
407 | All other non-permissive additional terms are considered "further | |
|
|
408 | restrictions" within the meaning of section 10. If the Program as you | |
|
|
409 | received it, or any part of it, contains a notice stating that it is | |
|
|
410 | governed by this License along with a term that is a further | |
|
|
411 | restriction, you may remove that term. If a license document contains | |
|
|
412 | a further restriction but permits relicensing or conveying under this | |
|
|
413 | License, you may add to a covered work material governed by the terms | |
|
|
414 | of that license document, provided that the further restriction does | |
|
|
415 | not survive such relicensing or conveying. | |
|
|
416 | ||
|
|
417 | If you add terms to a covered work in accord with this section, you | |
|
|
418 | must place, in the relevant source files, a statement of the | |
|
|
419 | additional terms that apply to those files, or a notice indicating | |
|
|
420 | where to find the applicable terms. | |
|
|
421 | ||
|
|
422 | Additional terms, permissive or non-permissive, may be stated in the | |
|
|
423 | form of a separately written license, or stated as exceptions; | |
|
|
424 | the above requirements apply either way. | |
|
|
425 | ||
|
|
426 | 8. Termination. | |
|
|
427 | ||
|
|
428 | You may not propagate or modify a covered work except as expressly | |
|
|
429 | provided under this License. Any attempt otherwise to propagate or | |
|
|
430 | modify it is void, and will automatically terminate your rights under | |
|
|
431 | this License (including any patent licenses granted under the third | |
|
|
432 | paragraph of section 11). | |
|
|
433 | ||
|
|
434 | However, if you cease all violation of this License, then your | |
|
|
435 | license from a particular copyright holder is reinstated (a) | |
|
|
436 | provisionally, unless and until the copyright holder explicitly and | |
|
|
437 | finally terminates your license, and (b) permanently, if the copyright | |
|
|
438 | holder fails to notify you of the violation by some reasonable means | |
|
|
439 | prior to 60 days after the cessation. | |
|
|
440 | ||
|
|
441 | Moreover, your license from a particular copyright holder is | |
|
|
442 | reinstated permanently if the copyright holder notifies you of the | |
|
|
443 | violation by some reasonable means, this is the first time you have | |
|
|
444 | received notice of violation of this License (for any work) from that | |
|
|
445 | copyright holder, and you cure the violation prior to 30 days after | |
|
|
446 | your receipt of the notice. | |
|
|
447 | ||
|
|
448 | Termination of your rights under this section does not terminate the | |
|
|
449 | licenses of parties who have received copies or rights from you under | |
|
|
450 | this License. If your rights have been terminated and not permanently | |
|
|
451 | reinstated, you do not qualify to receive new licenses for the same | |
|
|
452 | material under section 10. | |
|
|
453 | ||
|
|
454 | 9. Acceptance Not Required for Having Copies. | |
|
|
455 | ||
|
|
456 | You are not required to accept this License in order to receive or | |
|
|
457 | run a copy of the Program. Ancillary propagation of a covered work | |
|
|
458 | occurring solely as a consequence of using peer-to-peer transmission | |
|
|
459 | to receive a copy likewise does not require acceptance. However, | |
|
|
460 | nothing other than this License grants you permission to propagate or | |
|
|
461 | modify any covered work. These actions infringe copyright if you do | |
|
|
462 | not accept this License. Therefore, by modifying or propagating a | |
|
|
463 | covered work, you indicate your acceptance of this License to do so. | |
|
|
464 | ||
|
|
465 | 10. Automatic Licensing of Downstream Recipients. | |
|
|
466 | ||
|
|
467 | Each time you convey a covered work, the recipient automatically | |
|
|
468 | receives a license from the original licensors, to run, modify and | |
|
|
469 | propagate that work, subject to this License. You are not responsible | |
|
|
470 | for enforcing compliance by third parties with this License. | |
|
|
471 | ||
|
|
472 | An "entity transaction" is a transaction transferring control of an | |
|
|
473 | organization, or substantially all assets of one, or subdividing an | |
|
|
474 | organization, or merging organizations. If propagation of a covered | |
|
|
475 | work results from an entity transaction, each party to that | |
|
|
476 | transaction who receives a copy of the work also receives whatever | |
|
|
477 | licenses to the work the party's predecessor in interest had or could | |
|
|
478 | give under the previous paragraph, plus a right to possession of the | |
|
|
479 | Corresponding Source of the work from the predecessor in interest, if | |
|
|
480 | the predecessor has it or can get it with reasonable efforts. | |
|
|
481 | ||
|
|
482 | You may not impose any further restrictions on the exercise of the | |
|
|
483 | rights granted or affirmed under this License. For example, you may | |
|
|
484 | not impose a license fee, royalty, or other charge for exercise of | |
|
|
485 | rights granted under this License, and you may not initiate litigation | |
|
|
486 | (including a cross-claim or counterclaim in a lawsuit) alleging that | |
|
|
487 | any patent claim is infringed by making, using, selling, offering for | |
|
|
488 | sale, or importing the Program or any portion of it. | |
|
|
489 | ||
|
|
490 | 11. Patents. | |
|
|
491 | ||
|
|
492 | A "contributor" is a copyright holder who authorizes use under this | |
|
|
493 | License of the Program or a work on which the Program is based. The | |
|
|
494 | work thus licensed is called the contributor's "contributor version". | |
|
|
495 | ||
|
|
496 | A contributor's "essential patent claims" are all patent claims | |
|
|
497 | owned or controlled by the contributor, whether already acquired or | |
|
|
498 | hereafter acquired, that would be infringed by some manner, permitted | |
|
|
499 | by this License, of making, using, or selling its contributor version, | |
|
|
500 | but do not include claims that would be infringed only as a | |
|
|
501 | consequence of further modification of the contributor version. For | |
|
|
502 | purposes of this definition, "control" includes the right to grant | |
|
|
503 | patent sublicenses in a manner consistent with the requirements of | |
|
|
504 | this License. | |
|
|
505 | ||
|
|
506 | Each contributor grants you a non-exclusive, worldwide, royalty-free | |
|
|
507 | patent license under the contributor's essential patent claims, to | |
|
|
508 | make, use, sell, offer for sale, import and otherwise run, modify and | |
|
|
509 | propagate the contents of its contributor version. | |
|
|
510 | ||
|
|
511 | In the following three paragraphs, a "patent license" is any express | |
|
|
512 | agreement or commitment, however denominated, not to enforce a patent | |
|
|
513 | (such as an express permission to practice a patent or covenant not to | |
|
|
514 | sue for patent infringement). To "grant" such a patent license to a | |
|
|
515 | party means to make such an agreement or commitment not to enforce a | |
|
|
516 | patent against the party. | |
|
|
517 | ||
|
|
518 | If you convey a covered work, knowingly relying on a patent license, | |
|
|
519 | and the Corresponding Source of the work is not available for anyone | |
|
|
520 | to copy, free of charge and under the terms of this License, through a | |
|
|
521 | publicly available network server or other readily accessible means, | |
|
|
522 | then you must either (1) cause the Corresponding Source to be so | |
|
|
523 | available, or (2) arrange to deprive yourself of the benefit of the | |
|
|
524 | patent license for this particular work, or (3) arrange, in a manner | |
|
|
525 | consistent with the requirements of this License, to extend the patent | |
|
|
526 | license to downstream recipients. "Knowingly relying" means you have | |
|
|
527 | actual knowledge that, but for the patent license, your conveying the | |
|
|
528 | covered work in a country, or your recipient's use of the covered work | |
|
|
529 | in a country, would infringe one or more identifiable patents in that | |
|
|
530 | country that you have reason to believe are valid. | |
|
|
531 | ||
|
|
532 | If, pursuant to or in connection with a single transaction or | |
|
|
533 | arrangement, you convey, or propagate by procuring conveyance of, a | |
|
|
534 | covered work, and grant a patent license to some of the parties | |
|
|
535 | receiving the covered work authorizing them to use, propagate, modify | |
|
|
536 | or convey a specific copy of the covered work, then the patent license | |
|
|
537 | you grant is automatically extended to all recipients of the covered | |
|
|
538 | work and works based on it. | |
|
|
539 | ||
|
|
540 | A patent license is "discriminatory" if it does not include within | |
|
|
541 | the scope of its coverage, prohibits the exercise of, or is | |
|
|
542 | conditioned on the non-exercise of one or more of the rights that are | |
|
|
543 | specifically granted under this License. You may not convey a covered | |
|
|
544 | work if you are a party to an arrangement with a third party that is | |
|
|
545 | in the business of distributing software, under which you make payment | |
|
|
546 | to the third party based on the extent of your activity of conveying | |
|
|
547 | the work, and under which the third party grants, to any of the | |
|
|
548 | parties who would receive the covered work from you, a discriminatory | |
|
|
549 | patent license (a) in connection with copies of the covered work | |
|
|
550 | conveyed by you (or copies made from those copies), or (b) primarily | |
|
|
551 | for and in connection with specific products or compilations that | |
|
|
552 | contain the covered work, unless you entered into that arrangement, | |
|
|
553 | or that patent license was granted, prior to 28 March 2007. | |
|
|
554 | ||
|
|
555 | Nothing in this License shall be construed as excluding or limiting | |
|
|
556 | any implied license or other defenses to infringement that may | |
|
|
557 | otherwise be available to you under applicable patent law. | |
|
|
558 | ||
|
|
559 | 12. No Surrender of Others' Freedom. | |
|
|
560 | ||
|
|
561 | If conditions are imposed on you (whether by court order, agreement or | |
|
|
562 | otherwise) that contradict the conditions of this License, they do not | |
|
|
563 | excuse you from the conditions of this License. If you cannot convey a | |
|
|
564 | covered work so as to satisfy simultaneously your obligations under this | |
|
|
565 | License and any other pertinent obligations, then as a consequence you may | |
|
|
566 | not convey it at all. For example, if you agree to terms that obligate you | |
|
|
567 | to collect a royalty for further conveying from those to whom you convey | |
|
|
568 | the Program, the only way you could satisfy both those terms and this | |
|
|
569 | License would be to refrain entirely from conveying the Program. | |
|
|
570 | ||
|
|
571 | 13. Use with the GNU Affero General Public License. | |
|
|
572 | ||
|
|
573 | Notwithstanding any other provision of this License, you have | |
|
|
574 | permission to link or combine any covered work with a work licensed | |
|
|
575 | under version 3 of the GNU Affero General Public License into a single | |
|
|
576 | combined work, and to convey the resulting work. The terms of this | |
|
|
577 | License will continue to apply to the part which is the covered work, | |
|
|
578 | but the special requirements of the GNU Affero General Public License, | |
|
|
579 | section 13, concerning interaction through a network will apply to the | |
|
|
580 | combination as such. | |
|
|
581 | ||
|
|
582 | 14. Revised Versions of this License. | |
|
|
583 | ||
|
|
584 | The Free Software Foundation may publish revised and/or new versions of | |
|
|
585 | the GNU General Public License from time to time. Such new versions will | |
|
|
586 | be similar in spirit to the present version, but may differ in detail to | |
|
|
587 | address new problems or concerns. | |
|
|
588 | ||
|
|
589 | Each version is given a distinguishing version number. If the | |
|
|
590 | Program specifies that a certain numbered version of the GNU General | |
|
|
591 | Public License "or any later version" applies to it, you have the | |
|
|
592 | option of following the terms and conditions either of that numbered | |
|
|
593 | version or of any later version published by the Free Software | |
|
|
594 | Foundation. If the Program does not specify a version number of the | |
|
|
595 | GNU General Public License, you may choose any version ever published | |
|
|
596 | by the Free Software Foundation. | |
|
|
597 | ||
|
|
598 | If the Program specifies that a proxy can decide which future | |
|
|
599 | versions of the GNU General Public License can be used, that proxy's | |
|
|
600 | public statement of acceptance of a version permanently authorizes you | |
|
|
601 | to choose that version for the Program. | |
|
|
602 | ||
|
|
603 | Later license versions may give you additional or different | |
|
|
604 | permissions. However, no additional obligations are imposed on any | |
|
|
605 | author or copyright holder as a result of your choosing to follow a | |
|
|
606 | later version. | |
|
|
607 | ||
|
|
608 | 15. Disclaimer of Warranty. | |
|
|
609 | ||
|
|
610 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | |
|
|
611 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | |
|
|
612 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | |
|
|
613 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | |
|
|
614 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
|
|
615 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | |
|
|
616 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | |
|
|
617 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |
|
|
618 | ||
|
|
619 | 16. Limitation of Liability. | |
|
|
620 | ||
|
|
621 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |
|
|
622 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | |
|
|
623 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | |
|
|
624 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | |
|
|
625 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | |
|
|
626 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | |
|
|
627 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | |
|
|
628 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | |
|
|
629 | SUCH DAMAGES. | |
|
|
630 | ||
|
|
631 | 17. Interpretation of Sections 15 and 16. | |
|
|
632 | ||
|
|
633 | If the disclaimer of warranty and limitation of liability provided | |
|
|
634 | above cannot be given local legal effect according to their terms, | |
|
|
635 | reviewing courts shall apply local law that most closely approximates | |
|
|
636 | an absolute waiver of all civil liability in connection with the | |
|
|
637 | Program, unless a warranty or assumption of liability accompanies a | |
|
|
638 | copy of the Program in return for a fee. | |
|
|
639 | ||
|
|
640 | END OF TERMS AND CONDITIONS | |
|
|
641 | ||
|
|
642 | How to Apply These Terms to Your New Programs | |
|
|
643 | ||
|
|
644 | If you develop a new program, and you want it to be of the greatest | |
|
|
645 | possible use to the public, the best way to achieve this is to make it | |
|
|
646 | free software which everyone can redistribute and change under these terms. | |
|
|
647 | ||
|
|
648 | To do so, attach the following notices to the program. It is safest | |
|
|
649 | to attach them to the start of each source file to most effectively | |
|
|
650 | state the exclusion of warranty; and each file should have at least | |
|
|
651 | the "copyright" line and a pointer to where the full notice is found. | |
|
|
652 | ||
|
|
653 | <one line to give the program's name and a brief idea of what it does.> | |
|
|
654 | Copyright (C) <year> <name of author> | |
|
|
655 | ||
|
|
656 | This program is free software: you can redistribute it and/or modify | |
|
|
657 | it under the terms of the GNU General Public License as published by | |
|
|
658 | the Free Software Foundation, either version 3 of the License, or | |
|
|
659 | (at your option) any later version. | |
|
|
660 | ||
|
|
661 | This program is distributed in the hope that it will be useful, | |
|
|
662 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
|
663 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
|
664 | GNU General Public License for more details. | |
|
|
665 | ||
|
|
666 | You should have received a copy of the GNU General Public License | |
|
|
667 | along with this program. If not, see <https://www.gnu.org/licenses/>. | |
|
|
668 | ||
|
|
669 | Also add information on how to contact you by electronic and paper mail. | |
|
|
670 | ||
|
|
671 | If the program does terminal interaction, make it output a short | |
|
|
672 | notice like this when it starts in an interactive mode: | |
|
|
673 | ||
|
|
674 | <program> Copyright (C) <year> <name of author> | |
|
|
675 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |
|
|
676 | This is free software, and you are welcome to redistribute it | |
|
|
677 | under certain conditions; type `show c' for details. | |
|
|
678 | ||
|
|
679 | The hypothetical commands `show w' and `show c' should show the appropriate | |
|
|
680 | parts of the General Public License. Of course, your program's commands | |
|
|
681 | might be different; for a GUI interface, you would use an "about box". | |
|
|
682 | ||
|
|
683 | You should also get your employer (if you work as a programmer) or school, | |
|
|
684 | if any, to sign a "copyright disclaimer" for the program, if necessary. | |
|
|
685 | For more information on this, and how to apply and follow the GNU GPL, see | |
|
|
686 | <https://www.gnu.org/licenses/>. | |
|
|
687 | ||
|
|
688 | The GNU General Public License does not permit incorporating your program | |
|
|
689 | into proprietary programs. If your program is a subroutine library, you | |
|
|
690 | may consider it more useful to permit linking proprietary applications with | |
|
|
691 | the library. If this is what you want to do, use the GNU Lesser General | |
|
|
692 | Public License instead of this License. But first, please read | |
|
|
693 | <https://www.gnu.org/licenses/why-not-lgpl.html>. | |
| @@ -0,0 +1,99 | |||
|
|
1 | .POSIX: | |
|
|
2 | .SUFFIXES: | |
|
|
3 | ||
|
|
4 | include config.mk | |
|
|
5 | ||
|
|
6 | DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) \ | |
|
|
7 | -I. -Iinclude -Isrc -Iparser -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" \ | |
|
|
8 | $(XWAYLAND) -g -Wall -Wextra -Wno-unused-parameter -O1 -std=c11 $(CFLAGS) | |
|
|
9 | LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) | |
|
|
10 | ||
|
|
11 | SCANNER = `$(PKG_CONFIG) --variable=wayland_scanner wayland-scanner` | |
|
|
12 | PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols` | |
|
|
13 | ||
|
|
14 | SMSG_CFLAGS = `$(PKG_CONFIG) --cflags wayland-client` -Wall -Wextra -Wno-unused-parameter | |
|
|
15 | SMSG_LDLIBS = `$(PKG_CONFIG) --libs wayland-client` | |
|
|
16 | ||
|
|
17 | all: swindle smsg/smsg | |
|
|
18 | ||
|
|
19 | swindle: src/dwl.o src/util.o parser/parser.o dwl-ipc-unstable-v2-protocol.o src/wlr_ext_workspace_v1.o ext-workspace-v1-protocol.o | |
|
|
20 | $(CC) $^ $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ | |
|
|
21 | ||
|
|
22 | src/dwl.o: src/swindle.c include/client.h config.h include/dwl-ipc.h dwl-ipc-unstable-v2-protocol.h \ | |
|
|
23 | include/ext-workspace.h src/wlr_ext_workspace_v1.h ext-workspace-v1-protocol.h \ | |
|
|
24 | cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h \ | |
|
|
25 | wlr-layer-shell-unstable-v1-protocol.h \ | |
|
|
26 | wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ | |
|
|
27 | parser/parser.h | |
|
|
28 | $(CC) $(DWLCFLAGS) -o $@ -c $< | |
|
|
29 | ||
|
|
30 | src/util.o: src/util.c src/util.h | |
|
|
31 | $(CC) $(DWLCFLAGS) -o $@ -c $< | |
|
|
32 | ||
|
|
33 | src/wlr_ext_workspace_v1.o: src/wlr_ext_workspace_v1.c src/wlr_ext_workspace_v1.h ext-workspace-v1-protocol.h | |
|
|
34 | $(CC) $(DWLCFLAGS) -o $@ -c $< | |
|
|
35 | ||
|
|
36 | parser/parser.o: parser/parser.c parser/parser.h | |
|
|
37 | $(CC) $(DWLCFLAGS) -o $@ -c $< | |
|
|
38 | ||
|
|
39 | dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.c | |
|
|
40 | ||
|
|
41 | ext-workspace-v1-protocol.o: ext-workspace-v1-protocol.c | |
|
|
42 | ||
|
|
43 | # protocol headers and glue | |
|
|
44 | cursor-shape-v1-protocol.h: | |
|
|
45 | $(SCANNER) enum-header $(PROTOCOLS)/staging/cursor-shape/cursor-shape-v1.xml $@ | |
|
|
46 | pointer-constraints-unstable-v1-protocol.h: | |
|
|
47 | $(SCANNER) enum-header $(PROTOCOLS)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@ | |
|
|
48 | wlr-layer-shell-unstable-v1-protocol.h: | |
|
|
49 | $(SCANNER) enum-header protocols/wlr-layer-shell-unstable-v1.xml $@ | |
|
|
50 | wlr-output-power-management-unstable-v1-protocol.h: | |
|
|
51 | $(SCANNER) server-header protocols/wlr-output-power-management-unstable-v1.xml $@ | |
|
|
52 | xdg-shell-protocol.h: | |
|
|
53 | $(SCANNER) server-header $(PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ | |
|
|
54 | dwl-ipc-unstable-v2-protocol.h: | |
|
|
55 | $(SCANNER) server-header protocols/dwl-ipc-unstable-v2.xml $@ | |
|
|
56 | dwl-ipc-unstable-v2-protocol.c: | |
|
|
57 | $(SCANNER) private-code protocols/dwl-ipc-unstable-v2.xml $@ | |
|
|
58 | ||
|
|
59 | # smsg | |
|
|
60 | smsg/dwl-ipc-unstable-v2-protocol.h: | |
|
|
61 | $(SCANNER) client-header protocols/dwl-ipc-unstable-v2.xml $@ | |
|
|
62 | ||
|
|
63 | smsg/dwl-ipc-unstable-v2-protocol.c: | |
|
|
64 | $(SCANNER) private-code protocols/dwl-ipc-unstable-v2.xml $@ | |
|
|
65 | ||
|
|
66 | smsg/dwl-ipc-unstable-v2-protocol.o: smsg/dwl-ipc-unstable-v2-protocol.c | |
|
|
67 | $(CC) $(SMSG_CFLAGS) -o $@ -c $< | |
|
|
68 | ||
|
|
69 | smsg/smsg.o: smsg/smsg.c smsg/dwl-ipc-unstable-v2-protocol.h | |
|
|
70 | $(CC) $(SMSG_CFLAGS) -o $@ -c $< | |
|
|
71 | ||
|
|
72 | smsg/smsg: smsg/smsg.o smsg/dwl-ipc-unstable-v2-protocol.o | |
|
|
73 | $(CC) $^ $(SMSG_CFLAGS) $(SMSG_LDLIBS) -o $@ | |
|
|
74 | ||
|
|
75 | ext-workspace-v1-protocol.h: | |
|
|
76 | $(SCANNER) server-header protocols/ext-workspace-v1.xml $@ | |
|
|
77 | ext-workspace-v1-protocol.c: | |
|
|
78 | $(SCANNER) private-code protocols/ext-workspace-v1.xml $@ | |
|
|
79 | ||
|
|
80 | clean: | |
|
|
81 | rm -f swindle smsg/smsg src/*.o parser/*.o smsg/*.o smsg/*-protocol.h smsg/*-protocol.c *.o *-protocol.h *-protocol.c | |
|
|
82 | ||
|
|
83 | install: swindle smsg/smsg | |
|
|
84 | mkdir -p $(DESTDIR)$(PREFIX)/bin | |
|
|
85 | cp -f swindle $(DESTDIR)$(PREFIX)/bin | |
|
|
86 | chmod 755 $(DESTDIR)$(PREFIX)/bin/swindle | |
|
|
87 | cp -f smsg/smsg $(DESTDIR)$(PREFIX)/bin | |
|
|
88 | chmod 755 $(DESTDIR)$(PREFIX)/bin/smsg | |
|
|
89 | mkdir -p $(DESTDIR)/etc/swindle | |
|
|
90 | cp -r example/* $(DESTDIR)/etc/swindle | |
|
|
91 | ||
|
|
92 | uninstall: | |
|
|
93 | rm -f $(DESTDIR)$(PREFIX)/bin/swindle | |
|
|
94 | rm -f $(DESTDIR)$(PREFIX)/bin/smsg | |
|
|
95 | rm -rf $(DESTDIR)/etc/swindle | |
|
|
96 | ||
|
|
97 | .SUFFIXES: .c .o | |
|
|
98 | .c.o: | |
|
|
99 | $(CC) $(DWLCFLAGS) -o $@ -c $< | |
| @@ -0,0 +1,56 | |||
|
|
1 | ## Swindle | |
|
|
2 | ||
|
|
3 | ||
|
|
4 | ||
|
|
5 | > "It's so bad it's not even funny!" -kantiankant, 2026 | |
|
|
6 | ||
|
|
7 | ||
|
|
8 | Swindle is a fork of [dwl](https://codeberg.org/dwl/dwl) that was designed from the start with one goal: to make it feel like the poor man's Hyprland. It has the following: | |
|
|
9 | ||
|
|
10 | * NO cool vfx | |
|
|
11 | * nearly NO documentation | |
|
|
12 | * ZERO good original code | |
|
|
13 | * only ONE tiling layout (dwindle) | |
|
|
14 | ||
|
|
15 | > Fun fact: I actually took some parts of [MangoWM](https://github.com/mangowm/mango) (such as the ext-workspaces implementation). hence why the LICENSE.mangowm exists | |
|
|
16 | ||
|
|
17 | ## Dependencies | |
|
|
18 | ||
|
|
19 | * libinput | |
|
|
20 | * wayland | |
|
|
21 | * wlroots-0.20 (compiled with the libinput backend) | |
|
|
22 | * xkbcommon | |
|
|
23 | * wayland-protocols (compile-time only) | |
|
|
24 | * pkg-config (compile-time only) | |
|
|
25 | ||
|
|
26 | Install these (and their `-devel` versions if your distro has separate | |
|
|
27 | development packages) and run `make` followed by `doas/sudo make install`, if you wish to install it (installs to /usr/local/bin/ by default). | |
|
|
28 | ||
|
|
29 | ## Things that are good to have | |
|
|
30 | ||
|
|
31 | * [foot](https://codeberg.org/dnkl/foot) | |
|
|
32 | ||
|
|
33 | ||
|
|
34 | ## Known Issues | |
|
|
35 | ||
|
|
36 | N/A | |
|
|
37 | ||
|
|
38 | ## Configuration | |
|
|
39 | ||
|
|
40 | read example/config.lua. It should give you a basic idea of how configuring swindle works. | |
|
|
41 | ||
|
|
42 | > note: it's best to copy /etc/swindle/config.lua into XDG_HOME_DIR/.config/swindle/ before you attempt to | |
|
|
43 | start swindle because it (swindle) won't start without it | |
|
|
44 | ||
|
|
45 | ## Checklist | |
|
|
46 | ||
|
|
47 | - [ ] separate the trackpad scroll from the mousee scroll | |
|
|
48 | - [x] Add ability to change your keymap | |
|
|
49 | - [ ] Add animations via [scenefx](https://github.com/wlrfx/scenefx) when 0.5 drops (in another branch) | |
|
|
50 | - [ ] Add the ability for the compositor to read a custom path for configs | |
|
|
51 | - [ ] Add /etc/swindle/config.lua as a fallback path if $HOME/.config/swindle/config.lua is not found | |
|
|
52 | ||
|
|
53 | ||
|
|
54 | ## License | |
|
|
55 | ||
|
|
56 | GPL-v3, probably | |
| @@ -0,0 +1,4 | |||
|
|
1 | ββββββββ ββ ββ | |
|
|
2 | ββ ββ ββ ββ | |
|
|
3 | ββ ββ ββ ββ | |
|
|
4 | ββββ ββββββββββ | |
| @@ -0,0 +1,6 | |||
|
|
1 | static void dwindle(Monitor *m); | |
|
|
2 | ||
|
|
3 | static const Layout layouts[] = { | |
|
|
4 | {"><>", NULL}, | |
|
|
5 | {"[T]", dwindle}, | |
|
|
6 | }; | |
| @@ -0,0 +1,31 | |||
|
|
1 | _VERSION = 0.1 | |
|
|
2 | VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)` | |
|
|
3 | ||
|
|
4 | PKG_CONFIG = pkg-config | |
|
|
5 | ||
|
|
6 | # paths | |
|
|
7 | PREFIX = /usr/local | |
|
|
8 | MANDIR = $(PREFIX)/share/man | |
|
|
9 | DATDIR = $(PREFIX)/share | |
|
|
10 | ||
|
|
11 | WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.20` | |
|
|
12 | WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.20` | |
|
|
13 | ||
|
|
14 | # Allow using an alternative wlroots installation | |
|
|
15 | #WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \ | |
|
|
16 | # -I$(PWD)/wlroots/include | |
|
|
17 | #WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/build -L$(PWD)/wlroots/build -lwlroots-0.19 | |
|
|
18 | ||
|
|
19 | #XWAYLAND = | |
|
|
20 | #XLIBS = | |
|
|
21 | # Uncomment to build XWayland support | |
|
|
22 | XWAYLAND = -DXWAYLAND | |
|
|
23 | XLIBS = xcb xcb-icccm | |
|
|
24 | ||
|
|
25 | # lua | |
|
|
26 | LUA_PKG = lua5.4 | |
|
|
27 | ||
|
|
28 | PKGS = wayland-server xkbcommon libinput $(LUA_PKG) $(XLIBS) | |
|
|
29 | ||
|
|
30 | # Requires C11: _Alignas and anonymous unions in wlroots headers. | |
|
|
31 | CC = cc | |
| @@ -0,0 +1,101 | |||
|
|
1 | sloppy_focus = true | |
|
|
2 | bypass_surface_visibility = false | |
|
|
3 | log_level = "error" -- "silent", "error", "info", "debug" | |
|
|
4 | ||
|
|
5 | appearance = { | |
|
|
6 | border_px = 2, | |
|
|
7 | gaps = 10, -- 0 = no gaps. simple as. | |
|
|
8 | smart_gaps = false, | |
|
|
9 | ||
|
|
10 | root_color = 0x222222ff, | |
|
|
11 | border_color = 0x00000000, | |
|
|
12 | focus_color = 0xe8e8e8ff, | |
|
|
13 | urgent_color = 0xff0000ff, | |
|
|
14 | ||
|
|
15 | fullscreen_bg = 0x000000ff, | |
|
|
16 | } | |
|
|
17 | ||
|
|
18 | ||
|
|
19 | -- Note: the entire input section requires you to restart | |
|
|
20 | -- the compositor once changed | |
|
|
21 | input = { | |
|
|
22 | repeat_rate = 50, | |
|
|
23 | repeat_delay = 150, | |
|
|
24 | tap_to_click = true, | |
|
|
25 | tap_and_drag = true, | |
|
|
26 | drag_lock = true, | |
|
|
27 | natural_scrolling = false, | |
|
|
28 | disable_while_typing = true, | |
|
|
29 | left_handed = false, | |
|
|
30 | middle_button_emulation = false, | |
|
|
31 | scroll_method = "2fg", -- "2fg", "edge", "button" | |
|
|
32 | click_method = "button_areas", -- "button_areas", "clickfinger" | |
|
|
33 | accel_profile = "adaptive", -- "adaptive", "flat" | |
|
|
34 | accel_speed = 0.0, | |
|
|
35 | ||
|
|
36 | layout = "us", -- "us", "de", "de,us", ... | |
|
|
37 | -- variant = "nodeadkeys", | |
|
|
38 | -- options = "grp:alt_shift_toggle", | |
|
|
39 | } | |
|
|
40 | ||
|
|
41 | rules = { | |
|
|
42 | -- { app_id = "Gimp", floating = true, monitor = -1 }, | |
|
|
43 | -- { app_id = "firefox", tags = 1 << 8, floating = false, monitor = -1 }, | |
|
|
44 | } | |
|
|
45 | ||
|
|
46 | monitors = { | |
|
|
47 | -- catch-all rule; name = nil means match anything | |
|
|
48 | { name = nil, mfact = 0.55, nmaster = 1, scale = 1.0, | |
|
|
49 | layout = "dwindle", x = -1, y = -1 }, | |
|
|
50 | ||
|
|
51 | -- HiDPI laptop example: | |
|
|
52 | -- { name = "eDP-1", mfact = 0.5, nmaster = 1, scale = 2.0, | |
|
|
53 | -- layout = "dwindle", x = -1, y = -1 }, | |
|
|
54 | } | |
|
|
55 | ||
|
|
56 | -- autostart: it starts stuff in sequence | |
|
|
57 | autostart = { | |
|
|
58 | "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_SESSION_TYPE XDG_CURRENT_DESKTOP", | |
|
|
59 | "systemctl --user import-environment WAYLAND_DISPLAY XDG_SESSION_TYPE XDG_CURRENT_DESKTOP", | |
|
|
60 | "waybar", | |
|
|
61 | } | |
|
|
62 | ||
|
|
63 | ||
|
|
64 | keybinds = { | |
|
|
65 | { mods = {"logo"}, key = "q", action = "spawn", args = {"alacritty"} }, | |
|
|
66 | { mods = {"logo"}, key = "space", action = "spawn", args = {"wofi", "--show", "drun"} }, | |
|
|
67 | { mods = {"logo"}, key = "w", action = "killclient" }, | |
|
|
68 | { mods = {"logo"}, key = "v", action = "togglefloating" }, | |
|
|
69 | { mods = {"logo"}, key = "f", action = "togglefullscreen" }, | |
|
|
70 | { mods = {"logo"}, key = "g", action = "togglegaps" }, | |
|
|
71 | { mods = {"logo"}, key = "h", action = "focusdir", args = {"left"} }, | |
|
|
72 | { mods = {"logo"}, key = "j", action = "focusdir", args = {"down"} }, | |
|
|
73 | { mods = {"logo"}, key = "k", action = "focusdir", args = {"up"} }, | |
|
|
74 | { mods = {"logo"}, key = "l", action = "focusdir", args = {"right"} }, | |
|
|
75 | { mods = {"logo", "shift"}, key = "H", action = "swapdir", args = {"left"} }, | |
|
|
76 | { mods = {"logo", "shift"}, key = "J", action = "swapdir", args = {"down"} }, | |
|
|
77 | { mods = {"logo", "shift"}, key = "K", action = "swapdir", args = {"up"} }, | |
|
|
78 | { mods = {"logo", "shift"}, key = "L", action = "swapdir", args = {"right"} }, | |
|
|
79 | { mods = {"logo"}, key = "Tab", action = "view" }, | |
|
|
80 | { mods = {"logo"}, key = "0", action = "view", args = {"all"} }, | |
|
|
81 | { mods = {"logo"}, key = "comma", action = "focusmon", args = {"left"} }, | |
|
|
82 | { mods = {"logo"}, key = "period", action = "focusmon", args = {"right"} }, | |
|
|
83 | { mods = {"logo", "shift"}, key = "less", action = "tagmon", args = {"left"} }, | |
|
|
84 | { mods = {"logo", "shift"}, key = "greater", action = "tagmon", args = {"right"} }, | |
|
|
85 | { mods = {"logo", "shift"}, key = "e", action = "quit" }, | |
|
|
86 | } | |
|
|
87 | ||
|
|
88 | for i = 1, 9 do | |
|
|
89 | local key = tostring(i) | |
|
|
90 | local mask = 1 << (i - 1) | |
|
|
91 | table.insert(keybinds, { mods = {"logo"}, key = key, action = "view", args = {tostring(mask)} }) | |
|
|
92 | table.insert(keybinds, { mods = {"logo", "ctrl"}, key = key, action = "toggleview", args = {tostring(mask)} }) | |
|
|
93 | table.insert(keybinds, { mods = {"logo", "shift"}, key = key, action = "tag", args = {tostring(mask)} }) | |
|
|
94 | table.insert(keybinds, { mods = {"logo", "ctrl", "shift"}, key = key, action = "toggletag", args = {tostring(mask)} }) | |
|
|
95 | end | |
|
|
96 | ||
|
|
97 | buttons = { | |
|
|
98 | { mods = {"logo"}, button = "left", action = "moveresize", args = {"move"} }, | |
|
|
99 | { mods = {"logo"}, button = "middle", action = "togglefloating" }, | |
|
|
100 | { mods = {"logo"}, button = "right", action = "moveresize", args = {"resize"} }, | |
|
|
101 | } | |
| @@ -0,0 +1,61 | |||
|
|
1 | { | |
|
|
2 | "nodes": { | |
|
|
3 | "flake-utils": { | |
|
|
4 | "inputs": { | |
|
|
5 | "systems": "systems" | |
|
|
6 | }, | |
|
|
7 | "locked": { | |
|
|
8 | "lastModified": 1731533236, | |
|
|
9 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", | |
|
|
10 | "owner": "numtide", | |
|
|
11 | "repo": "flake-utils", | |
|
|
12 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", | |
|
|
13 | "type": "github" | |
|
|
14 | }, | |
|
|
15 | "original": { | |
|
|
16 | "owner": "numtide", | |
|
|
17 | "repo": "flake-utils", | |
|
|
18 | "type": "github" | |
|
|
19 | } | |
|
|
20 | }, | |
|
|
21 | "nixpkgs": { | |
|
|
22 | "locked": { | |
|
|
23 | "lastModified": 1786106723, | |
|
|
24 | "narHash": "sha256-zDSUbpoeo/9ZmD2+wXnzxoo1+uhL8vxc0b8yuYMKYq0=", | |
|
|
25 | "owner": "NixOS", | |
|
|
26 | "repo": "nixpkgs", | |
|
|
27 | "rev": "f13ff45afd1bb73e640eaa08a7066dbed07e3238", | |
|
|
28 | "type": "github" | |
|
|
29 | }, | |
|
|
30 | "original": { | |
|
|
31 | "owner": "NixOS", | |
|
|
32 | "ref": "nixos-unstable", | |
|
|
33 | "repo": "nixpkgs", | |
|
|
34 | "type": "github" | |
|
|
35 | } | |
|
|
36 | }, | |
|
|
37 | "root": { | |
|
|
38 | "inputs": { | |
|
|
39 | "flake-utils": "flake-utils", | |
|
|
40 | "nixpkgs": "nixpkgs" | |
|
|
41 | } | |
|
|
42 | }, | |
|
|
43 | "systems": { | |
|
|
44 | "locked": { | |
|
|
45 | "lastModified": 1681028828, | |
|
|
46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", | |
|
|
47 | "owner": "nix-systems", | |
|
|
48 | "repo": "default", | |
|
|
49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", | |
|
|
50 | "type": "github" | |
|
|
51 | }, | |
|
|
52 | "original": { | |
|
|
53 | "owner": "nix-systems", | |
|
|
54 | "repo": "default", | |
|
|
55 | "type": "github" | |
|
|
56 | } | |
|
|
57 | } | |
|
|
58 | }, | |
|
|
59 | "root": "root", | |
|
|
60 | "version": 7 | |
|
|
61 | } | |
| @@ -0,0 +1,65 | |||
|
|
1 | { | |
|
|
2 | description = "swindle: a dwl fork with Lua config, IPC, and ext-workspace support, plus its smsg client"; | |
|
|
3 | ||
|
|
4 | inputs = { | |
|
|
5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; | |
|
|
6 | flake-utils.url = "github:numtide/flake-utils"; | |
|
|
7 | }; | |
|
|
8 | ||
|
|
9 | outputs = { self, nixpkgs, flake-utils }: | |
|
|
10 | flake-utils.lib.eachDefaultSystem (system: | |
|
|
11 | let | |
|
|
12 | pkgs = nixpkgs.legacyPackages.${system}; | |
|
|
13 | in | |
|
|
14 | { | |
|
|
15 | packages.default = pkgs.stdenv.mkDerivation rec { | |
|
|
16 | pname = "swindle"; | |
|
|
17 | version = "0.1"; | |
|
|
18 | ||
|
|
19 | src = self; | |
|
|
20 | ||
|
|
21 | nativeBuildInputs = with pkgs; [ | |
|
|
22 | pkg-config | |
|
|
23 | wayland-scanner | |
|
|
24 | wayland-protocols | |
|
|
25 | ]; | |
|
|
26 | ||
|
|
27 | buildInputs = with pkgs; [ | |
|
|
28 | wayland | |
|
|
29 | wlroots_0_20 | |
|
|
30 | pixman | |
|
|
31 | libxkbcommon | |
|
|
32 | libinput | |
|
|
33 | lua5_4 | |
|
|
34 | libxcb | |
|
|
35 | libxcb-wm | |
|
|
36 | ]; | |
|
|
37 | ||
|
|
38 | enableParallelBuilding = true; | |
|
|
39 | ||
|
|
40 | postPatch = '' | |
|
|
41 | substituteInPlace Makefile \ | |
|
|
42 | --replace '$(DESTDIR)/etc/swindle' '$(DESTDIR)$(PREFIX)/etc/swindle' | |
|
|
43 | ''; | |
|
|
44 | ||
|
|
45 | makeFlags = [ "PREFIX=${placeholder "out"}" ]; | |
|
|
46 | ||
|
|
47 | meta = with pkgs.lib; { | |
|
|
48 | description = "A dwl fork with Lua configuration, IPC support, and ext-workspace-v1"; | |
|
|
49 | license = with licenses; [ gpl3Only mit isc ]; | |
|
|
50 | platforms = platforms.linux; | |
|
|
51 | mainProgram = "swindle"; | |
|
|
52 | }; | |
|
|
53 | }; | |
|
|
54 | ||
|
|
55 | devShells.default = pkgs.mkShell { | |
|
|
56 | inputsFrom = [ self.packages.${system}.default ]; | |
|
|
57 | packages = with pkgs; [ pkg-config gdb ]; | |
|
|
58 | }; | |
|
|
59 | ||
|
|
60 | apps.default = flake-utils.lib.mkApp { | |
|
|
61 | drv = self.packages.${system}.default; | |
|
|
62 | }; | |
|
|
63 | }); | |
|
|
64 | } | |
|
|
65 | ||
| @@ -0,0 +1,447 | |||
|
|
1 | /* | |
|
|
2 | * Attempt to consolidate unavoidable suck into one file, away from src/swindle.c. This | |
|
|
3 | * file is not meant to be pretty. We use a .h file with static inline | |
|
|
4 | * functions instead of a separate .c module, or function pointers like sway, so | |
|
|
5 | * that they will simply compile out if the chosen #defines leave them unused. | |
|
|
6 | */ | |
|
|
7 | ||
|
|
8 | /* Leave these functions first; they're used in the others */ | |
|
|
9 | static inline int | |
|
|
10 | client_is_x11(Client *c) | |
|
|
11 | { | |
|
|
12 | #ifdef XWAYLAND | |
|
|
13 | return c->type == X11; | |
|
|
14 | #endif | |
|
|
15 | return 0; | |
|
|
16 | } | |
|
|
17 | ||
|
|
18 | static inline struct wlr_surface * | |
|
|
19 | client_surface(Client *c) | |
|
|
20 | { | |
|
|
21 | #ifdef XWAYLAND | |
|
|
22 | if (client_is_x11(c)) | |
|
|
23 | return c->surface.xwayland->surface; | |
|
|
24 | #endif | |
|
|
25 | return c->surface.xdg->surface; | |
|
|
26 | } | |
|
|
27 | ||
|
|
28 | static inline int | |
|
|
29 | toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl) | |
|
|
30 | { | |
|
|
31 | struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface; | |
|
|
32 | struct wlr_surface *root_surface; | |
|
|
33 | struct wlr_layer_surface_v1 *layer_surface; | |
|
|
34 | Client *c = NULL; | |
|
|
35 | LayerSurface *l = NULL; | |
|
|
36 | int type = -1; | |
|
|
37 | #ifdef XWAYLAND | |
|
|
38 | struct wlr_xwayland_surface *xsurface; | |
|
|
39 | #endif | |
|
|
40 | ||
|
|
41 | if (!s) | |
|
|
42 | return -1; | |
|
|
43 | root_surface = wlr_surface_get_root_surface(s); | |
|
|
44 | ||
|
|
45 | #ifdef XWAYLAND | |
|
|
46 | if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) { | |
|
|
47 | c = xsurface->data; | |
|
|
48 | type = c->type; | |
|
|
49 | goto end; | |
|
|
50 | } | |
|
|
51 | #endif | |
|
|
52 | ||
|
|
53 | if ((layer_surface = wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) { | |
|
|
54 | l = layer_surface->data; | |
|
|
55 | type = LayerShell; | |
|
|
56 | goto end; | |
|
|
57 | } | |
|
|
58 | ||
|
|
59 | xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface); | |
|
|
60 | while (xdg_surface) { | |
|
|
61 | tmp_xdg_surface = NULL; | |
|
|
62 | switch (xdg_surface->role) { | |
|
|
63 | case WLR_XDG_SURFACE_ROLE_POPUP: | |
|
|
64 | if (!xdg_surface->popup || !xdg_surface->popup->parent) | |
|
|
65 | return -1; | |
|
|
66 | ||
|
|
67 | tmp_xdg_surface = wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent); | |
|
|
68 | ||
|
|
69 | if (!tmp_xdg_surface) | |
|
|
70 | return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl); | |
|
|
71 | ||
|
|
72 | xdg_surface = tmp_xdg_surface; | |
|
|
73 | break; | |
|
|
74 | case WLR_XDG_SURFACE_ROLE_TOPLEVEL: | |
|
|
75 | c = xdg_surface->data; | |
|
|
76 | type = c->type; | |
|
|
77 | goto end; | |
|
|
78 | case WLR_XDG_SURFACE_ROLE_NONE: | |
|
|
79 | return -1; | |
|
|
80 | } | |
|
|
81 | } | |
|
|
82 | ||
|
|
83 | end: | |
|
|
84 | if (pl) | |
|
|
85 | *pl = l; | |
|
|
86 | if (pc) | |
|
|
87 | *pc = c; | |
|
|
88 | return type; | |
|
|
89 | } | |
|
|
90 | ||
|
|
91 | /* The others */ | |
|
|
92 | static inline void | |
|
|
93 | client_activate_surface(struct wlr_surface *s, int activated) | |
|
|
94 | { | |
|
|
95 | struct wlr_xdg_toplevel *toplevel; | |
|
|
96 | #ifdef XWAYLAND | |
|
|
97 | struct wlr_xwayland_surface *xsurface; | |
|
|
98 | if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) { | |
|
|
99 | wlr_xwayland_surface_activate(xsurface, activated); | |
|
|
100 | return; | |
|
|
101 | } | |
|
|
102 | #endif | |
|
|
103 | if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s))) | |
|
|
104 | wlr_xdg_toplevel_set_activated(toplevel, activated); | |
|
|
105 | } | |
|
|
106 | ||
|
|
107 | static inline uint32_t | |
|
|
108 | client_set_bounds(Client *c, int32_t width, int32_t height) | |
|
|
109 | { | |
|
|
110 | #ifdef XWAYLAND | |
|
|
111 | if (client_is_x11(c)) | |
|
|
112 | return 0; | |
|
|
113 | #endif | |
|
|
114 | if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= | |
|
|
115 | XDG_TOPLEVEL_STATE_TILED_BOTTOM_SINCE_VERSION && width >= 0 && height >= 0 | |
|
|
116 | && (c->bounds.width != width || c->bounds.height != height)) { | |
|
|
117 | c->bounds.width = width; | |
|
|
118 | c->bounds.height = height; | |
|
|
119 | return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height); | |
|
|
120 | } | |
|
|
121 | return 0; | |
|
|
122 | } | |
|
|
123 | ||
|
|
124 | static inline const char * | |
|
|
125 | client_get_appid(Client *c) | |
|
|
126 | { | |
|
|
127 | #ifdef XWAYLAND | |
|
|
128 | if (client_is_x11(c)) | |
|
|
129 | return c->surface.xwayland->class ? c->surface.xwayland->class : "broken"; | |
|
|
130 | #endif | |
|
|
131 | return c->surface.xdg->toplevel->app_id ? c->surface.xdg->toplevel->app_id : "broken"; | |
|
|
132 | } | |
|
|
133 | ||
|
|
134 | static inline void | |
|
|
135 | client_get_clip(Client *c, struct wlr_box *clip) | |
|
|
136 | { | |
|
|
137 | *clip = (struct wlr_box){ | |
|
|
138 | .x = 0, | |
|
|
139 | .y = 0, | |
|
|
140 | .width = c->geom.width - c->bw, | |
|
|
141 | .height = c->geom.height - c->bw, | |
|
|
142 | }; | |
|
|
143 | ||
|
|
144 | #ifdef XWAYLAND | |
|
|
145 | if (client_is_x11(c)) | |
|
|
146 | return; | |
|
|
147 | #endif | |
|
|
148 | ||
|
|
149 | clip->x = c->surface.xdg->geometry.x; | |
|
|
150 | clip->y = c->surface.xdg->geometry.y; | |
|
|
151 | } | |
|
|
152 | ||
|
|
153 | static inline void | |
|
|
154 | client_get_geometry(Client *c, struct wlr_box *geom) | |
|
|
155 | { | |
|
|
156 | #ifdef XWAYLAND | |
|
|
157 | if (client_is_x11(c)) { | |
|
|
158 | geom->x = c->surface.xwayland->x; | |
|
|
159 | geom->y = c->surface.xwayland->y; | |
|
|
160 | geom->width = c->surface.xwayland->width; | |
|
|
161 | geom->height = c->surface.xwayland->height; | |
|
|
162 | return; | |
|
|
163 | } | |
|
|
164 | #endif | |
|
|
165 | *geom = c->surface.xdg->geometry; | |
|
|
166 | } | |
|
|
167 | ||
|
|
168 | static inline Client * | |
|
|
169 | client_get_parent(Client *c) | |
|
|
170 | { | |
|
|
171 | Client *p = NULL; | |
|
|
172 | #ifdef XWAYLAND | |
|
|
173 | if (client_is_x11(c)) { | |
|
|
174 | if (c->surface.xwayland->parent) | |
|
|
175 | toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); | |
|
|
176 | return p; | |
|
|
177 | } | |
|
|
178 | #endif | |
|
|
179 | if (c->surface.xdg->toplevel->parent) | |
|
|
180 | toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL); | |
|
|
181 | return p; | |
|
|
182 | } | |
|
|
183 | ||
|
|
184 | static inline int | |
|
|
185 | client_has_children(Client *c) | |
|
|
186 | { | |
|
|
187 | #ifdef XWAYLAND | |
|
|
188 | if (client_is_x11(c)) | |
|
|
189 | return !wl_list_empty(&c->surface.xwayland->children); | |
|
|
190 | #endif | |
|
|
191 | /* surface.xdg->link is never empty because it always contains at least the | |
|
|
192 | * surface itself. */ | |
|
|
193 | return wl_list_length(&c->surface.xdg->link) > 1; | |
|
|
194 | } | |
|
|
195 | ||
|
|
196 | static inline const char * | |
|
|
197 | client_get_title(Client *c) | |
|
|
198 | { | |
|
|
199 | #ifdef XWAYLAND | |
|
|
200 | if (client_is_x11(c)) | |
|
|
201 | return c->surface.xwayland->title ? c->surface.xwayland->title : "broken"; | |
|
|
202 | #endif | |
|
|
203 | return c->surface.xdg->toplevel->title ? c->surface.xdg->toplevel->title : "broken"; | |
|
|
204 | } | |
|
|
205 | ||
|
|
206 | static inline int | |
|
|
207 | client_is_float_type(Client *c) | |
|
|
208 | { | |
|
|
209 | struct wlr_xdg_toplevel *toplevel; | |
|
|
210 | struct wlr_xdg_toplevel_state state; | |
|
|
211 | ||
|
|
212 | #ifdef XWAYLAND | |
|
|
213 | if (client_is_x11(c)) { | |
|
|
214 | struct wlr_xwayland_surface *surface = c->surface.xwayland; | |
|
|
215 | xcb_size_hints_t *size_hints = surface->size_hints; | |
|
|
216 | if (surface->modal) | |
|
|
217 | return 1; | |
|
|
218 | ||
|
|
219 | if (wlr_xwayland_surface_has_window_type(surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG) | |
|
|
220 | || wlr_xwayland_surface_has_window_type(surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH) | |
|
|
221 | || wlr_xwayland_surface_has_window_type(surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR) | |
|
|
222 | || wlr_xwayland_surface_has_window_type(surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY)) { | |
|
|
223 | return 1; | |
|
|
224 | } | |
|
|
225 | ||
|
|
226 | return size_hints && size_hints->min_width > 0 && size_hints->min_height > 0 | |
|
|
227 | && (size_hints->max_width == size_hints->min_width | |
|
|
228 | || size_hints->max_height == size_hints->min_height); | |
|
|
229 | } | |
|
|
230 | #endif | |
|
|
231 | ||
|
|
232 | toplevel = c->surface.xdg->toplevel; | |
|
|
233 | state = toplevel->current; | |
|
|
234 | return toplevel->parent || (state.min_width != 0 && state.min_height != 0 | |
|
|
235 | && (state.min_width == state.max_width | |
|
|
236 | || state.min_height == state.max_height)); | |
|
|
237 | } | |
|
|
238 | ||
|
|
239 | static inline int | |
|
|
240 | client_is_rendered_on_mon(Client *c, Monitor *m) | |
|
|
241 | { | |
|
|
242 | /* This is needed for when you don't want to check formal assignment, | |
|
|
243 | * but rather actual displaying of the pixels. | |
|
|
244 | * Usually VISIBLEON suffices and is also faster. */ | |
|
|
245 | struct wlr_surface_output *s; | |
|
|
246 | int unused_lx, unused_ly; | |
|
|
247 | if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly)) | |
|
|
248 | return 0; | |
|
|
249 | wl_list_for_each(s, &client_surface(c)->current_outputs, link) | |
|
|
250 | if (s->output == m->wlr_output) | |
|
|
251 | return 1; | |
|
|
252 | return 0; | |
|
|
253 | } | |
|
|
254 | ||
|
|
255 | static inline int | |
|
|
256 | client_is_stopped(Client *c) | |
|
|
257 | { | |
|
|
258 | int pid; | |
|
|
259 | siginfo_t in = {0}; | |
|
|
260 | #ifdef XWAYLAND | |
|
|
261 | if (client_is_x11(c)) | |
|
|
262 | return 0; | |
|
|
263 | #endif | |
|
|
264 | ||
|
|
265 | wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); | |
|
|
266 | if (waitid(P_PID, pid, &in, WNOHANG|WCONTINUED|WSTOPPED|WNOWAIT) < 0) { | |
|
|
267 | /* This process is not our child process, while is very unlikely that | |
|
|
268 | * it is stopped, in order to do not skip frames, assume that it is. */ | |
|
|
269 | if (errno == ECHILD) | |
|
|
270 | return 1; | |
|
|
271 | } else if (in.si_pid) { | |
|
|
272 | if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED) | |
|
|
273 | return 1; | |
|
|
274 | if (in.si_code == CLD_CONTINUED) | |
|
|
275 | return 0; | |
|
|
276 | } | |
|
|
277 | ||
|
|
278 | return 0; | |
|
|
279 | } | |
|
|
280 | ||
|
|
281 | static inline int | |
|
|
282 | client_is_unmanaged(Client *c) | |
|
|
283 | { | |
|
|
284 | #ifdef XWAYLAND | |
|
|
285 | if (client_is_x11(c)) | |
|
|
286 | return c->surface.xwayland->override_redirect; | |
|
|
287 | #endif | |
|
|
288 | return 0; | |
|
|
289 | } | |
|
|
290 | ||
|
|
291 | static inline void | |
|
|
292 | client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb) | |
|
|
293 | { | |
|
|
294 | if (kb) | |
|
|
295 | wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes, | |
|
|
296 | kb->num_keycodes, &kb->modifiers); | |
|
|
297 | else | |
|
|
298 | wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); | |
|
|
299 | } | |
|
|
300 | ||
|
|
301 | static inline void | |
|
|
302 | client_send_close(Client *c) | |
|
|
303 | { | |
|
|
304 | #ifdef XWAYLAND | |
|
|
305 | if (client_is_x11(c)) { | |
|
|
306 | wlr_xwayland_surface_close(c->surface.xwayland); | |
|
|
307 | return; | |
|
|
308 | } | |
|
|
309 | #endif | |
|
|
310 | wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel); | |
|
|
311 | } | |
|
|
312 | ||
|
|
313 | static inline void | |
|
|
314 | client_set_border_color(Client *c, const float inner[static 4], const float outer[static 4]) | |
|
|
315 | { | |
|
|
316 | int i; | |
|
|
317 | for (i = 0; i < 4; i++) { | |
|
|
318 | wlr_scene_rect_set_color(c->inner_border[i], inner); | |
|
|
319 | wlr_scene_rect_set_color(c->outer_border[i], outer); | |
|
|
320 | } | |
|
|
321 | } | |
|
|
322 | ||
|
|
323 | ||
|
|
324 | /* Opacity black magic I cooked up half asleep. Idk how this works so uhm | |
|
|
325 | * baii */ | |
|
|
326 | ||
|
|
327 | static inline void | |
|
|
328 | client_node_apply_opacity(struct wlr_scene_node *node, float opacity) | |
|
|
329 | { | |
|
|
330 | struct wlr_scene_tree *tree; | |
|
|
331 | struct wlr_scene_node *child; | |
|
|
332 | ||
|
|
333 | if (!node->enabled && node->type != WLR_SCENE_NODE_TREE) | |
|
|
334 | return; | |
|
|
335 | ||
|
|
336 | switch (node->type) { | |
|
|
337 | case WLR_SCENE_NODE_BUFFER: | |
|
|
338 | wlr_scene_buffer_set_opacity(wlr_scene_buffer_from_node(node), opacity); | |
|
|
339 | break; | |
|
|
340 | case WLR_SCENE_NODE_TREE: | |
|
|
341 | tree = wlr_scene_tree_from_node(node); | |
|
|
342 | wl_list_for_each(child, &tree->children, link) | |
|
|
343 | client_node_apply_opacity(child, opacity); | |
|
|
344 | break; | |
|
|
345 | case WLR_SCENE_NODE_RECT: | |
|
|
346 | default: | |
|
|
347 | break; | |
|
|
348 | } | |
|
|
349 | } | |
|
|
350 | ||
|
|
351 | static inline void | |
|
|
352 | client_apply_opacity(Client *c) | |
|
|
353 | { | |
|
|
354 | client_node_apply_opacity(&c->scene_surface->node, c->isfullscreen ? 1.0f : c->opacity); | |
|
|
355 | } | |
|
|
356 | ||
|
|
357 | static inline void | |
|
|
358 | client_set_opacity(Client *c, float opacity) | |
|
|
359 | { | |
|
|
360 | c->opacity = opacity; | |
|
|
361 | client_apply_opacity(c); | |
|
|
362 | } | |
|
|
363 | ||
|
|
364 | static inline void | |
|
|
365 | client_set_fullscreen(Client *c, int fullscreen) | |
|
|
366 | { | |
|
|
367 | #ifdef XWAYLAND | |
|
|
368 | if (client_is_x11(c)) { | |
|
|
369 | wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen); | |
|
|
370 | return; | |
|
|
371 | } | |
|
|
372 | #endif | |
|
|
373 | wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen); | |
|
|
374 | } | |
|
|
375 | ||
|
|
376 | static inline void | |
|
|
377 | client_set_scale(struct wlr_surface *s, float scale) | |
|
|
378 | { | |
|
|
379 | wlr_fractional_scale_v1_notify_scale(s, scale); | |
|
|
380 | wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale)); | |
|
|
381 | } | |
|
|
382 | ||
|
|
383 | static inline uint32_t | |
|
|
384 | client_set_size(Client *c, uint32_t width, uint32_t height) | |
|
|
385 | { | |
|
|
386 | #ifdef XWAYLAND | |
|
|
387 | if (client_is_x11(c)) { | |
|
|
388 | wlr_xwayland_surface_configure(c->surface.xwayland, | |
|
|
389 | c->geom.x + c->bw, c->geom.y + c->bw, width, height); | |
|
|
390 | return 0; | |
|
|
391 | } | |
|
|
392 | #endif | |
|
|
393 | if ((int32_t)width == c->surface.xdg->toplevel->current.width | |
|
|
394 | && (int32_t)height == c->surface.xdg->toplevel->current.height) | |
|
|
395 | return 0; | |
|
|
396 | return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, (int32_t)height); | |
|
|
397 | } | |
|
|
398 | ||
|
|
399 | static inline void | |
|
|
400 | client_set_tiled(Client *c, uint32_t edges) | |
|
|
401 | { | |
|
|
402 | #ifdef XWAYLAND | |
|
|
403 | if (client_is_x11(c)) { | |
|
|
404 | wlr_xwayland_surface_set_maximized(c->surface.xwayland, | |
|
|
405 | edges != WLR_EDGE_NONE, edges != WLR_EDGE_NONE); | |
|
|
406 | return; | |
|
|
407 | } | |
|
|
408 | #endif | |
|
|
409 | if (wl_resource_get_version(c->surface.xdg->toplevel->resource) | |
|
|
410 | >= XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { | |
|
|
411 | wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); | |
|
|
412 | } else { | |
|
|
413 | wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, edges != WLR_EDGE_NONE); | |
|
|
414 | } | |
|
|
415 | } | |
|
|
416 | ||
|
|
417 | static inline void | |
|
|
418 | client_set_suspended(Client *c, int suspended) | |
|
|
419 | { | |
|
|
420 | #ifdef XWAYLAND | |
|
|
421 | if (client_is_x11(c)) | |
|
|
422 | return; | |
|
|
423 | #endif | |
|
|
424 | ||
|
|
425 | wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); | |
|
|
426 | } | |
|
|
427 | ||
|
|
428 | static inline int | |
|
|
429 | client_wants_focus(Client *c) | |
|
|
430 | { | |
|
|
431 | #ifdef XWAYLAND | |
|
|
432 | return client_is_unmanaged(c) | |
|
|
433 | && wlr_xwayland_surface_override_redirect_wants_focus(c->surface.xwayland) | |
|
|
434 | && wlr_xwayland_surface_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE; | |
|
|
435 | #endif | |
|
|
436 | return 0; | |
|
|
437 | } | |
|
|
438 | ||
|
|
439 | static inline int | |
|
|
440 | client_wants_fullscreen(Client *c) | |
|
|
441 | { | |
|
|
442 | #ifdef XWAYLAND | |
|
|
443 | if (client_is_x11(c)) | |
|
|
444 | return c->surface.xwayland->fullscreen; | |
|
|
445 | #endif | |
|
|
446 | return c->surface.xdg->toplevel->requested.fullscreen; | |
|
|
447 | } | |
| @@ -0,0 +1,284 | |||
|
|
1 | #include "dwl-ipc-unstable-v2-protocol.h" | |
|
|
2 | ||
|
|
3 | /* Forward declarations for dwl.c static functions */ | |
|
|
4 | ||
|
|
5 | static void arrange(Monitor *m); | |
|
|
6 | static void focusclient(Client *c, int lift); | |
|
|
7 | static Client *focustop(Monitor *m); | |
|
|
8 | static void printstatus(void); | |
|
|
9 | ||
|
|
10 | /* globals */ | |
|
|
11 | ||
|
|
12 | static struct wl_global *ipc_global = NULL; | |
|
|
13 | /* All bound manager objects */ | |
|
|
14 | static struct wl_list ipc_managers; /* IpcManager.link */ | |
|
|
15 | ||
|
|
16 | typedef struct { | |
|
|
17 | struct wl_resource *resource; | |
|
|
18 | struct wl_list link; /* ipc_managers */ | |
|
|
19 | struct wl_list outputs; /* IpcOutput.link */ | |
|
|
20 | } IpcManager; | |
|
|
21 | ||
|
|
22 | typedef struct { | |
|
|
23 | struct wl_resource *resource; | |
|
|
24 | Monitor *mon; | |
|
|
25 | struct wl_list link; /* IpcManager.outputs */ | |
|
|
26 | } IpcOutput; | |
|
|
27 | ||
|
|
28 | /* helpers */ | |
|
|
29 | ||
|
|
30 | static IpcOutput * | |
|
|
31 | ipc_output_for_mon(IpcManager *mgr, Monitor *m) | |
|
|
32 | { | |
|
|
33 | IpcOutput *o; | |
|
|
34 | wl_list_for_each(o, &mgr->outputs, link) | |
|
|
35 | if (o->mon == m) | |
|
|
36 | return o; | |
|
|
37 | return NULL; | |
|
|
38 | } | |
|
|
39 | ||
|
|
40 | /* Send the full state of monitor m to one IpcOutput resource */ | |
|
|
41 | static void | |
|
|
42 | ipc_send_output_state(IpcOutput *ipc_out) | |
|
|
43 | { | |
|
|
44 | Monitor *m = ipc_out->mon; | |
|
|
45 | struct wl_resource *res = ipc_out->resource; | |
|
|
46 | Client *c; | |
|
|
47 | uint32_t occ = 0, urg = 0, sel_tags = 0; | |
|
|
48 | int tag, focused; | |
|
|
49 | ||
|
|
50 | /* Compute occupancy/urgency (same logic as printstatus, I think) */ | |
|
|
51 | wl_list_for_each(c, &clients, link) { | |
|
|
52 | if (c->mon != m) | |
|
|
53 | continue; | |
|
|
54 | occ |= c->tags; | |
|
|
55 | if (c->isurgent) | |
|
|
56 | urg |= c->tags; | |
|
|
57 | } | |
|
|
58 | ||
|
|
59 | c = focustop(m); | |
|
|
60 | sel_tags = c ? c->tags : 0; | |
|
|
61 | ||
|
|
62 | /* active */ | |
|
|
63 | zdwl_ipc_output_v2_send_active(res, m == selmon ? 1 : 0); | |
|
|
64 | ||
|
|
65 | /* per-tag state */ | |
|
|
66 | for (tag = 0; tag < TAGCOUNT; tag++) { | |
|
|
67 | uint32_t mask = 1u << tag; | |
|
|
68 | uint32_t state = ZDWL_IPC_OUTPUT_V2_TAG_STATE_NONE; | |
|
|
69 | uint32_t clients_on_tag = 0; | |
|
|
70 | ||
|
|
71 | if (m->tagset[m->seltags] & mask) | |
|
|
72 | state = ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE; | |
|
|
73 | if (urg & mask) | |
|
|
74 | state = ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT; | |
|
|
75 | if (occ & mask) | |
|
|
76 | clients_on_tag = 1; /* report β₯1, not exact count */ | |
|
|
77 | ||
|
|
78 | focused = (sel_tags & mask) ? 1 : 0; | |
|
|
79 | zdwl_ipc_output_v2_send_tag(res, tag, state, clients_on_tag, focused); | |
|
|
80 | } | |
|
|
81 | ||
|
|
82 | /* layout index */ | |
|
|
83 | { | |
|
|
84 | uint32_t i; | |
|
|
85 | for (i = 0; i < LENGTH(layouts); i++) | |
|
|
86 | if (&layouts[i] == m->lt[m->sellt]) | |
|
|
87 | break; | |
|
|
88 | zdwl_ipc_output_v2_send_layout(res, i); | |
|
|
89 | } | |
|
|
90 | ||
|
|
91 | /* layout symbol */ | |
|
|
92 | zdwl_ipc_output_v2_send_layout_symbol(res, m->ltsymbol); | |
|
|
93 | ||
|
|
94 | /* title/appid/fullscreen/floating */ | |
|
|
95 | if (c) { | |
|
|
96 | zdwl_ipc_output_v2_send_title(res, client_get_title(c)); | |
|
|
97 | zdwl_ipc_output_v2_send_appid(res, client_get_appid(c)); | |
|
|
98 | if (wl_resource_get_version(res) >= 2) { | |
|
|
99 | zdwl_ipc_output_v2_send_fullscreen(res, c->isfullscreen ? 1 : 0); | |
|
|
100 | zdwl_ipc_output_v2_send_floating(res, c->isfloating ? 1 : 0); | |
|
|
101 | } | |
|
|
102 | } else { | |
|
|
103 | zdwl_ipc_output_v2_send_title(res, ""); | |
|
|
104 | zdwl_ipc_output_v2_send_appid(res, ""); | |
|
|
105 | if (wl_resource_get_version(res) >= 2) { | |
|
|
106 | zdwl_ipc_output_v2_send_fullscreen(res, 0); | |
|
|
107 | zdwl_ipc_output_v2_send_floating(res, 0); | |
|
|
108 | } | |
|
|
109 | } | |
|
|
110 | ||
|
|
111 | /* frame β signals end of this batch of events */ | |
|
|
112 | zdwl_ipc_output_v2_send_frame(res); | |
|
|
113 | } | |
|
|
114 | ||
|
|
115 | /* Called instead of (or alongside) the old printstatus() */ | |
|
|
116 | static void | |
|
|
117 | ipc_printstatus(void) | |
|
|
118 | { | |
|
|
119 | IpcManager *mgr; | |
|
|
120 | Monitor *m; | |
|
|
121 | ||
|
|
122 | wl_list_for_each(mgr, &ipc_managers, link) { | |
|
|
123 | wl_list_for_each(m, &mons, link) { | |
|
|
124 | IpcOutput *out = ipc_output_for_mon(mgr, m); | |
|
|
125 | if (out) | |
|
|
126 | ipc_send_output_state(out); | |
|
|
127 | } | |
|
|
128 | } | |
|
|
129 | } | |
|
|
130 | ||
|
|
131 | /* zdwl_ipc_output_v2 requests */ | |
|
|
132 | ||
|
|
133 | static void | |
|
|
134 | ipc_output_handle_release(struct wl_client *client, struct wl_resource *resource) | |
|
|
135 | { | |
|
|
136 | wl_resource_destroy(resource); | |
|
|
137 | } | |
|
|
138 | ||
|
|
139 | static void | |
|
|
140 | ipc_output_handle_set_tags(struct wl_client *client, struct wl_resource *resource, | |
|
|
141 | uint32_t tagmask, uint32_t toggle_tagset) | |
|
|
142 | { | |
|
|
143 | IpcOutput *out = wl_resource_get_user_data(resource); | |
|
|
144 | Monitor *m = out->mon; | |
|
|
145 | if (!m) return; | |
|
|
146 | ||
|
|
147 | if (toggle_tagset) | |
|
|
148 | m->seltags ^= 1; | |
|
|
149 | m->tagset[m->seltags] = tagmask & TAGMASK; | |
|
|
150 | focusclient(focustop(m), 1); | |
|
|
151 | arrange(m); | |
|
|
152 | printstatus(); | |
|
|
153 | } | |
|
|
154 | ||
|
|
155 | static void | |
|
|
156 | ipc_output_handle_set_client_tags(struct wl_client *client, | |
|
|
157 | struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags) | |
|
|
158 | { | |
|
|
159 | IpcOutput *out = wl_resource_get_user_data(resource); | |
|
|
160 | Monitor *m = out->mon; | |
|
|
161 | Client *sel; | |
|
|
162 | uint32_t newtags; | |
|
|
163 | if (!m) return; | |
|
|
164 | ||
|
|
165 | sel = focustop(m); | |
|
|
166 | if (!sel) return; | |
|
|
167 | ||
|
|
168 | newtags = (sel->tags & and_tags) ^ xor_tags; | |
|
|
169 | if (!newtags) return; | |
|
|
170 | sel->tags = newtags; | |
|
|
171 | focusclient(focustop(m), 1); | |
|
|
172 | arrange(m); | |
|
|
173 | printstatus(); | |
|
|
174 | } | |
|
|
175 | ||
|
|
176 | static void | |
|
|
177 | ipc_output_handle_set_layout(struct wl_client *client, | |
|
|
178 | struct wl_resource *resource, uint32_t idx) | |
|
|
179 | { | |
|
|
180 | IpcOutput *out = wl_resource_get_user_data(resource); | |
|
|
181 | Monitor *m = out->mon; | |
|
|
182 | if (!m || idx >= LENGTH(layouts)) return; | |
|
|
183 | ||
|
|
184 | m->lt[m->sellt] = &layouts[idx]; | |
|
|
185 | strncpy(m->ltsymbol, layouts[idx].symbol, LENGTH(m->ltsymbol)); | |
|
|
186 | arrange(m); | |
|
|
187 | printstatus(); | |
|
|
188 | } | |
|
|
189 | ||
|
|
190 | static const struct zdwl_ipc_output_v2_interface ipc_output_impl = { | |
|
|
191 | .release = ipc_output_handle_release, | |
|
|
192 | .set_tags = ipc_output_handle_set_tags, | |
|
|
193 | .set_client_tags = ipc_output_handle_set_client_tags, | |
|
|
194 | .set_layout = ipc_output_handle_set_layout, | |
|
|
195 | }; | |
|
|
196 | ||
|
|
197 | static void | |
|
|
198 | ipc_output_destroy(struct wl_resource *resource) | |
|
|
199 | { | |
|
|
200 | IpcOutput *out = wl_resource_get_user_data(resource); | |
|
|
201 | wl_list_remove(&out->link); | |
|
|
202 | free(out); | |
|
|
203 | } | |
|
|
204 | ||
|
|
205 | /* zdwl_ipc_manager_v2 requests */ | |
|
|
206 | ||
|
|
207 | static void | |
|
|
208 | ipc_manager_handle_release(struct wl_client *client, struct wl_resource *resource) | |
|
|
209 | { | |
|
|
210 | wl_resource_destroy(resource); | |
|
|
211 | } | |
|
|
212 | ||
|
|
213 | static void | |
|
|
214 | ipc_manager_handle_get_output(struct wl_client *client, struct wl_resource *resource, | |
|
|
215 | uint32_t id, struct wl_resource *output_resource) | |
|
|
216 | { | |
|
|
217 | IpcManager *mgr = wl_resource_get_user_data(resource); | |
|
|
218 | struct wlr_output *wlr_out = wlr_output_from_resource(output_resource); | |
|
|
219 | Monitor *m = (wlr_out && wlr_out->data) ? wlr_out->data : NULL; | |
|
|
220 | ||
|
|
221 | IpcOutput *out = ecalloc(1, sizeof(*out)); | |
|
|
222 | out->mon = m; | |
|
|
223 | out->resource = wl_resource_create(client, &zdwl_ipc_output_v2_interface, | |
|
|
224 | wl_resource_get_version(resource), id); | |
|
|
225 | if (!out->resource) { | |
|
|
226 | free(out); | |
|
|
227 | wl_client_post_no_memory(client); | |
|
|
228 | return; | |
|
|
229 | } | |
|
|
230 | wl_resource_set_implementation(out->resource, &ipc_output_impl, | |
|
|
231 | out, ipc_output_destroy); | |
|
|
232 | wl_list_insert(&mgr->outputs, &out->link); | |
|
|
233 | ||
|
|
234 | if (m) | |
|
|
235 | ipc_send_output_state(out); | |
|
|
236 | } | |
|
|
237 | ||
|
|
238 | static const struct zdwl_ipc_manager_v2_interface ipc_manager_impl = { | |
|
|
239 | .release = ipc_manager_handle_release, | |
|
|
240 | .get_output = ipc_manager_handle_get_output, | |
|
|
241 | }; | |
|
|
242 | ||
|
|
243 | static void | |
|
|
244 | ipc_manager_destroy(struct wl_resource *resource) | |
|
|
245 | { | |
|
|
246 | IpcManager *mgr = wl_resource_get_user_data(resource); | |
|
|
247 | IpcOutput *out, *tmp; | |
|
|
248 | wl_list_for_each_safe(out, tmp, &mgr->outputs, link) | |
|
|
249 | wl_resource_destroy(out->resource); | |
|
|
250 | wl_list_remove(&mgr->link); | |
|
|
251 | free(mgr); | |
|
|
252 | } | |
|
|
253 | ||
|
|
254 | /* global bind */ | |
|
|
255 | ||
|
|
256 | static void | |
|
|
257 | ipc_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) | |
|
|
258 | { | |
|
|
259 | IpcManager *mgr = ecalloc(1, sizeof(*mgr)); | |
|
|
260 | wl_list_init(&mgr->outputs); | |
|
|
261 | mgr->resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, | |
|
|
262 | version, id); | |
|
|
263 | if (!mgr->resource) { | |
|
|
264 | free(mgr); | |
|
|
265 | wl_client_post_no_memory(client); | |
|
|
266 | return; | |
|
|
267 | } | |
|
|
268 | wl_resource_set_implementation(mgr->resource, &ipc_manager_impl, | |
|
|
269 | mgr, ipc_manager_destroy); | |
|
|
270 | wl_list_insert(&ipc_managers, &mgr->link); | |
|
|
271 | ||
|
|
272 | /* Announce tags and layouts */ | |
|
|
273 | zdwl_ipc_manager_v2_send_tags(mgr->resource, TAGCOUNT); | |
|
|
274 | for (uint32_t i = 0; i < LENGTH(layouts); i++) | |
|
|
275 | zdwl_ipc_manager_v2_send_layout(mgr->resource, layouts[i].symbol); | |
|
|
276 | } | |
|
|
277 | ||
|
|
278 | static void | |
|
|
279 | ipc_init(void) | |
|
|
280 | { | |
|
|
281 | wl_list_init(&ipc_managers); | |
|
|
282 | ipc_global = wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, | |
|
|
283 | 2, NULL, ipc_bind); | |
|
|
284 | } | |
| @@ -0,0 +1,210 | |||
|
|
1 | /* My shitty port of Mango's ext-workspace.h for my compositor; | |
|
|
2 | * thanks DreamMaoMao for doing most of the heavy lifting | |
|
|
3 | * by actually writing the thing, it didn't work the first | |
|
|
4 | * few tries and I barely have any idea how this code works anyway. | |
|
|
5 | * To say that it's the eighth wonder of the world | |
|
|
6 | * would be an understatement | |
|
|
7 | */ | |
|
|
8 | ||
|
|
9 | #include "wlr_ext_workspace_v1.h" | |
|
|
10 | ||
|
|
11 | #define EXT_WORKSPACE_CAPS \ | |
|
|
12 | (EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \ | |
|
|
13 | EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_DEACTIVATE) | |
|
|
14 | ||
|
|
15 | /* types */ | |
|
|
16 | ||
|
|
17 | struct ext_workspace { | |
|
|
18 | struct wl_list link; | |
|
|
19 | uint32_t tag; | |
|
|
20 | Monitor *m; | |
|
|
21 | struct wlr_ext_workspace_handle_v1 *handle; | |
|
|
22 | }; | |
|
|
23 | ||
|
|
24 | /* global */ | |
|
|
25 | ||
|
|
26 | static struct wlr_ext_workspace_manager_v1 *ext_workspace_manager; | |
|
|
27 | static struct wl_list ext_workspaces; | |
|
|
28 | static struct wl_listener ext_commit_listener; | |
|
|
29 | static struct wl_listener ext_destroy_listener; | |
|
|
30 | ||
|
|
31 | /* helpers */ | |
|
|
32 | ||
|
|
33 | ||
|
|
34 | static int | |
|
|
35 | get_tag_status(uint32_t tag, Monitor *m) | |
|
|
36 | { | |
|
|
37 | Client *c; | |
|
|
38 | uint32_t mask = 1 << (tag - 1); | |
|
|
39 | ||
|
|
40 | wl_list_for_each(c, &clients, link) { | |
|
|
41 | if (c->mon != m) | |
|
|
42 | continue; | |
|
|
43 | if (!(c->tags & mask)) | |
|
|
44 | continue; | |
|
|
45 | if (c->isurgent) | |
|
|
46 | return 2; | |
|
|
47 | return 1; | |
|
|
48 | } | |
|
|
49 | return 0; | |
|
|
50 | } | |
|
|
51 | ||
|
|
52 | static const char * | |
|
|
53 | tag_name(uint32_t tag) | |
|
|
54 | { | |
|
|
55 | static const char *names[] = { | |
|
|
56 | "1", "2", "3", "4", "5", "6", "7", "8", "9", | |
|
|
57 | }; | |
|
|
58 | if (tag >= 1 && tag <= LENGTH(names)) | |
|
|
59 | return names[tag - 1]; | |
|
|
60 | return "?"; | |
|
|
61 | } | |
|
|
62 | ||
|
|
63 | /* workspace lifecycle */ | |
|
|
64 | ||
|
|
65 | static void | |
|
|
66 | ext_workspace_destroy(struct ext_workspace *ws) | |
|
|
67 | { | |
|
|
68 | wlr_ext_workspace_handle_v1_destroy(ws->handle); | |
|
|
69 | wl_list_remove(&ws->link); | |
|
|
70 | free(ws); | |
|
|
71 | } | |
|
|
72 | ||
|
|
73 | static void | |
|
|
74 | ext_workspace_create(uint32_t tag, Monitor *m) | |
|
|
75 | { | |
|
|
76 | const char *name = tag_name(tag); | |
|
|
77 | ||
|
|
78 | struct ext_workspace *ws = ecalloc(1, sizeof(*ws)); | |
|
|
79 | ws->tag = tag; | |
|
|
80 | ws->m = m; | |
|
|
81 | ws->handle = wlr_ext_workspace_handle_v1_create( | |
|
|
82 | ext_workspace_manager, name, EXT_WORKSPACE_CAPS); | |
|
|
83 | ws->handle->data = ws; | |
|
|
84 | ||
|
|
85 | wlr_ext_workspace_handle_v1_set_group(ws->handle, m->ext_group); | |
|
|
86 | wlr_ext_workspace_handle_v1_set_name(ws->handle, name); | |
|
|
87 | ||
|
|
88 | wl_list_insert(ext_workspaces.prev, &ws->link); | |
|
|
89 | } | |
|
|
90 | ||
|
|
91 | /* monitor integration */ | |
|
|
92 | ||
|
|
93 | static void | |
|
|
94 | ext_workspace_createmon(Monitor *m) | |
|
|
95 | { | |
|
|
96 | uint32_t i; | |
|
|
97 | ||
|
|
98 | m->ext_group = wlr_ext_workspace_group_handle_v1_create( | |
|
|
99 | ext_workspace_manager, 0); | |
|
|
100 | wlr_ext_workspace_group_handle_v1_output_enter( | |
|
|
101 | m->ext_group, m->wlr_output); | |
|
|
102 | ||
|
|
103 | for (i = 1; i <= TAGCOUNT; i++) | |
|
|
104 | ext_workspace_create(i, m); | |
|
|
105 | } | |
|
|
106 | ||
|
|
107 | static void | |
|
|
108 | ext_workspace_cleanupmon(Monitor *m) | |
|
|
109 | { | |
|
|
110 | struct ext_workspace *ws, *tmp; | |
|
|
111 | wl_list_for_each_safe(ws, tmp, &ext_workspaces, link) | |
|
|
112 | if (ws->m == m) | |
|
|
113 | ext_workspace_destroy(ws); | |
|
|
114 | ||
|
|
115 | wlr_ext_workspace_group_handle_v1_output_leave( | |
|
|
116 | m->ext_group, m->wlr_output); | |
|
|
117 | wlr_ext_workspace_group_handle_v1_destroy(m->ext_group); | |
|
|
118 | m->ext_group = NULL; | |
|
|
119 | } | |
|
|
120 | ||
|
|
121 | /* status */ | |
|
|
122 | ||
|
|
123 | static void | |
|
|
124 | ext_workspace_printstatus(Monitor *m) | |
|
|
125 | { | |
|
|
126 | struct ext_workspace *ws; | |
|
|
127 | ||
|
|
128 | wl_list_for_each(ws, &ext_workspaces, link) { | |
|
|
129 | if (ws->m != m) | |
|
|
130 | continue; | |
|
|
131 | ||
|
|
132 | int status = get_tag_status(ws->tag, m); | |
|
|
133 | int active = !!(m->tagset[m->seltags] & (1 << (ws->tag - 1)) & TAGMASK); | |
|
|
134 | ||
|
|
135 | wlr_ext_workspace_handle_v1_set_urgent(ws->handle, status == 2); | |
|
|
136 | wlr_ext_workspace_handle_v1_set_hidden(ws->handle, 0); | |
|
|
137 | wlr_ext_workspace_handle_v1_set_active(ws->handle, active); | |
|
|
138 | } | |
|
|
139 | } | |
|
|
140 | ||
|
|
141 | /* commit handler */ | |
|
|
142 | ||
|
|
143 | static void | |
|
|
144 | handle_ext_commit(struct wl_listener *listener, void *data) | |
|
|
145 | { | |
|
|
146 | struct wlr_ext_workspace_v1_commit_event *event = data; | |
|
|
147 | struct wlr_ext_workspace_v1_request *req; | |
|
|
148 | ||
|
|
149 | wl_list_for_each(req, event->requests, link) { | |
|
|
150 | struct ext_workspace *ws = NULL; | |
|
|
151 | struct ext_workspace *w; | |
|
|
152 | ||
|
|
153 | switch (req->type) { | |
|
|
154 | case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE: | |
|
|
155 | if (!req->activate.workspace) | |
|
|
156 | break; | |
|
|
157 | wl_list_for_each(w, &ext_workspaces, link) { | |
|
|
158 | if (w->handle == req->activate.workspace) { | |
|
|
159 | ws = w; | |
|
|
160 | break; | |
|
|
161 | } | |
|
|
162 | } | |
|
|
163 | if (!ws) | |
|
|
164 | break; | |
|
|
165 | view(&(Arg){.ui = 1 << (ws->tag - 1)}); | |
|
|
166 | break; | |
|
|
167 | ||
|
|
168 | case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE: | |
|
|
169 | if (!req->deactivate.workspace) | |
|
|
170 | break; | |
|
|
171 | wl_list_for_each(w, &ext_workspaces, link) { | |
|
|
172 | if (w->handle == req->deactivate.workspace) { | |
|
|
173 | ws = w; | |
|
|
174 | break; | |
|
|
175 | } | |
|
|
176 | } | |
|
|
177 | if (!ws) | |
|
|
178 | break; | |
|
|
179 | toggleview(&(Arg){.ui = 1 << (ws->tag - 1)}); | |
|
|
180 | break; | |
|
|
181 | ||
|
|
182 | default: | |
|
|
183 | break; | |
|
|
184 | } | |
|
|
185 | } | |
|
|
186 | } | |
|
|
187 | ||
|
|
188 | /* init */ | |
|
|
189 | ||
|
|
190 | static void | |
|
|
191 | handle_ext_destroy(struct wl_listener *listener, void *data) | |
|
|
192 | { | |
|
|
193 | wl_list_remove(&ext_commit_listener.link); | |
|
|
194 | wl_list_remove(&ext_destroy_listener.link); | |
|
|
195 | } | |
|
|
196 | ||
|
|
197 | static void | |
|
|
198 | workspaces_init(void) | |
|
|
199 | { | |
|
|
200 | ext_workspace_manager = wlr_ext_workspace_manager_v1_create(dpy, 1); | |
|
|
201 | wl_list_init(&ext_workspaces); | |
|
|
202 | ||
|
|
203 | ext_commit_listener.notify = handle_ext_commit; | |
|
|
204 | wl_signal_add(&ext_workspace_manager->events.commit, | |
|
|
205 | &ext_commit_listener); | |
|
|
206 | ||
|
|
207 | ext_destroy_listener.notify = handle_ext_destroy; | |
|
|
208 | wl_signal_add(&ext_workspace_manager->events.destroy, | |
|
|
209 | &ext_destroy_listener); | |
|
|
210 | } | |
| @@ -0,0 +1,351 | |||
|
|
1 | swindle - wayland compositor | |
|
|
2 | ||
|
|
3 | Copyright Β© 2026 kantiankant | |
|
|
4 | ||
|
|
5 | See also the files LICENSE.dwl, LICENSE.dwm, | |
|
|
6 | LICENSE.tinywl, LICENSE.sway, LICENSE.wlroots, LICENSE.mangowm. | |
|
|
7 | ||
|
|
8 | This program is free software: you can redistribute it and/or modify | |
|
|
9 | it under the terms of the GNU General Public License as published by | |
|
|
10 | the Free Software Foundation, version 2 of the License. | |
|
|
11 | ||
|
|
12 | ---- | |
|
|
13 | ||
|
|
14 | GNU GENERAL PUBLIC LICENSE | |
|
|
15 | Version 2, June 1991 | |
|
|
16 | ||
|
|
17 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., | |
|
|
18 | <https://fsf.org/> | |
|
|
19 | Everyone is permitted to copy and distribute verbatim copies | |
|
|
20 | of this license document, but changing it is not allowed. | |
|
|
21 | ||
|
|
22 | Preamble | |
|
|
23 | ||
|
|
24 | The licenses for most software are designed to take away your | |
|
|
25 | freedom to share and change it. By contrast, the GNU General Public | |
|
|
26 | License is intended to guarantee your freedom to share and change free | |
|
|
27 | software--to make sure the software is free for all its users. This | |
|
|
28 | General Public License applies to most of the Free Software | |
|
|
29 | Foundation's software and to any other program whose authors commit to | |
|
|
30 | using it. (Some other Free Software Foundation software is covered by | |
|
|
31 | the GNU Lesser General Public License instead.) You can apply it to | |
|
|
32 | your programs, too. | |
|
|
33 | ||
|
|
34 | When we speak of free software, we are referring to freedom, not | |
|
|
35 | price. Our General Public Licenses are designed to make sure that you | |
|
|
36 | have the freedom to distribute copies of free software (and charge for | |
|
|
37 | this service if you wish), that you receive source code or can get it | |
|
|
38 | if you want it, that you can change the software or use pieces of it | |
|
|
39 | in new free programs; and that you know you can do these things. | |
|
|
40 | ||
|
|
41 | To protect your rights, we need to make restrictions that forbid | |
|
|
42 | anyone to deny you these rights or to ask you to surrender the rights. | |
|
|
43 | These restrictions translate to certain responsibilities for you if you | |
|
|
44 | distribute copies of the software, or if you modify it. | |
|
|
45 | ||
|
|
46 | For example, if you distribute copies of such a program, whether | |
|
|
47 | gratis or for a fee, you must give the recipients all the rights that | |
|
|
48 | you have. You must make sure that they, too, receive or can get the | |
|
|
49 | source code. And you must show them these terms so they know their | |
|
|
50 | rights. | |
|
|
51 | ||
|
|
52 | We protect your rights with two steps: (1) copyright the software, and | |
|
|
53 | (2) offer you this license which gives you legal permission to copy, | |
|
|
54 | distribute and/or modify the software. | |
|
|
55 | ||
|
|
56 | Also, for each author's protection and ours, we want to make certain | |
|
|
57 | that everyone understands that there is no warranty for this free | |
|
|
58 | software. If the software is modified by someone else and passed on, we | |
|
|
59 | want its recipients to know that what they have is not the original, so | |
|
|
60 | that any problems introduced by others will not reflect on the original | |
|
|
61 | authors' reputations. | |
|
|
62 | ||
|
|
63 | Finally, any free program is threatened constantly by software | |
|
|
64 | patents. We wish to avoid the danger that redistributors of a free | |
|
|
65 | program will individually obtain patent licenses, in effect making the | |
|
|
66 | program proprietary. To prevent this, we have made it clear that any | |
|
|
67 | patent must be licensed for everyone's free use or not licensed at all. | |
|
|
68 | ||
|
|
69 | The precise terms and conditions for copying, distribution and | |
|
|
70 | modification follow. | |
|
|
71 | ||
|
|
72 | GNU GENERAL PUBLIC LICENSE | |
|
|
73 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
|
|
74 | ||
|
|
75 | 0. This License applies to any program or other work which contains | |
|
|
76 | a notice placed by the copyright holder saying it may be distributed | |
|
|
77 | under the terms of this General Public License. The "Program", below, | |
|
|
78 | refers to any such program or work, and a "work based on the Program" | |
|
|
79 | means either the Program or any derivative work under copyright law: | |
|
|
80 | that is to say, a work containing the Program or a portion of it, | |
|
|
81 | either verbatim or with modifications and/or translated into another | |
|
|
82 | language. (Hereinafter, translation is included without limitation in | |
|
|
83 | the term "modification".) Each licensee is addressed as "you". | |
|
|
84 | ||
|
|
85 | Activities other than copying, distribution and modification are not | |
|
|
86 | covered by this License; they are outside its scope. The act of | |
|
|
87 | running the Program is not restricted, and the output from the Program | |
|
|
88 | is covered only if its contents constitute a work based on the | |
|
|
89 | Program (independent of having been made by running the Program). | |
|
|
90 | Whether that is true depends on what the Program does. | |
|
|
91 | ||
|
|
92 | 1. You may copy and distribute verbatim copies of the Program's | |
|
|
93 | source code as you receive it, in any medium, provided that you | |
|
|
94 | conspicuously and appropriately publish on each copy an appropriate | |
|
|
95 | copyright notice and disclaimer of warranty; keep intact all the | |
|
|
96 | notices that refer to this License and to the absence of any warranty; | |
|
|
97 | and give any other recipients of the Program a copy of this License | |
|
|
98 | along with the Program. | |
|
|
99 | ||
|
|
100 | You may charge a fee for the physical act of transferring a copy, and | |
|
|
101 | you may at your option offer warranty protection in exchange for a fee. | |
|
|
102 | ||
|
|
103 | 2. You may modify your copy or copies of the Program or any portion | |
|
|
104 | of it, thus forming a work based on the Program, and copy and | |
|
|
105 | distribute such modifications or work under the terms of Section 1 | |
|
|
106 | above, provided that you also meet all of these conditions: | |
|
|
107 | ||
|
|
108 | a) You must cause the modified files to carry prominent notices | |
|
|
109 | stating that you changed the files and the date of any change. | |
|
|
110 | ||
|
|
111 | b) You must cause any work that you distribute or publish, that in | |
|
|
112 | whole or in part contains or is derived from the Program or any | |
|
|
113 | part thereof, to be licensed as a whole at no charge to all third | |
|
|
114 | parties under the terms of this License. | |
|
|
115 | ||
|
|
116 | c) If the modified program normally reads commands interactively | |
|
|
117 | when run, you must cause it, when started running for such | |
|
|
118 | interactive use in the most ordinary way, to print or display an | |
|
|
119 | announcement including an appropriate copyright notice and a | |
|
|
120 | notice that there is no warranty (or else, saying that you provide | |
|
|
121 | a warranty) and that users may redistribute the program under | |
|
|
122 | these conditions, and telling the user how to view a copy of this | |
|
|
123 | License. (Exception: if the Program itself is interactive but | |
|
|
124 | does not normally print such an announcement, your work based on | |
|
|
125 | the Program is not required to print an announcement.) | |
|
|
126 | ||
|
|
127 | These requirements apply to the modified work as a whole. If | |
|
|
128 | identifiable sections of that work are not derived from the Program, | |
|
|
129 | and can be reasonably considered independent and separate works in | |
|
|
130 | themselves, then this License, and its terms, do not apply to those | |
|
|
131 | sections when you distribute them as separate works. But when you | |
|
|
132 | distribute the same sections as part of a whole which is a work based | |
|
|
133 | on the Program, the distribution of the whole must be on the terms of | |
|
|
134 | this License, whose permissions for other licensees extend to the | |
|
|
135 | entire whole, and thus to each and every part regardless of who wrote it. | |
|
|
136 | ||
|
|
137 | Thus, it is not the intent of this section to claim rights or contest | |
|
|
138 | your rights to work written entirely by you; rather, the intent is to | |
|
|
139 | exercise the right to control the distribution of derivative or | |
|
|
140 | collective works based on the Program. | |
|
|
141 | ||
|
|
142 | In addition, mere aggregation of another work not based on the Program | |
|
|
143 | with the Program (or with a work based on the Program) on a volume of | |
|
|
144 | a storage or distribution medium does not bring the other work under | |
|
|
145 | the scope of this License. | |
|
|
146 | ||
|
|
147 | 3. You may copy and distribute the Program (or a work based on it, | |
|
|
148 | under Section 2) in object code or executable form under the terms of | |
|
|
149 | Sections 1 and 2 above provided that you also do one of the following: | |
|
|
150 | ||
|
|
151 | a) Accompany it with the complete corresponding machine-readable | |
|
|
152 | source code, which must be distributed under the terms of Sections | |
|
|
153 | 1 and 2 above on a medium customarily used for software interchange; or, | |
|
|
154 | ||
|
|
155 | b) Accompany it with a written offer, valid for at least three | |
|
|
156 | years, to give any third party, for a charge no more than your | |
|
|
157 | cost of physically performing source distribution, a complete | |
|
|
158 | machine-readable copy of the corresponding source code, to be | |
|
|
159 | distributed under the terms of Sections 1 and 2 above on a medium | |
|
|
160 | customarily used for software interchange; or, | |
|
|
161 | ||
|
|
162 | c) Accompany it with the information you received as to the offer | |
|
|
163 | to distribute corresponding source code. (This alternative is | |
|
|
164 | allowed only for noncommercial distribution and only if you | |
|
|
165 | received the program in object code or executable form with such | |
|
|
166 | an offer, in accord with Subsection b above.) | |
|
|
167 | ||
|
|
168 | The source code for a work means the preferred form of the work for | |
|
|
169 | making modifications to it. For an executable work, complete source | |
|
|
170 | code means all the source code for all modules it contains, plus any | |
|
|
171 | associated interface definition files, plus the scripts used to | |
|
|
172 | control compilation and installation of the executable. However, as a | |
|
|
173 | special exception, the source code distributed need not include | |
|
|
174 | anything that is normally distributed (in either source or binary | |
|
|
175 | form) with the major components (compiler, kernel, and so on) of the | |
|
|
176 | operating system on which the executable runs, unless that component | |
|
|
177 | itself accompanies the executable. | |
|
|
178 | ||
|
|
179 | If distribution of executable or object code is made by offering | |
|
|
180 | access to copy from a designated place, then offering equivalent | |
|
|
181 | access to copy the source code from the same place counts as | |
|
|
182 | distribution of the source code, even though third parties are not | |
|
|
183 | compelled to copy the source along with the object code. | |
|
|
184 | ||
|
|
185 | 4. You may not copy, modify, sublicense, or distribute the Program | |
|
|
186 | except as expressly provided under this License. Any attempt | |
|
|
187 | otherwise to copy, modify, sublicense or distribute the Program is | |
|
|
188 | void, and will automatically terminate your rights under this License. | |
|
|
189 | However, parties who have received copies, or rights, from you under | |
|
|
190 | this License will not have their licenses terminated so long as such | |
|
|
191 | parties remain in full compliance. | |
|
|
192 | ||
|
|
193 | 5. You are not required to accept this License, since you have not | |
|
|
194 | signed it. However, nothing else grants you permission to modify or | |
|
|
195 | distribute the Program or its derivative works. These actions are | |
|
|
196 | prohibited by law if you do not accept this License. Therefore, by | |
|
|
197 | modifying or distributing the Program (or any work based on the | |
|
|
198 | Program), you indicate your acceptance of this License to do so, and | |
|
|
199 | all its terms and conditions for copying, distributing or modifying | |
|
|
200 | the Program or works based on it. | |
|
|
201 | ||
|
|
202 | 6. Each time you redistribute the Program (or any work based on the | |
|
|
203 | Program), the recipient automatically receives a license from the | |
|
|
204 | original licensor to copy, distribute or modify the Program subject to | |
|
|
205 | these terms and conditions. You may not impose any further | |
|
|
206 | restrictions on the recipients' exercise of the rights granted herein. | |
|
|
207 | You are not responsible for enforcing compliance by third parties to | |
|
|
208 | this License. | |
|
|
209 | ||
|
|
210 | 7. If, as a consequence of a court judgment or allegation of patent | |
|
|
211 | infringement or for any other reason (not limited to patent issues), | |
|
|
212 | conditions are imposed on you (whether by court order, agreement or | |
|
|
213 | otherwise) that contradict the conditions of this License, they do not | |
|
|
214 | excuse you from the conditions of this License. If you cannot | |
|
|
215 | distribute so as to satisfy simultaneously your obligations under this | |
|
|
216 | License and any other pertinent obligations, then as a consequence you | |
|
|
217 | may not distribute the Program at all. For example, if a patent | |
|
|
218 | license would not permit royalty-free redistribution of the Program by | |
|
|
219 | all those who receive copies directly or indirectly through you, then | |
|
|
220 | the only way you could satisfy both it and this License would be to | |
|
|
221 | refrain entirely from distribution of the Program. | |
|
|
222 | ||
|
|
223 | If any portion of this section is held invalid or unenforceable under | |
|
|
224 | any particular circumstance, the balance of the section is intended to | |
|
|
225 | apply and the section as a whole is intended to apply in other | |
|
|
226 | circumstances. | |
|
|
227 | ||
|
|
228 | It is not the purpose of this section to induce you to infringe any | |
|
|
229 | patents or other property right claims or to contest validity of any | |
|
|
230 | such claims; this section has the sole purpose of protecting the | |
|
|
231 | integrity of the free software distribution system, which is | |
|
|
232 | implemented by public license practices. Many people have made | |
|
|
233 | generous contributions to the wide range of software distributed | |
|
|
234 | through that system in reliance on consistent application of that | |
|
|
235 | system; it is up to the author/donor to decide if he or she is willing | |
|
|
236 | to distribute software through any other system and a licensee cannot | |
|
|
237 | impose that choice. | |
|
|
238 | ||
|
|
239 | This section is intended to make thoroughly clear what is believed to | |
|
|
240 | be a consequence of the rest of this License. | |
|
|
241 | ||
|
|
242 | 8. If the distribution and/or use of the Program is restricted in | |
|
|
243 | certain countries either by patents or by copyrighted interfaces, the | |
|
|
244 | original copyright holder who places the Program under this License | |
|
|
245 | may add an explicit geographical distribution limitation excluding | |
|
|
246 | those countries, so that distribution is permitted only in or among | |
|
|
247 | countries not thus excluded. In such case, this License incorporates | |
|
|
248 | the limitation as if written in the body of this License. | |
|
|
249 | ||
|
|
250 | 9. The Free Software Foundation may publish revised and/or new versions | |
|
|
251 | of the General Public License from time to time. Such new versions will | |
|
|
252 | be similar in spirit to the present version, but may differ in detail to | |
|
|
253 | address new problems or concerns. | |
|
|
254 | ||
|
|
255 | Each version is given a distinguishing version number. If the Program | |
|
|
256 | specifies a version number of this License which applies to it and "any | |
|
|
257 | later version", you have the option of following the terms and conditions | |
|
|
258 | either of that version or of any later version published by the Free | |
|
|
259 | Software Foundation. If the Program does not specify a version number of | |
|
|
260 | this License, you may choose any version ever published by the Free Software | |
|
|
261 | Foundation. | |
|
|
262 | ||
|
|
263 | 10. If you wish to incorporate parts of the Program into other free | |
|
|
264 | programs whose distribution conditions are different, write to the author | |
|
|
265 | to ask for permission. For software which is copyrighted by the Free | |
|
|
266 | Software Foundation, write to the Free Software Foundation; we sometimes | |
|
|
267 | make exceptions for this. Our decision will be guided by the two goals | |
|
|
268 | of preserving the free status of all derivatives of our free software and | |
|
|
269 | of promoting the sharing and reuse of software generally. | |
|
|
270 | ||
|
|
271 | NO WARRANTY | |
|
|
272 | ||
|
|
273 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |
|
|
274 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |
|
|
275 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |
|
|
276 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |
|
|
277 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
|
|
278 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |
|
|
279 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |
|
|
280 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |
|
|
281 | REPAIR OR CORRECTION. | |
|
|
282 | ||
|
|
283 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |
|
|
284 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |
|
|
285 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |
|
|
286 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |
|
|
287 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |
|
|
288 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |
|
|
289 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |
|
|
290 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |
|
|
291 | POSSIBILITY OF SUCH DAMAGES. | |
|
|
292 | ||
|
|
293 | END OF TERMS AND CONDITIONS | |
|
|
294 | ||
|
|
295 | How to Apply These Terms to Your New Programs | |
|
|
296 | ||
|
|
297 | If you develop a new program, and you want it to be of the greatest | |
|
|
298 | possible use to the public, the best way to achieve this is to make it | |
|
|
299 | free software which everyone can redistribute and change under these terms. | |
|
|
300 | ||
|
|
301 | To do so, attach the following notices to the program. It is safest | |
|
|
302 | to attach them to the start of each source file to most effectively | |
|
|
303 | convey the exclusion of warranty; and each file should have at least | |
|
|
304 | the "copyright" line and a pointer to where the full notice is found. | |
|
|
305 | ||
|
|
306 | <one line to give the program's name and a brief idea of what it does.> | |
|
|
307 | Copyright (C) <year> <name of author> | |
|
|
308 | ||
|
|
309 | This program is free software; you can redistribute it and/or modify | |
|
|
310 | it under the terms of the GNU General Public License as published by | |
|
|
311 | the Free Software Foundation; either version 2 of the License, or | |
|
|
312 | (at your option) any later version. | |
|
|
313 | ||
|
|
314 | This program is distributed in the hope that it will be useful, | |
|
|
315 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
|
316 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
|
317 | GNU General Public License for more details. | |
|
|
318 | ||
|
|
319 | You should have received a copy of the GNU General Public License along | |
|
|
320 | with this program; if not, see <https://www.gnu.org/licenses/>. | |
|
|
321 | ||
|
|
322 | Also add information on how to contact you by electronic and paper mail. | |
|
|
323 | ||
|
|
324 | If the program is interactive, make it output a short notice like this | |
|
|
325 | when it starts in an interactive mode: | |
|
|
326 | ||
|
|
327 | Gnomovision version 69, Copyright (C) year name of author | |
|
|
328 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |
|
|
329 | This is free software, and you are welcome to redistribute it | |
|
|
330 | under certain conditions; type `show c' for details. | |
|
|
331 | ||
|
|
332 | The hypothetical commands `show w' and `show c' should show the appropriate | |
|
|
333 | parts of the General Public License. Of course, the commands you use may | |
|
|
334 | be called something other than `show w' and `show c'; they could even be | |
|
|
335 | mouse-clicks or menu items--whatever suits your program. | |
|
|
336 | ||
|
|
337 | You should also get your employer (if you work as a programmer) or your | |
|
|
338 | school, if any, to sign a "copyright disclaimer" for the program, if | |
|
|
339 | necessary. Here is a sample; alter the names: | |
|
|
340 | ||
|
|
341 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |
|
|
342 | `Gnomovision' (which makes passes at compilers) written by James Hacker. | |
|
|
343 | ||
|
|
344 | <signature of Moe Ghoul>, 1 April 1989 | |
|
|
345 | Moe Ghoul, President of Vice | |
|
|
346 | ||
|
|
347 | This General Public License does not permit incorporating your program into | |
|
|
348 | proprietary programs. If your program is a subroutine library, you may | |
|
|
349 | consider it more useful to permit linking proprietary applications with the | |
|
|
350 | library. If this is what you want to do, use the GNU Lesser General | |
|
|
351 | Public License instead of this License. | |
| This diff has been collapsed as it changes many lines, (692 lines changed) Show them Hide them | |||
| @@ -0,0 +1,692 | |||
|
|
1 | dwl - dwm for Wayland | |
|
|
2 | ||
|
|
3 | Copyright Β© 2020 dwl team | |
|
|
4 | ||
|
|
5 | See also the files LICENSE.tinywl, LICENSE.dwm and LICENSE.sway. | |
|
|
6 | ||
|
|
7 | This program is free software: you can redistribute it and/or modify | |
|
|
8 | it under the terms of the GNU General Public License as published by | |
|
|
9 | the Free Software Foundation, either version 3 of the License, or | |
|
|
10 | (at your option) any later version. | |
|
|
11 | ||
|
|
12 | This program is distributed in the hope that it will be useful, | |
|
|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
|
15 | GNU General Public License for more details. | |
|
|
16 | ||
|
|
17 | ---- | |
|
|
18 | ||
|
|
19 | GNU GENERAL PUBLIC LICENSE | |
|
|
20 | Version 3, 29 June 2007 | |
|
|
21 | ||
|
|
22 | Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> | |
|
|
23 | Everyone is permitted to copy and distribute verbatim copies | |
|
|
24 | of this license document, but changing it is not allowed. | |
|
|
25 | ||
|
|
26 | Preamble | |
|
|
27 | ||
|
|
28 | The GNU General Public License is a free, copyleft license for | |
|
|
29 | software and other kinds of works. | |
|
|
30 | ||
|
|
31 | The licenses for most software and other practical works are designed | |
|
|
32 | to take away your freedom to share and change the works. By contrast, | |
|
|
33 | the GNU General Public License is intended to guarantee your freedom to | |
|
|
34 | share and change all versions of a program--to make sure it remains free | |
|
|
35 | software for all its users. We, the Free Software Foundation, use the | |
|
|
36 | GNU General Public License for most of our software; it applies also to | |
|
|
37 | any other work released this way by its authors. You can apply it to | |
|
|
38 | your programs, too. | |
|
|
39 | ||
|
|
40 | When we speak of free software, we are referring to freedom, not | |
|
|
41 | price. Our General Public Licenses are designed to make sure that you | |
|
|
42 | have the freedom to distribute copies of free software (and charge for | |
|
|
43 | them if you wish), that you receive source code or can get it if you | |
|
|
44 | want it, that you can change the software or use pieces of it in new | |
|
|
45 | free programs, and that you know you can do these things. | |
|
|
46 | ||
|
|
47 | To protect your rights, we need to prevent others from denying you | |
|
|
48 | these rights or asking you to surrender the rights. Therefore, you have | |
|
|
49 | certain responsibilities if you distribute copies of the software, or if | |
|
|
50 | you modify it: responsibilities to respect the freedom of others. | |
|
|
51 | ||
|
|
52 | For example, if you distribute copies of such a program, whether | |
|
|
53 | gratis or for a fee, you must pass on to the recipients the same | |
|
|
54 | freedoms that you received. You must make sure that they, too, receive | |
|
|
55 | or can get the source code. And you must show them these terms so they | |
|
|
56 | know their rights. | |
|
|
57 | ||
|
|
58 | Developers that use the GNU GPL protect your rights with two steps: | |
|
|
59 | (1) assert copyright on the software, and (2) offer you this License | |
|
|
60 | giving you legal permission to copy, distribute and/or modify it. | |
|
|
61 | ||
|
|
62 | For the developers' and authors' protection, the GPL clearly explains | |
|
|
63 | that there is no warranty for this free software. For both users' and | |
|
|
64 | authors' sake, the GPL requires that modified versions be marked as | |
|
|
65 | changed, so that their problems will not be attributed erroneously to | |
|
|
66 | authors of previous versions. | |
|
|
67 | ||
|
|
68 | Some devices are designed to deny users access to install or run | |
|
|
69 | modified versions of the software inside them, although the manufacturer | |
|
|
70 | can do so. This is fundamentally incompatible with the aim of | |
|
|
71 | protecting users' freedom to change the software. The systematic | |
|
|
72 | pattern of such abuse occurs in the area of products for individuals to | |
|
|
73 | use, which is precisely where it is most unacceptable. Therefore, we | |
|
|
74 | have designed this version of the GPL to prohibit the practice for those | |
|
|
75 | products. If such problems arise substantially in other domains, we | |
|
|
76 | stand ready to extend this provision to those domains in future versions | |
|
|
77 | of the GPL, as needed to protect the freedom of users. | |
|
|
78 | ||
|
|
79 | Finally, every program is threatened constantly by software patents. | |
|
|
80 | States should not allow patents to restrict development and use of | |
|
|
81 | software on general-purpose computers, but in those that do, we wish to | |
|
|
82 | avoid the special danger that patents applied to a free program could | |
|
|
83 | make it effectively proprietary. To prevent this, the GPL assures that | |
|
|
84 | patents cannot be used to render the program non-free. | |
|
|
85 | ||
|
|
86 | The precise terms and conditions for copying, distribution and | |
|
|
87 | modification follow. | |
|
|
88 | ||
|
|
89 | TERMS AND CONDITIONS | |
|
|
90 | ||
|
|
91 | 0. Definitions. | |
|
|
92 | ||
|
|
93 | "This License" refers to version 3 of the GNU General Public License. | |
|
|
94 | ||
|
|
95 | "Copyright" also means copyright-like laws that apply to other kinds of | |
|
|
96 | works, such as semiconductor masks. | |
|
|
97 | ||
|
|
98 | "The Program" refers to any copyrightable work licensed under this | |
|
|
99 | License. Each licensee is addressed as "you". "Licensees" and | |
|
|
100 | "recipients" may be individuals or organizations. | |
|
|
101 | ||
|
|
102 | To "modify" a work means to copy from or adapt all or part of the work | |
|
|
103 | in a fashion requiring copyright permission, other than the making of an | |
|
|
104 | exact copy. The resulting work is called a "modified version" of the | |
|
|
105 | earlier work or a work "based on" the earlier work. | |
|
|
106 | ||
|
|
107 | A "covered work" means either the unmodified Program or a work based | |
|
|
108 | on the Program. | |
|
|
109 | ||
|
|
110 | To "propagate" a work means to do anything with it that, without | |
|
|
111 | permission, would make you directly or secondarily liable for | |
|
|
112 | infringement under applicable copyright law, except executing it on a | |
|
|
113 | computer or modifying a private copy. Propagation includes copying, | |
|
|
114 | distribution (with or without modification), making available to the | |
|
|
115 | public, and in some countries other activities as well. | |
|
|
116 | ||
|
|
117 | To "convey" a work means any kind of propagation that enables other | |
|
|
118 | parties to make or receive copies. Mere interaction with a user through | |
|
|
119 | a computer network, with no transfer of a copy, is not conveying. | |
|
|
120 | ||
|
|
121 | An interactive user interface displays "Appropriate Legal Notices" | |
|
|
122 | to the extent that it includes a convenient and prominently visible | |
|
|
123 | feature that (1) displays an appropriate copyright notice, and (2) | |
|
|
124 | tells the user that there is no warranty for the work (except to the | |
|
|
125 | extent that warranties are provided), that licensees may convey the | |
|
|
126 | work under this License, and how to view a copy of this License. If | |
|
|
127 | the interface presents a list of user commands or options, such as a | |
|
|
128 | menu, a prominent item in the list meets this criterion. | |
|
|
129 | ||
|
|
130 | 1. Source Code. | |
|
|
131 | ||
|
|
132 | The "source code" for a work means the preferred form of the work | |
|
|
133 | for making modifications to it. "Object code" means any non-source | |
|
|
134 | form of a work. | |
|
|
135 | ||
|
|
136 | A "Standard Interface" means an interface that either is an official | |
|
|
137 | standard defined by a recognized standards body, or, in the case of | |
|
|
138 | interfaces specified for a particular programming language, one that | |
|
|
139 | is widely used among developers working in that language. | |
|
|
140 | ||
|
|
141 | The "System Libraries" of an executable work include anything, other | |
|
|
142 | than the work as a whole, that (a) is included in the normal form of | |
|
|
143 | packaging a Major Component, but which is not part of that Major | |
|
|
144 | Component, and (b) serves only to enable use of the work with that | |
|
|
145 | Major Component, or to implement a Standard Interface for which an | |
|
|
146 | implementation is available to the public in source code form. A | |
|
|
147 | "Major Component", in this context, means a major essential component | |
|
|
148 | (kernel, window system, and so on) of the specific operating system | |
|
|
149 | (if any) on which the executable work runs, or a compiler used to | |
|
|
150 | produce the work, or an object code interpreter used to run it. | |
|
|
151 | ||
|
|
152 | The "Corresponding Source" for a work in object code form means all | |
|
|
153 | the source code needed to generate, install, and (for an executable | |
|
|
154 | work) run the object code and to modify the work, including scripts to | |
|
|
155 | control those activities. However, it does not include the work's | |
|
|
156 | System Libraries, or general-purpose tools or generally available free | |
|
|
157 | programs which are used unmodified in performing those activities but | |
|
|
158 | which are not part of the work. For example, Corresponding Source | |
|
|
159 | includes interface definition files associated with source files for | |
|
|
160 | the work, and the source code for shared libraries and dynamically | |
|
|
161 | linked subprograms that the work is specifically designed to require, | |
|
|
162 | such as by intimate data communication or control flow between those | |
|
|
163 | subprograms and other parts of the work. | |
|
|
164 | ||
|
|
165 | The Corresponding Source need not include anything that users | |
|
|
166 | can regenerate automatically from other parts of the Corresponding | |
|
|
167 | Source. | |
|
|
168 | ||
|
|
169 | The Corresponding Source for a work in source code form is that | |
|
|
170 | same work. | |
|
|
171 | ||
|
|
172 | 2. Basic Permissions. | |
|
|
173 | ||
|
|
174 | All rights granted under this License are granted for the term of | |
|
|
175 | copyright on the Program, and are irrevocable provided the stated | |
|
|
176 | conditions are met. This License explicitly affirms your unlimited | |
|
|
177 | permission to run the unmodified Program. The output from running a | |
|
|
178 | covered work is covered by this License only if the output, given its | |
|
|
179 | content, constitutes a covered work. This License acknowledges your | |
|
|
180 | rights of fair use or other equivalent, as provided by copyright law. | |
|
|
181 | ||
|
|
182 | You may make, run and propagate covered works that you do not | |
|
|
183 | convey, without conditions so long as your license otherwise remains | |
|
|
184 | in force. You may convey covered works to others for the sole purpose | |
|
|
185 | of having them make modifications exclusively for you, or provide you | |
|
|
186 | with facilities for running those works, provided that you comply with | |
|
|
187 | the terms of this License in conveying all material for which you do | |
|
|
188 | not control copyright. Those thus making or running the covered works | |
|
|
189 | for you must do so exclusively on your behalf, under your direction | |
|
|
190 | and control, on terms that prohibit them from making any copies of | |
|
|
191 | your copyrighted material outside their relationship with you. | |
|
|
192 | ||
|
|
193 | Conveying under any other circumstances is permitted solely under | |
|
|
194 | the conditions stated below. Sublicensing is not allowed; section 10 | |
|
|
195 | makes it unnecessary. | |
|
|
196 | ||
|
|
197 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. | |
|
|
198 | ||
|
|
199 | No covered work shall be deemed part of an effective technological | |
|
|
200 | measure under any applicable law fulfilling obligations under article | |
|
|
201 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or | |
|
|
202 | similar laws prohibiting or restricting circumvention of such | |
|
|
203 | measures. | |
|
|
204 | ||
|
|
205 | When you convey a covered work, you waive any legal power to forbid | |
|
|
206 | circumvention of technological measures to the extent such circumvention | |
|
|
207 | is effected by exercising rights under this License with respect to | |
|
|
208 | the covered work, and you disclaim any intention to limit operation or | |
|
|
209 | modification of the work as a means of enforcing, against the work's | |
|
|
210 | users, your or third parties' legal rights to forbid circumvention of | |
|
|
211 | technological measures. | |
|
|
212 | ||
|
|
213 | 4. Conveying Verbatim Copies. | |
|
|
214 | ||
|
|
215 | You may convey verbatim copies of the Program's source code as you | |
|
|
216 | receive it, in any medium, provided that you conspicuously and | |
|
|
217 | appropriately publish on each copy an appropriate copyright notice; | |
|
|
218 | keep intact all notices stating that this License and any | |
|
|
219 | non-permissive terms added in accord with section 7 apply to the code; | |
|
|
220 | keep intact all notices of the absence of any warranty; and give all | |
|
|
221 | recipients a copy of this License along with the Program. | |
|
|
222 | ||
|
|
223 | You may charge any price or no price for each copy that you convey, | |
|
|
224 | and you may offer support or warranty protection for a fee. | |
|
|
225 | ||
|
|
226 | 5. Conveying Modified Source Versions. | |
|
|
227 | ||
|
|
228 | You may convey a work based on the Program, or the modifications to | |
|
|
229 | produce it from the Program, in the form of source code under the | |
|
|
230 | terms of section 4, provided that you also meet all of these conditions: | |
|
|
231 | ||
|
|
232 | a) The work must carry prominent notices stating that you modified | |
|
|
233 | it, and giving a relevant date. | |
|
|
234 | ||
|
|
235 | b) The work must carry prominent notices stating that it is | |
|
|
236 | released under this License and any conditions added under section | |
|
|
237 | 7. This requirement modifies the requirement in section 4 to | |
|
|
238 | "keep intact all notices". | |
|
|
239 | ||
|
|
240 | c) You must license the entire work, as a whole, under this | |
|
|
241 | License to anyone who comes into possession of a copy. This | |
|
|
242 | License will therefore apply, along with any applicable section 7 | |
|
|
243 | additional terms, to the whole of the work, and all its parts, | |
|
|
244 | regardless of how they are packaged. This License gives no | |
|
|
245 | permission to license the work in any other way, but it does not | |
|
|
246 | invalidate such permission if you have separately received it. | |
|
|
247 | ||
|
|
248 | d) If the work has interactive user interfaces, each must display | |
|
|
249 | Appropriate Legal Notices; however, if the Program has interactive | |
|
|
250 | interfaces that do not display Appropriate Legal Notices, your | |
|
|
251 | work need not make them do so. | |
|
|
252 | ||
|
|
253 | A compilation of a covered work with other separate and independent | |
|
|
254 | works, which are not by their nature extensions of the covered work, | |
|
|
255 | and which are not combined with it such as to form a larger program, | |
|
|
256 | in or on a volume of a storage or distribution medium, is called an | |
|
|
257 | "aggregate" if the compilation and its resulting copyright are not | |
|
|
258 | used to limit the access or legal rights of the compilation's users | |
|
|
259 | beyond what the individual works permit. Inclusion of a covered work | |
|
|
260 | in an aggregate does not cause this License to apply to the other | |
|
|
261 | parts of the aggregate. | |
|
|
262 | ||
|
|
263 | 6. Conveying Non-Source Forms. | |
|
|
264 | ||
|
|
265 | You may convey a covered work in object code form under the terms | |
|
|
266 | of sections 4 and 5, provided that you also convey the | |
|
|
267 | machine-readable Corresponding Source under the terms of this License, | |
|
|
268 | in one of these ways: | |
|
|
269 | ||
|
|
270 | a) Convey the object code in, or embodied in, a physical product | |
|
|
271 | (including a physical distribution medium), accompanied by the | |
|
|
272 | Corresponding Source fixed on a durable physical medium | |
|
|
273 | customarily used for software interchange. | |
|
|
274 | ||
|
|
275 | b) Convey the object code in, or embodied in, a physical product | |
|
|
276 | (including a physical distribution medium), accompanied by a | |
|
|
277 | written offer, valid for at least three years and valid for as | |
|
|
278 | long as you offer spare parts or customer support for that product | |
|
|
279 | model, to give anyone who possesses the object code either (1) a | |
|
|
280 | copy of the Corresponding Source for all the software in the | |
|
|
281 | product that is covered by this License, on a durable physical | |
|
|
282 | medium customarily used for software interchange, for a price no | |
|
|
283 | more than your reasonable cost of physically performing this | |
|
|
284 | conveying of source, or (2) access to copy the | |
|
|
285 | Corresponding Source from a network server at no charge. | |
|
|
286 | ||
|
|
287 | c) Convey individual copies of the object code with a copy of the | |
|
|
288 | written offer to provide the Corresponding Source. This | |
|
|
289 | alternative is allowed only occasionally and noncommercially, and | |
|
|
290 | only if you received the object code with such an offer, in accord | |
|
|
291 | with subsection 6b. | |
|
|
292 | ||
|
|
293 | d) Convey the object code by offering access from a designated | |
|
|
294 | place (gratis or for a charge), and offer equivalent access to the | |
|
|
295 | Corresponding Source in the same way through the same place at no | |
|
|
296 | further charge. You need not require recipients to copy the | |
|
|
297 | Corresponding Source along with the object code. If the place to | |
|
|
298 | copy the object code is a network server, the Corresponding Source | |
|
|
299 | may be on a different server (operated by you or a third party) | |
|
|
300 | that supports equivalent copying facilities, provided you maintain | |
|
|
301 | clear directions next to the object code saying where to find the | |
|
|
302 | Corresponding Source. Regardless of what server hosts the | |
|
|
303 | Corresponding Source, you remain obligated to ensure that it is | |
|
|
304 | available for as long as needed to satisfy these requirements. | |
|
|
305 | ||
|
|
306 | e) Convey the object code using peer-to-peer transmission, provided | |
|
|
307 | you inform other peers where the object code and Corresponding | |
|
|
308 | Source of the work are being offered to the general public at no | |
|
|
309 | charge under subsection 6d. | |
|
|
310 | ||
|
|
311 | A separable portion of the object code, whose source code is excluded | |
|
|
312 | from the Corresponding Source as a System Library, need not be | |
|
|
313 | included in conveying the object code work. | |
|
|
314 | ||
|
|
315 | A "User Product" is either (1) a "consumer product", which means any | |
|
|
316 | tangible personal property which is normally used for personal, family, | |
|
|
317 | or household purposes, or (2) anything designed or sold for incorporation | |
|
|
318 | into a dwelling. In determining whether a product is a consumer product, | |
|
|
319 | doubtful cases shall be resolved in favor of coverage. For a particular | |
|
|
320 | product received by a particular user, "normally used" refers to a | |
|
|
321 | typical or common use of that class of product, regardless of the status | |
|
|
322 | of the particular user or of the way in which the particular user | |
|
|
323 | actually uses, or expects or is expected to use, the product. A product | |
|
|
324 | is a consumer product regardless of whether the product has substantial | |
|
|
325 | commercial, industrial or non-consumer uses, unless such uses represent | |
|
|
326 | the only significant mode of use of the product. | |
|
|
327 | ||
|
|
328 | "Installation Information" for a User Product means any methods, | |
|
|
329 | procedures, authorization keys, or other information required to install | |
|
|
330 | and execute modified versions of a covered work in that User Product from | |
|
|
331 | a modified version of its Corresponding Source. The information must | |
|
|
332 | suffice to ensure that the continued functioning of the modified object | |
|
|
333 | code is in no case prevented or interfered with solely because | |
|
|
334 | modification has been made. | |
|
|
335 | ||
|
|
336 | If you convey an object code work under this section in, or with, or | |
|
|
337 | specifically for use in, a User Product, and the conveying occurs as | |
|
|
338 | part of a transaction in which the right of possession and use of the | |
|
|
339 | User Product is transferred to the recipient in perpetuity or for a | |
|
|
340 | fixed term (regardless of how the transaction is characterized), the | |
|
|
341 | Corresponding Source conveyed under this section must be accompanied | |
|
|
342 | by the Installation Information. But this requirement does not apply | |
|
|
343 | if neither you nor any third party retains the ability to install | |
|
|
344 | modified object code on the User Product (for example, the work has | |
|
|
345 | been installed in ROM). | |
|
|
346 | ||
|
|
347 | The requirement to provide Installation Information does not include a | |
|
|
348 | requirement to continue to provide support service, warranty, or updates | |
|
|
349 | for a work that has been modified or installed by the recipient, or for | |
|
|
350 | the User Product in which it has been modified or installed. Access to a | |
|
|
351 | network may be denied when the modification itself materially and | |
|
|
352 | adversely affects the operation of the network or violates the rules and | |
|
|
353 | protocols for communication across the network. | |
|
|
354 | ||
|
|
355 | Corresponding Source conveyed, and Installation Information provided, | |
|
|
356 | in accord with this section must be in a format that is publicly | |
|
|
357 | documented (and with an implementation available to the public in | |
|
|
358 | source code form), and must require no special password or key for | |
|
|
359 | unpacking, reading or copying. | |
|
|
360 | ||
|
|
361 | 7. Additional Terms. | |
|
|
362 | ||
|
|
363 | "Additional permissions" are terms that supplement the terms of this | |
|
|
364 | License by making exceptions from one or more of its conditions. | |
|
|
365 | Additional permissions that are applicable to the entire Program shall | |
|
|
366 | be treated as though they were included in this License, to the extent | |
|
|
367 | that they are valid under applicable law. If additional permissions | |
|
|
368 | apply only to part of the Program, that part may be used separately | |
|
|
369 | under those permissions, but the entire Program remains governed by | |
|
|
370 | this License without regard to the additional permissions. | |
|
|
371 | ||
|
|
372 | When you convey a copy of a covered work, you may at your option | |
|
|
373 | remove any additional permissions from that copy, or from any part of | |
|
|
374 | it. (Additional permissions may be written to require their own | |
|
|
375 | removal in certain cases when you modify the work.) You may place | |
|
|
376 | additional permissions on material, added by you to a covered work, | |
|
|
377 | for which you have or can give appropriate copyright permission. | |
|
|
378 | ||
|
|
379 | Notwithstanding any other provision of this License, for material you | |
|
|
380 | add to a covered work, you may (if authorized by the copyright holders of | |
|
|
381 | that material) supplement the terms of this License with terms: | |
|
|
382 | ||
|
|
383 | a) Disclaiming warranty or limiting liability differently from the | |
|
|
384 | terms of sections 15 and 16 of this License; or | |
|
|
385 | ||
|
|
386 | b) Requiring preservation of specified reasonable legal notices or | |
|
|
387 | author attributions in that material or in the Appropriate Legal | |
|
|
388 | Notices displayed by works containing it; or | |
|
|
389 | ||
|
|
390 | c) Prohibiting misrepresentation of the origin of that material, or | |
|
|
391 | requiring that modified versions of such material be marked in | |
|
|
392 | reasonable ways as different from the original version; or | |
|
|
393 | ||
|
|
394 | d) Limiting the use for publicity purposes of names of licensors or | |
|
|
395 | authors of the material; or | |
|
|
396 | ||
|
|
397 | e) Declining to grant rights under trademark law for use of some | |
|
|
398 | trade names, trademarks, or service marks; or | |
|
|
399 | ||
|
|
400 | f) Requiring indemnification of licensors and authors of that | |
|
|
401 | material by anyone who conveys the material (or modified versions of | |
|
|
402 | it) with contractual assumptions of liability to the recipient, for | |
|
|
403 | any liability that these contractual assumptions directly impose on | |
|
|
404 | those licensors and authors. | |
|
|
405 | ||
|
|
406 | All other non-permissive additional terms are considered "further | |
|
|
407 | restrictions" within the meaning of section 10. If the Program as you | |
|
|
408 | received it, or any part of it, contains a notice stating that it is | |
|
|
409 | governed by this License along with a term that is a further | |
|
|
410 | restriction, you may remove that term. If a license document contains | |
|
|
411 | a further restriction but permits relicensing or conveying under this | |
|
|
412 | License, you may add to a covered work material governed by the terms | |
|
|
413 | of that license document, provided that the further restriction does | |
|
|
414 | not survive such relicensing or conveying. | |
|
|
415 | ||
|
|
416 | If you add terms to a covered work in accord with this section, you | |
|
|
417 | must place, in the relevant source files, a statement of the | |
|
|
418 | additional terms that apply to those files, or a notice indicating | |
|
|
419 | where to find the applicable terms. | |
|
|
420 | ||
|
|
421 | Additional terms, permissive or non-permissive, may be stated in the | |
|
|
422 | form of a separately written license, or stated as exceptions; | |
|
|
423 | the above requirements apply either way. | |
|
|
424 | ||
|
|
425 | 8. Termination. | |
|
|
426 | ||
|
|
427 | You may not propagate or modify a covered work except as expressly | |
|
|
428 | provided under this License. Any attempt otherwise to propagate or | |
|
|
429 | modify it is void, and will automatically terminate your rights under | |
|
|
430 | this License (including any patent licenses granted under the third | |
|
|
431 | paragraph of section 11). | |
|
|
432 | ||
|
|
433 | However, if you cease all violation of this License, then your | |
|
|
434 | license from a particular copyright holder is reinstated (a) | |
|
|
435 | provisionally, unless and until the copyright holder explicitly and | |
|
|
436 | finally terminates your license, and (b) permanently, if the copyright | |
|
|
437 | holder fails to notify you of the violation by some reasonable means | |
|
|
438 | prior to 60 days after the cessation. | |
|
|
439 | ||
|
|
440 | Moreover, your license from a particular copyright holder is | |
|
|
441 | reinstated permanently if the copyright holder notifies you of the | |
|
|
442 | violation by some reasonable means, this is the first time you have | |
|
|
443 | received notice of violation of this License (for any work) from that | |
|
|
444 | copyright holder, and you cure the violation prior to 30 days after | |
|
|
445 | your receipt of the notice. | |
|
|
446 | ||
|
|
447 | Termination of your rights under this section does not terminate the | |
|
|
448 | licenses of parties who have received copies or rights from you under | |
|
|
449 | this License. If your rights have been terminated and not permanently | |
|
|
450 | reinstated, you do not qualify to receive new licenses for the same | |
|
|
451 | material under section 10. | |
|
|
452 | ||
|
|
453 | 9. Acceptance Not Required for Having Copies. | |
|
|
454 | ||
|
|
455 | You are not required to accept this License in order to receive or | |
|
|
456 | run a copy of the Program. Ancillary propagation of a covered work | |
|
|
457 | occurring solely as a consequence of using peer-to-peer transmission | |
|
|
458 | to receive a copy likewise does not require acceptance. However, | |
|
|
459 | nothing other than this License grants you permission to propagate or | |
|
|
460 | modify any covered work. These actions infringe copyright if you do | |
|
|
461 | not accept this License. Therefore, by modifying or propagating a | |
|
|
462 | covered work, you indicate your acceptance of this License to do so. | |
|
|
463 | ||
|
|
464 | 10. Automatic Licensing of Downstream Recipients. | |
|
|
465 | ||
|
|
466 | Each time you convey a covered work, the recipient automatically | |
|
|
467 | receives a license from the original licensors, to run, modify and | |
|
|
468 | propagate that work, subject to this License. You are not responsible | |
|
|
469 | for enforcing compliance by third parties with this License. | |
|
|
470 | ||
|
|
471 | An "entity transaction" is a transaction transferring control of an | |
|
|
472 | organization, or substantially all assets of one, or subdividing an | |
|
|
473 | organization, or merging organizations. If propagation of a covered | |
|
|
474 | work results from an entity transaction, each party to that | |
|
|
475 | transaction who receives a copy of the work also receives whatever | |
|
|
476 | licenses to the work the party's predecessor in interest had or could | |
|
|
477 | give under the previous paragraph, plus a right to possession of the | |
|
|
478 | Corresponding Source of the work from the predecessor in interest, if | |
|
|
479 | the predecessor has it or can get it with reasonable efforts. | |
|
|
480 | ||
|
|
481 | You may not impose any further restrictions on the exercise of the | |
|
|
482 | rights granted or affirmed under this License. For example, you may | |
|
|
483 | not impose a license fee, royalty, or other charge for exercise of | |
|
|
484 | rights granted under this License, and you may not initiate litigation | |
|
|
485 | (including a cross-claim or counterclaim in a lawsuit) alleging that | |
|
|
486 | any patent claim is infringed by making, using, selling, offering for | |
|
|
487 | sale, or importing the Program or any portion of it. | |
|
|
488 | ||
|
|
489 | 11. Patents. | |
|
|
490 | ||
|
|
491 | A "contributor" is a copyright holder who authorizes use under this | |
|
|
492 | License of the Program or a work on which the Program is based. The | |
|
|
493 | work thus licensed is called the contributor's "contributor version". | |
|
|
494 | ||
|
|
495 | A contributor's "essential patent claims" are all patent claims | |
|
|
496 | owned or controlled by the contributor, whether already acquired or | |
|
|
497 | hereafter acquired, that would be infringed by some manner, permitted | |
|
|
498 | by this License, of making, using, or selling its contributor version, | |
|
|
499 | but do not include claims that would be infringed only as a | |
|
|
500 | consequence of further modification of the contributor version. For | |
|
|
501 | purposes of this definition, "control" includes the right to grant | |
|
|
502 | patent sublicenses in a manner consistent with the requirements of | |
|
|
503 | this License. | |
|
|
504 | ||
|
|
505 | Each contributor grants you a non-exclusive, worldwide, royalty-free | |
|
|
506 | patent license under the contributor's essential patent claims, to | |
|
|
507 | make, use, sell, offer for sale, import and otherwise run, modify and | |
|
|
508 | propagate the contents of its contributor version. | |
|
|
509 | ||
|
|
510 | In the following three paragraphs, a "patent license" is any express | |
|
|
511 | agreement or commitment, however denominated, not to enforce a patent | |
|
|
512 | (such as an express permission to practice a patent or covenant not to | |
|
|
513 | sue for patent infringement). To "grant" such a patent license to a | |
|
|
514 | party means to make such an agreement or commitment not to enforce a | |
|
|
515 | patent against the party. | |
|
|
516 | ||
|
|
517 | If you convey a covered work, knowingly relying on a patent license, | |
|
|
518 | and the Corresponding Source of the work is not available for anyone | |
|
|
519 | to copy, free of charge and under the terms of this License, through a | |
|
|
520 | publicly available network server or other readily accessible means, | |
|
|
521 | then you must either (1) cause the Corresponding Source to be so | |
|
|
522 | available, or (2) arrange to deprive yourself of the benefit of the | |
|
|
523 | patent license for this particular work, or (3) arrange, in a manner | |
|
|
524 | consistent with the requirements of this License, to extend the patent | |
|
|
525 | license to downstream recipients. "Knowingly relying" means you have | |
|
|
526 | actual knowledge that, but for the patent license, your conveying the | |
|
|
527 | covered work in a country, or your recipient's use of the covered work | |
|
|
528 | in a country, would infringe one or more identifiable patents in that | |
|
|
529 | country that you have reason to believe are valid. | |
|
|
530 | ||
|
|
531 | If, pursuant to or in connection with a single transaction or | |
|
|
532 | arrangement, you convey, or propagate by procuring conveyance of, a | |
|
|
533 | covered work, and grant a patent license to some of the parties | |
|
|
534 | receiving the covered work authorizing them to use, propagate, modify | |
|
|
535 | or convey a specific copy of the covered work, then the patent license | |
|
|
536 | you grant is automatically extended to all recipients of the covered | |
|
|
537 | work and works based on it. | |
|
|
538 | ||
|
|
539 | A patent license is "discriminatory" if it does not include within | |
|
|
540 | the scope of its coverage, prohibits the exercise of, or is | |
|
|
541 | conditioned on the non-exercise of one or more of the rights that are | |
|
|
542 | specifically granted under this License. You may not convey a covered | |
|
|
543 | work if you are a party to an arrangement with a third party that is | |
|
|
544 | in the business of distributing software, under which you make payment | |
|
|
545 | to the third party based on the extent of your activity of conveying | |
|
|
546 | the work, and under which the third party grants, to any of the | |
|
|
547 | parties who would receive the covered work from you, a discriminatory | |
|
|
548 | patent license (a) in connection with copies of the covered work | |
|
|
549 | conveyed by you (or copies made from those copies), or (b) primarily | |
|
|
550 | for and in connection with specific products or compilations that | |
|
|
551 | contain the covered work, unless you entered into that arrangement, | |
|
|
552 | or that patent license was granted, prior to 28 March 2007. | |
|
|
553 | ||
|
|
554 | Nothing in this License shall be construed as excluding or limiting | |
|
|
555 | any implied license or other defenses to infringement that may | |
|
|
556 | otherwise be available to you under applicable patent law. | |
|
|
557 | ||
|
|
558 | 12. No Surrender of Others' Freedom. | |
|
|
559 | ||
|
|
560 | If conditions are imposed on you (whether by court order, agreement or | |
|
|
561 | otherwise) that contradict the conditions of this License, they do not | |
|
|
562 | excuse you from the conditions of this License. If you cannot convey a | |
|
|
563 | covered work so as to satisfy simultaneously your obligations under this | |
|
|
564 | License and any other pertinent obligations, then as a consequence you may | |
|
|
565 | not convey it at all. For example, if you agree to terms that obligate you | |
|
|
566 | to collect a royalty for further conveying from those to whom you convey | |
|
|
567 | the Program, the only way you could satisfy both those terms and this | |
|
|
568 | License would be to refrain entirely from conveying the Program. | |
|
|
569 | ||
|
|
570 | 13. Use with the GNU Affero General Public License. | |
|
|
571 | ||
|
|
572 | Notwithstanding any other provision of this License, you have | |
|
|
573 | permission to link or combine any covered work with a work licensed | |
|
|
574 | under version 3 of the GNU Affero General Public License into a single | |
|
|
575 | combined work, and to convey the resulting work. The terms of this | |
|
|
576 | License will continue to apply to the part which is the covered work, | |
|
|
577 | but the special requirements of the GNU Affero General Public License, | |
|
|
578 | section 13, concerning interaction through a network will apply to the | |
|
|
579 | combination as such. | |
|
|
580 | ||
|
|
581 | 14. Revised Versions of this License. | |
|
|
582 | ||
|
|
583 | The Free Software Foundation may publish revised and/or new versions of | |
|
|
584 | the GNU General Public License from time to time. Such new versions will | |
|
|
585 | be similar in spirit to the present version, but may differ in detail to | |
|
|
586 | address new problems or concerns. | |
|
|
587 | ||
|
|
588 | Each version is given a distinguishing version number. If the | |
|
|
589 | Program specifies that a certain numbered version of the GNU General | |
|
|
590 | Public License "or any later version" applies to it, you have the | |
|
|
591 | option of following the terms and conditions either of that numbered | |
|
|
592 | version or of any later version published by the Free Software | |
|
|
593 | Foundation. If the Program does not specify a version number of the | |
|
|
594 | GNU General Public License, you may choose any version ever published | |
|
|
595 | by the Free Software Foundation. | |
|
|
596 | ||
|
|
597 | If the Program specifies that a proxy can decide which future | |
|
|
598 | versions of the GNU General Public License can be used, that proxy's | |
|
|
599 | public statement of acceptance of a version permanently authorizes you | |
|
|
600 | to choose that version for the Program. | |
|
|
601 | ||
|
|
602 | Later license versions may give you additional or different | |
|
|
603 | permissions. However, no additional obligations are imposed on any | |
|
|
604 | author or copyright holder as a result of your choosing to follow a | |
|
|
605 | later version. | |
|
|
606 | ||
|
|
607 | 15. Disclaimer of Warranty. | |
|
|
608 | ||
|
|
609 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | |
|
|
610 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | |
|
|
611 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | |
|
|
612 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | |
|
|
613 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
|
|
614 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | |
|
|
615 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | |
|
|
616 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |
|
|
617 | ||
|
|
618 | 16. Limitation of Liability. | |
|
|
619 | ||
|
|
620 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |
|
|
621 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | |
|
|
622 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | |
|
|
623 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | |
|
|
624 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | |
|
|
625 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | |
|
|
626 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | |
|
|
627 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | |
|
|
628 | SUCH DAMAGES. | |
|
|
629 | ||
|
|
630 | 17. Interpretation of Sections 15 and 16. | |
|
|
631 | ||
|
|
632 | If the disclaimer of warranty and limitation of liability provided | |
|
|
633 | above cannot be given local legal effect according to their terms, | |
|
|
634 | reviewing courts shall apply local law that most closely approximates | |
|
|
635 | an absolute waiver of all civil liability in connection with the | |
|
|
636 | Program, unless a warranty or assumption of liability accompanies a | |
|
|
637 | copy of the Program in return for a fee. | |
|
|
638 | ||
|
|
639 | END OF TERMS AND CONDITIONS | |
|
|
640 | ||
|
|
641 | How to Apply These Terms to Your New Programs | |
|
|
642 | ||
|
|
643 | If you develop a new program, and you want it to be of the greatest | |
|
|
644 | possible use to the public, the best way to achieve this is to make it | |
|
|
645 | free software which everyone can redistribute and change under these terms. | |
|
|
646 | ||
|
|
647 | To do so, attach the following notices to the program. It is safest | |
|
|
648 | to attach them to the start of each source file to most effectively | |
|
|
649 | state the exclusion of warranty; and each file should have at least | |
|
|
650 | the "copyright" line and a pointer to where the full notice is found. | |
|
|
651 | ||
|
|
652 | <one line to give the program's name and a brief idea of what it does.> | |
|
|
653 | Copyright (C) <year> <name of author> | |
|
|
654 | ||
|
|
655 | This program is free software: you can redistribute it and/or modify | |
|
|
656 | it under the terms of the GNU General Public License as published by | |
|
|
657 | the Free Software Foundation, either version 3 of the License, or | |
|
|
658 | (at your option) any later version. | |
|
|
659 | ||
|
|
660 | This program is distributed in the hope that it will be useful, | |
|
|
661 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
|
662 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
|
663 | GNU General Public License for more details. | |
|
|
664 | ||
|
|
665 | You should have received a copy of the GNU General Public License | |
|
|
666 | along with this program. If not, see <https://www.gnu.org/licenses/>. | |
|
|
667 | ||
|
|
668 | Also add information on how to contact you by electronic and paper mail. | |
|
|
669 | ||
|
|
670 | If the program does terminal interaction, make it output a short | |
|
|
671 | notice like this when it starts in an interactive mode: | |
|
|
672 | ||
|
|
673 | <program> Copyright (C) <year> <name of author> | |
|
|
674 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |
|
|
675 | This is free software, and you are welcome to redistribute it | |
|
|
676 | under certain conditions; type `show c' for details. | |
|
|
677 | ||
|
|
678 | The hypothetical commands `show w' and `show c' should show the appropriate | |
|
|
679 | parts of the General Public License. Of course, your program's commands | |
|
|
680 | might be different; for a GUI interface, you would use an "about box". | |
|
|
681 | ||
|
|
682 | You should also get your employer (if you work as a programmer) or school, | |
|
|
683 | if any, to sign a "copyright disclaimer" for the program, if necessary. | |
|
|
684 | For more information on this, and how to apply and follow the GNU GPL, see | |
|
|
685 | <https://www.gnu.org/licenses/>. | |
|
|
686 | ||
|
|
687 | The GNU General Public License does not permit incorporating your program | |
|
|
688 | into proprietary programs. If your program is a subroutine library, you | |
|
|
689 | may consider it more useful to permit linking proprietary applications with | |
|
|
690 | the library. If this is what you want to do, use the GNU Lesser General | |
|
|
691 | Public License instead of this License. But first, please read | |
|
|
692 | <https://www.gnu.org/licenses/why-not-lgpl.html>. | |
| @@ -0,0 +1,12 | |||
|
|
1 | Copyright (C) 2025 by notchoc <[email protected]> | |
|
|
2 | ||
|
|
3 | Permission to use, copy, modify, and/or distribute this software for any | |
|
|
4 | purpose with or without fee is hereby granted. | |
|
|
5 | ||
|
|
6 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
|
|
7 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
|
|
8 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
|
|
9 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
|
|
10 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
|
|
11 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
|
|
12 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| @@ -0,0 +1,39 | |||
|
|
1 | Portions of dwl based on dwm code are used under the following license: | |
|
|
2 | ||
|
|
3 | MIT/X Consortium License | |
|
|
4 | ||
|
|
5 | Β© 2006-2019 Anselm R Garbe <[email protected]> | |
|
|
6 | Β© 2006-2009 Jukka Salmi <jukka at salmi dot ch> | |
|
|
7 | Β© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com> | |
|
|
8 | Β© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com> | |
|
|
9 | Β© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com> | |
|
|
10 | Β© 2007-2009 Christof Musik <christof at sendfax dot de> | |
|
|
11 | Β© 2007-2009 Premysl Hruby <dfenze at gmail dot com> | |
|
|
12 | Β© 2007-2008 Enno Gottox Boland <gottox at s01 dot de> | |
|
|
13 | Β© 2008 Martin Hurton <martin dot hurton at gmail dot com> | |
|
|
14 | Β© 2008 Neale Pickett <neale dot woozle dot org> | |
|
|
15 | Β© 2009 Mate Nagy <mnagy at port70 dot net> | |
|
|
16 | Β© 2010-2016 Hiltjo Posthuma <[email protected]> | |
|
|
17 | Β© 2010-2012 Connor Lane Smith <[email protected]> | |
|
|
18 | Β© 2011 Christoph Lohmann <[email protected]> | |
|
|
19 | Β© 2015-2016 Quentin Rameau <[email protected]> | |
|
|
20 | Β© 2015-2016 Eric Pruitt <[email protected]> | |
|
|
21 | Β© 2016-2017 Markus Teich <[email protected]> | |
|
|
22 | ||
|
|
23 | Permission is hereby granted, free of charge, to any person obtaining a | |
|
|
24 | copy of this software and associated documentation files (the "Software"), | |
|
|
25 | to deal in the Software without restriction, including without limitation | |
|
|
26 | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
|
|
27 | and/or sell copies of the Software, and to permit persons to whom the | |
|
|
28 | Software is furnished to do so, subject to the following conditions: | |
|
|
29 | ||
|
|
30 | The above copyright notice and this permission notice shall be included in | |
|
|
31 | all copies or substantial portions of the Software. | |
|
|
32 | ||
|
|
33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
|
|
34 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
|
|
35 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
|
|
36 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
|
|
37 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
|
|
38 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
|
|
39 | DEALINGS IN THE SOFTWARE. | |
| This diff has been collapsed as it changes many lines, (692 lines changed) Show them Hide them | |||
| @@ -0,0 +1,692 | |||
|
|
1 | mango - wayland compositor base wlroots | |
|
|
2 | ||
|
|
3 | Copyright Β© 2025 DreamMaoMao | |
|
|
4 | ||
|
|
5 | See also the files LICENSE.dwl, LICENSE.tinywl, LICENSE.dwm and LICENSE.sway. | |
|
|
6 | ||
|
|
7 | This program is free software: you can redistribute it and/or modify | |
|
|
8 | it under the terms of the GNU General Public License as published by | |
|
|
9 | the Free Software Foundation, either version 3 of the License, or | |
|
|
10 | (at your option) any later version. | |
|
|
11 | ||
|
|
12 | This program is distributed in the hope that it will be useful, | |
|
|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
|
15 | GNU General Public License for more details. | |
|
|
16 | ||
|
|
17 | ---- | |
|
|
18 | ||
|
|
19 | GNU GENERAL PUBLIC LICENSE | |
|
|
20 | Version 3, 29 June 2007 | |
|
|
21 | ||
|
|
22 | Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> | |
|
|
23 | Everyone is permitted to copy and distribute verbatim copies | |
|
|
24 | of this license document, but changing it is not allowed. | |
|
|
25 | ||
|
|
26 | Preamble | |
|
|
27 | ||
|
|
28 | The GNU General Public License is a free, copyleft license for | |
|
|
29 | software and other kinds of works. | |
|
|
30 | ||
|
|
31 | The licenses for most software and other practical works are designed | |
|
|
32 | to take away your freedom to share and change the works. By contrast, | |
|
|
33 | the GNU General Public License is intended to guarantee your freedom to | |
|
|
34 | share and change all versions of a program--to make sure it remains free | |
|
|
35 | software for all its users. We, the Free Software Foundation, use the | |
|
|
36 | GNU General Public License for most of our software; it applies also to | |
|
|
37 | any other work released this way by its authors. You can apply it to | |
|
|
38 | your programs, too. | |
|
|
39 | ||
|
|
40 | When we speak of free software, we are referring to freedom, not | |
|
|
41 | price. Our General Public Licenses are designed to make sure that you | |
|
|
42 | have the freedom to distribute copies of free software (and charge for | |
|
|
43 | them if you wish), that you receive source code or can get it if you | |
|
|
44 | want it, that you can change the software or use pieces of it in new | |
|
|
45 | free programs, and that you know you can do these things. | |
|
|
46 | ||
|
|
47 | To protect your rights, we need to prevent others from denying you | |
|
|
48 | these rights or asking you to surrender the rights. Therefore, you have | |
|
|
49 | certain responsibilities if you distribute copies of the software, or if | |
|
|
50 | you modify it: responsibilities to respect the freedom of others. | |
|
|
51 | ||
|
|
52 | For example, if you distribute copies of such a program, whether | |
|
|
53 | gratis or for a fee, you must pass on to the recipients the same | |
|
|
54 | freedoms that you received. You must make sure that they, too, receive | |
|
|
55 | or can get the source code. And you must show them these terms so they | |
|
|
56 | know their rights. | |
|
|
57 | ||
|
|
58 | Developers that use the GNU GPL protect your rights with two steps: | |
|
|
59 | (1) assert copyright on the software, and (2) offer you this License | |
|
|
60 | giving you legal permission to copy, distribute and/or modify it. | |
|
|
61 | ||
|
|
62 | For the developers' and authors' protection, the GPL clearly explains | |
|
|
63 | that there is no warranty for this free software. For both users' and | |
|
|
64 | authors' sake, the GPL requires that modified versions be marked as | |
|
|
65 | changed, so that their problems will not be attributed erroneously to | |
|
|
66 | authors of previous versions. | |
|
|
67 | ||
|
|
68 | Some devices are designed to deny users access to install or run | |
|
|
69 | modified versions of the software inside them, although the manufacturer | |
|
|
70 | can do so. This is fundamentally incompatible with the aim of | |
|
|
71 | protecting users' freedom to change the software. The systematic | |
|
|
72 | pattern of such abuse occurs in the area of products for individuals to | |
|
|
73 | use, which is precisely where it is most unacceptable. Therefore, we | |
|
|
74 | have designed this version of the GPL to prohibit the practice for those | |
|
|
75 | products. If such problems arise substantially in other domains, we | |
|
|
76 | stand ready to extend this provision to those domains in future versions | |
|
|
77 | of the GPL, as needed to protect the freedom of users. | |
|
|
78 | ||
|
|
79 | Finally, every program is threatened constantly by software patents. | |
|
|
80 | States should not allow patents to restrict development and use of | |
|
|
81 | software on general-purpose computers, but in those that do, we wish to | |
|
|
82 | avoid the special danger that patents applied to a free program could | |
|
|
83 | make it effectively proprietary. To prevent this, the GPL assures that | |
|
|
84 | patents cannot be used to render the program non-free. | |
|
|
85 | ||
|
|
86 | The precise terms and conditions for copying, distribution and | |
|
|
87 | modification follow. | |
|
|
88 | ||
|
|
89 | TERMS AND CONDITIONS | |
|
|
90 | ||
|
|
91 | 1. Definitions. | |
|
|
92 | ||
|
|
93 | "This License" refers to version 3 of the GNU General Public License. | |
|
|
94 | ||
|
|
95 | "Copyright" also means copyright-like laws that apply to other kinds of | |
|
|
96 | works, such as semiconductor masks. | |
|
|
97 | ||
|
|
98 | "The Program" refers to any copyrightable work licensed under this | |
|
|
99 | License. Each licensee is addressed as "you". "Licensees" and | |
|
|
100 | "recipients" may be individuals or organizations. | |
|
|
101 | ||
|
|
102 | To "modify" a work means to copy from or adapt all or part of the work | |
|
|
103 | in a fashion requiring copyright permission, other than the making of an | |
|
|
104 | exact copy. The resulting work is called a "modified version" of the | |
|
|
105 | earlier work or a work "based on" the earlier work. | |
|
|
106 | ||
|
|
107 | A "covered work" means either the unmodified Program or a work based | |
|
|
108 | on the Program. | |
|
|
109 | ||
|
|
110 | To "propagate" a work means to do anything with it that, without | |
|
|
111 | permission, would make you directly or secondarily liable for | |
|
|
112 | infringement under applicable copyright law, except executing it on a | |
|
|
113 | computer or modifying a private copy. Propagation includes copying, | |
|
|
114 | distribution (with or without modification), making available to the | |
|
|
115 | public, and in some countries other activities as well. | |
|
|
116 | ||
|
|
117 | To "convey" a work means any kind of propagation that enables other | |
|
|
118 | parties to make or receive copies. Mere interaction with a user through | |
|
|
119 | a computer network, with no transfer of a copy, is not conveying. | |
|
|
120 | ||
|
|
121 | An interactive user interface displays "Appropriate Legal Notices" | |
|
|
122 | to the extent that it includes a convenient and prominently visible | |
|
|
123 | feature that (1) displays an appropriate copyright notice, and (2) | |
|
|
124 | tells the user that there is no warranty for the work (except to the | |
|
|
125 | extent that warranties are provided), that licensees may convey the | |
|
|
126 | work under this License, and how to view a copy of this License. If | |
|
|
127 | the interface presents a list of user commands or options, such as a | |
|
|
128 | menu, a prominent item in the list meets this criterion. | |
|
|
129 | ||
|
|
130 | 1. Source Code. | |
|
|
131 | ||
|
|
132 | The "source code" for a work means the preferred form of the work | |
|
|
133 | for making modifications to it. "Object code" means any non-source | |
|
|
134 | form of a work. | |
|
|
135 | ||
|
|
136 | A "Standard Interface" means an interface that either is an official | |
|
|
137 | standard defined by a recognized standards body, or, in the case of | |
|
|
138 | interfaces specified for a particular programming language, one that | |
|
|
139 | is widely used among developers working in that language. | |
|
|
140 | ||
|
|
141 | The "System Libraries" of an executable work include anything, other | |
|
|
142 | than the work as a whole, that (a) is included in the normal form of | |
|
|
143 | packaging a Major Component, but which is not part of that Major | |
|
|
144 | Component, and (b) serves only to enable use of the work with that | |
|
|
145 | Major Component, or to implement a Standard Interface for which an | |
|
|
146 | implementation is available to the public in source code form. A | |
|
|
147 | "Major Component", in this context, means a major essential component | |
|
|
148 | (kernel, window system, and so on) of the specific operating system | |
|
|
149 | (if any) on which the executable work runs, or a compiler used to | |
|
|
150 | produce the work, or an object code interpreter used to run it. | |
|
|
151 | ||
|
|
152 | The "Corresponding Source" for a work in object code form means all | |
|
|
153 | the source code needed to generate, install, and (for an executable | |
|
|
154 | work) run the object code and to modify the work, including scripts to | |
|
|
155 | control those activities. However, it does not include the work's | |
|
|
156 | System Libraries, or general-purpose tools or generally available free | |
|
|
157 | programs which are used unmodified in performing those activities but | |
|
|
158 | which are not part of the work. For example, Corresponding Source | |
|
|
159 | includes interface definition files associated with source files for | |
|
|
160 | the work, and the source code for shared libraries and dynamically | |
|
|
161 | linked subprograms that the work is specifically designed to require, | |
|
|
162 | such as by intimate data communication or control flow between those | |
|
|
163 | subprograms and other parts of the work. | |
|
|
164 | ||
|
|
165 | The Corresponding Source need not include anything that users | |
|
|
166 | can regenerate automatically from other parts of the Corresponding | |
|
|
167 | Source. | |
|
|
168 | ||
|
|
169 | The Corresponding Source for a work in source code form is that | |
|
|
170 | same work. | |
|
|
171 | ||
|
|
172 | 2. Basic Permissions. | |
|
|
173 | ||
|
|
174 | All rights granted under this License are granted for the term of | |
|
|
175 | copyright on the Program, and are irrevocable provided the stated | |
|
|
176 | conditions are met. This License explicitly affirms your unlimited | |
|
|
177 | permission to run the unmodified Program. The output from running a | |
|
|
178 | covered work is covered by this License only if the output, given its | |
|
|
179 | content, constitutes a covered work. This License acknowledges your | |
|
|
180 | rights of fair use or other equivalent, as provided by copyright law. | |
|
|
181 | ||
|
|
182 | You may make, run and propagate covered works that you do not | |
|
|
183 | convey, without conditions so long as your license otherwise remains | |
|
|
184 | in force. You may convey covered works to others for the sole purpose | |
|
|
185 | of having them make modifications exclusively for you, or provide you | |
|
|
186 | with facilities for running those works, provided that you comply with | |
|
|
187 | the terms of this License in conveying all material for which you do | |
|
|
188 | not control copyright. Those thus making or running the covered works | |
|
|
189 | for you must do so exclusively on your behalf, under your direction | |
|
|
190 | and control, on terms that prohibit them from making any copies of | |
|
|
191 | your copyrighted material outside their relationship with you. | |
|
|
192 | ||
|
|
193 | Conveying under any other circumstances is permitted solely under | |
|
|
194 | the conditions stated below. Sublicensing is not allowed; section 10 | |
|
|
195 | makes it unnecessary. | |
|
|
196 | ||
|
|
197 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. | |
|
|
198 | ||
|
|
199 | No covered work shall be deemed part of an effective technological | |
|
|
200 | measure under any applicable law fulfilling obligations under article | |
|
|
201 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or | |
|
|
202 | similar laws prohibiting or restricting circumvention of such | |
|
|
203 | measures. | |
|
|
204 | ||
|
|
205 | When you convey a covered work, you waive any legal power to forbid | |
|
|
206 | circumvention of technological measures to the extent such circumvention | |
|
|
207 | is effected by exercising rights under this License with respect to | |
|
|
208 | the covered work, and you disclaim any intention to limit operation or | |
|
|
209 | modification of the work as a means of enforcing, against the work's | |
|
|
210 | users, your or third parties' legal rights to forbid circumvention of | |
|
|
211 | technological measures. | |
|
|
212 | ||
|
|
213 | 4. Conveying Verbatim Copies. | |
|
|
214 | ||
|
|
215 | You may convey verbatim copies of the Program's source code as you | |
|
|
216 | receive it, in any medium, provided that you conspicuously and | |
|
|
217 | appropriately publish on each copy an appropriate copyright notice; | |
|
|
218 | keep intact all notices stating that this License and any | |
|
|
219 | non-permissive terms added in accord with section 7 apply to the code; | |
|
|
220 | keep intact all notices of the absence of any warranty; and give all | |
|
|
221 | recipients a copy of this License along with the Program. | |
|
|
222 | ||
|
|
223 | You may charge any price or no price for each copy that you convey, | |
|
|
224 | and you may offer support or warranty protection for a fee. | |
|
|
225 | ||
|
|
226 | 5. Conveying Modified Source Versions. | |
|
|
227 | ||
|
|
228 | You may convey a work based on the Program, or the modifications to | |
|
|
229 | produce it from the Program, in the form of source code under the | |
|
|
230 | terms of section 4, provided that you also meet all of these conditions: | |
|
|
231 | ||
|
|
232 | a) The work must carry prominent notices stating that you modified | |
|
|
233 | it, and giving a relevant date. | |
|
|
234 | ||
|
|
235 | b) The work must carry prominent notices stating that it is | |
|
|
236 | released under this License and any conditions added under section | |
|
|
237 | 7. This requirement modifies the requirement in section 4 to | |
|
|
238 | "keep intact all notices". | |
|
|
239 | ||
|
|
240 | c) You must license the entire work, as a whole, under this | |
|
|
241 | License to anyone who comes into possession of a copy. This | |
|
|
242 | License will therefore apply, along with any applicable section 7 | |
|
|
243 | additional terms, to the whole of the work, and all its parts, | |
|
|
244 | regardless of how they are packaged. This License gives no | |
|
|
245 | permission to license the work in any other way, but it does not | |
|
|
246 | invalidate such permission if you have separately received it. | |
|
|
247 | ||
|
|
248 | d) If the work has interactive user interfaces, each must display | |
|
|
249 | Appropriate Legal Notices; however, if the Program has interactive | |
|
|
250 | interfaces that do not display Appropriate Legal Notices, your | |
|
|
251 | work need not make them do so. | |
|
|
252 | ||
|
|
253 | A compilation of a covered work with other separate and independent | |
|
|
254 | works, which are not by their nature extensions of the covered work, | |
|
|
255 | and which are not combined with it such as to form a larger program, | |
|
|
256 | in or on a volume of a storage or distribution medium, is called an | |
|
|
257 | "aggregate" if the compilation and its resulting copyright are not | |
|
|
258 | used to limit the access or legal rights of the compilation's users | |
|
|
259 | beyond what the individual works permit. Inclusion of a covered work | |
|
|
260 | in an aggregate does not cause this License to apply to the other | |
|
|
261 | parts of the aggregate. | |
|
|
262 | ||
|
|
263 | 6. Conveying Non-Source Forms. | |
|
|
264 | ||
|
|
265 | You may convey a covered work in object code form under the terms | |
|
|
266 | of sections 4 and 5, provided that you also convey the | |
|
|
267 | machine-readable Corresponding Source under the terms of this License, | |
|
|
268 | in one of these ways: | |
|
|
269 | ||
|
|
270 | a) Convey the object code in, or embodied in, a physical product | |
|
|
271 | (including a physical distribution medium), accompanied by the | |
|
|
272 | Corresponding Source fixed on a durable physical medium | |
|
|
273 | customarily used for software interchange. | |
|
|
274 | ||
|
|
275 | b) Convey the object code in, or embodied in, a physical product | |
|
|
276 | (including a physical distribution medium), accompanied by a | |
|
|
277 | written offer, valid for at least three years and valid for as | |
|
|
278 | long as you offer spare parts or customer support for that product | |
|
|
279 | model, to give anyone who possesses the object code either (1) a | |
|
|
280 | copy of the Corresponding Source for all the software in the | |
|
|
281 | product that is covered by this License, on a durable physical | |
|
|
282 | medium customarily used for software interchange, for a price no | |
|
|
283 | more than your reasonable cost of physically performing this | |
|
|
284 | conveying of source, or (2) access to copy the | |
|
|
285 | Corresponding Source from a network server at no charge. | |
|
|
286 | ||
|
|
287 | c) Convey individual copies of the object code with a copy of the | |
|
|
288 | written offer to provide the Corresponding Source. This | |
|
|
289 | alternative is allowed only occasionally and noncommercially, and | |
|
|
290 | only if you received the object code with such an offer, in accord | |
|
|
291 | with subsection 6b. | |
|
|
292 | ||
|
|
293 | d) Convey the object code by offering access from a designated | |
|
|
294 | place (gratis or for a charge), and offer equivalent access to the | |
|
|
295 | Corresponding Source in the same way through the same place at no | |
|
|
296 | further charge. You need not require recipients to copy the | |
|
|
297 | Corresponding Source along with the object code. If the place to | |
|
|
298 | copy the object code is a network server, the Corresponding Source | |
|
|
299 | may be on a different server (operated by you or a third party) | |
|
|
300 | that supports equivalent copying facilities, provided you maintain | |
|
|
301 | clear directions next to the object code saying where to find the | |
|
|
302 | Corresponding Source. Regardless of what server hosts the | |
|
|
303 | Corresponding Source, you remain obligated to ensure that it is | |
|
|
304 | available for as long as needed to satisfy these requirements. | |
|
|
305 | ||
|
|
306 | e) Convey the object code using peer-to-peer transmission, provided | |
|
|
307 | you inform other peers where the object code and Corresponding | |
|
|
308 | Source of the work are being offered to the general public at no | |
|
|
309 | charge under subsection 6d. | |
|
|
310 | ||
|
|
311 | A separable portion of the object code, whose source code is excluded | |
|
|
312 | from the Corresponding Source as a System Library, need not be | |
|
|
313 | included in conveying the object code work. | |
|
|
314 | ||
|
|
315 | A "User Product" is either (1) a "consumer product", which means any | |
|
|
316 | tangible personal property which is normally used for personal, family, | |
|
|
317 | or household purposes, or (2) anything designed or sold for incorporation | |
|
|
318 | into a dwelling. In determining whether a product is a consumer product, | |
|
|
319 | doubtful cases shall be resolved in favor of coverage. For a particular | |
|
|
320 | product received by a particular user, "normally used" refers to a | |
|
|
321 | typical or common use of that class of product, regardless of the status | |
|
|
322 | of the particular user or of the way in which the particular user | |
|
|
323 | actually uses, or expects or is expected to use, the product. A product | |
|
|
324 | is a consumer product regardless of whether the product has substantial | |
|
|
325 | commercial, industrial or non-consumer uses, unless such uses represent | |
|
|
326 | the only significant mode of use of the product. | |
|
|
327 | ||
|
|
328 | "Installation Information" for a User Product means any methods, | |
|
|
329 | procedures, authorization keys, or other information required to install | |
|
|
330 | and execute modified versions of a covered work in that User Product from | |
|
|
331 | a modified version of its Corresponding Source. The information must | |
|
|
332 | suffice to ensure that the continued functioning of the modified object | |
|
|
333 | code is in no case prevented or interfered with solely because | |
|
|
334 | modification has been made. | |
|
|
335 | ||
|
|
336 | If you convey an object code work under this section in, or with, or | |
|
|
337 | specifically for use in, a User Product, and the conveying occurs as | |
|
|
338 | part of a transaction in which the right of possession and use of the | |
|
|
339 | User Product is transferred to the recipient in perpetuity or for a | |
|
|
340 | fixed term (regardless of how the transaction is characterized), the | |
|
|
341 | Corresponding Source conveyed under this section must be accompanied | |
|
|
342 | by the Installation Information. But this requirement does not apply | |
|
|
343 | if neither you nor any third party retains the ability to install | |
|
|
344 | modified object code on the User Product (for example, the work has | |
|
|
345 | been installed in ROM). | |
|
|
346 | ||
|
|
347 | The requirement to provide Installation Information does not include a | |
|
|
348 | requirement to continue to provide support service, warranty, or updates | |
|
|
349 | for a work that has been modified or installed by the recipient, or for | |
|
|
350 | the User Product in which it has been modified or installed. Access to a | |
|
|
351 | network may be denied when the modification itself materially and | |
|
|
352 | adversely affects the operation of the network or violates the rules and | |
|
|
353 | protocols for communication across the network. | |
|
|
354 | ||
|
|
355 | Corresponding Source conveyed, and Installation Information provided, | |
|
|
356 | in accord with this section must be in a format that is publicly | |
|
|
357 | documented (and with an implementation available to the public in | |
|
|
358 | source code form), and must require no special password or key for | |
|
|
359 | unpacking, reading or copying. | |
|
|
360 | ||
|
|
361 | 7. Additional Terms. | |
|
|
362 | ||
|
|
363 | "Additional permissions" are terms that supplement the terms of this | |
|
|
364 | License by making exceptions from one or more of its conditions. | |
|
|
365 | Additional permissions that are applicable to the entire Program shall | |
|
|
366 | be treated as though they were included in this License, to the extent | |
|
|
367 | that they are valid under applicable law. If additional permissions | |
|
|
368 | apply only to part of the Program, that part may be used separately | |
|
|
369 | under those permissions, but the entire Program remains governed by | |
|
|
370 | this License without regard to the additional permissions. | |
|
|
371 | ||
|
|
372 | When you convey a copy of a covered work, you may at your option | |
|
|
373 | remove any additional permissions from that copy, or from any part of | |
|
|
374 | it. (Additional permissions may be written to require their own | |
|
|
375 | removal in certain cases when you modify the work.) You may place | |
|
|
376 | additional permissions on material, added by you to a covered work, | |
|
|
377 | for which you have or can give appropriate copyright permission. | |
|
|
378 | ||
|
|
379 | Notwithstanding any other provision of this License, for material you | |
|
|
380 | add to a covered work, you may (if authorized by the copyright holders of | |
|
|
381 | that material) supplement the terms of this License with terms: | |
|
|
382 | ||
|
|
383 | a) Disclaiming warranty or limiting liability differently from the | |
|
|
384 | terms of sections 15 and 16 of this License; or | |
|
|
385 | ||
|
|
386 | b) Requiring preservation of specified reasonable legal notices or | |
|
|
387 | author attributions in that material or in the Appropriate Legal | |
|
|
388 | Notices displayed by works containing it; or | |
|
|
389 | ||
|
|
390 | c) Prohibiting misrepresentation of the origin of that material, or | |
|
|
391 | requiring that modified versions of such material be marked in | |
|
|
392 | reasonable ways as different from the original version; or | |
|
|
393 | ||
|
|
394 | d) Limiting the use for publicity purposes of names of licensors or | |
|
|
395 | authors of the material; or | |
|
|
396 | ||
|
|
397 | e) Declining to grant rights under trademark law for use of some | |
|
|
398 | trade names, trademarks, or service marks; or | |
|
|
399 | ||
|
|
400 | f) Requiring indemnification of licensors and authors of that | |
|
|
401 | material by anyone who conveys the material (or modified versions of | |
|
|
402 | it) with contractual assumptions of liability to the recipient, for | |
|
|
403 | any liability that these contractual assumptions directly impose on | |
|
|
404 | those licensors and authors. | |
|
|
405 | ||
|
|
406 | All other non-permissive additional terms are considered "further | |
|
|
407 | restrictions" within the meaning of section 10. If the Program as you | |
|
|
408 | received it, or any part of it, contains a notice stating that it is | |
|
|
409 | governed by this License along with a term that is a further | |
|
|
410 | restriction, you may remove that term. If a license document contains | |
|
|
411 | a further restriction but permits relicensing or conveying under this | |
|
|
412 | License, you may add to a covered work material governed by the terms | |
|
|
413 | of that license document, provided that the further restriction does | |
|
|
414 | not survive such relicensing or conveying. | |
|
|
415 | ||
|
|
416 | If you add terms to a covered work in accord with this section, you | |
|
|
417 | must place, in the relevant source files, a statement of the | |
|
|
418 | additional terms that apply to those files, or a notice indicating | |
|
|
419 | where to find the applicable terms. | |
|
|
420 | ||
|
|
421 | Additional terms, permissive or non-permissive, may be stated in the | |
|
|
422 | form of a separately written license, or stated as exceptions; | |
|
|
423 | the above requirements apply either way. | |
|
|
424 | ||
|
|
425 | 8. Termination. | |
|
|
426 | ||
|
|
427 | You may not propagate or modify a covered work except as expressly | |
|
|
428 | provided under this License. Any attempt otherwise to propagate or | |
|
|
429 | modify it is void, and will automatically terminate your rights under | |
|
|
430 | this License (including any patent licenses granted under the third | |
|
|
431 | paragraph of section 11). | |
|
|
432 | ||
|
|
433 | However, if you cease all violation of this License, then your | |
|
|
434 | license from a particular copyright holder is reinstated (a) | |
|
|
435 | provisionally, unless and until the copyright holder explicitly and | |
|
|
436 | finally terminates your license, and (b) permanently, if the copyright | |
|
|
437 | holder fails to notify you of the violation by some reasonable means | |
|
|
438 | prior to 60 days after the cessation. | |
|
|
439 | ||
|
|
440 | Moreover, your license from a particular copyright holder is | |
|
|
441 | reinstated permanently if the copyright holder notifies you of the | |
|
|
442 | violation by some reasonable means, this is the first time you have | |
|
|
443 | received notice of violation of this License (for any work) from that | |
|
|
444 | copyright holder, and you cure the violation prior to 30 days after | |
|
|
445 | your receipt of the notice. | |
|
|
446 | ||
|
|
447 | Termination of your rights under this section does not terminate the | |
|
|
448 | licenses of parties who have received copies or rights from you under | |
|
|
449 | this License. If your rights have been terminated and not permanently | |
|
|
450 | reinstated, you do not qualify to receive new licenses for the same | |
|
|
451 | material under section 10. | |
|
|
452 | ||
|
|
453 | 9. Acceptance Not Required for Having Copies. | |
|
|
454 | ||
|
|
455 | You are not required to accept this License in order to receive or | |
|
|
456 | run a copy of the Program. Ancillary propagation of a covered work | |
|
|
457 | occurring solely as a consequence of using peer-to-peer transmission | |
|
|
458 | to receive a copy likewise does not require acceptance. However, | |
|
|
459 | nothing other than this License grants you permission to propagate or | |
|
|
460 | modify any covered work. These actions infringe copyright if you do | |
|
|
461 | not accept this License. Therefore, by modifying or propagating a | |
|
|
462 | covered work, you indicate your acceptance of this License to do so. | |
|
|
463 | ||
|
|
464 | 10. Automatic Licensing of Downstream Recipients. | |
|
|
465 | ||
|
|
466 | Each time you convey a covered work, the recipient automatically | |
|
|
467 | receives a license from the original licensors, to run, modify and | |
|
|
468 | propagate that work, subject to this License. You are not responsible | |
|
|
469 | for enforcing compliance by third parties with this License. | |
|
|
470 | ||
|
|
471 | An "entity transaction" is a transaction transferring control of an | |
|
|
472 | organization, or substantially all assets of one, or subdividing an | |
|
|
473 | organization, or merging organizations. If propagation of a covered | |
|
|
474 | work results from an entity transaction, each party to that | |
|
|
475 | transaction who receives a copy of the work also receives whatever | |
|
|
476 | licenses to the work the party's predecessor in interest had or could | |
|
|
477 | give under the previous paragraph, plus a right to possession of the | |
|
|
478 | Corresponding Source of the work from the predecessor in interest, if | |
|
|
479 | the predecessor has it or can get it with reasonable efforts. | |
|
|
480 | ||
|
|
481 | You may not impose any further restrictions on the exercise of the | |
|
|
482 | rights granted or affirmed under this License. For example, you may | |
|
|
483 | not impose a license fee, royalty, or other charge for exercise of | |
|
|
484 | rights granted under this License, and you may not initiate litigation | |
|
|
485 | (including a cross-claim or counterclaim in a lawsuit) alleging that | |
|
|
486 | any patent claim is infringed by making, using, selling, offering for | |
|
|
487 | sale, or importing the Program or any portion of it. | |
|
|
488 | ||
|
|
489 | 11. Patents. | |
|
|
490 | ||
|
|
491 | A "contributor" is a copyright holder who authorizes use under this | |
|
|
492 | License of the Program or a work on which the Program is based. The | |
|
|
493 | work thus licensed is called the contributor's "contributor version". | |
|
|
494 | ||
|
|
495 | A contributor's "essential patent claims" are all patent claims | |
|
|
496 | owned or controlled by the contributor, whether already acquired or | |
|
|
497 | hereafter acquired, that would be infringed by some manner, permitted | |
|
|
498 | by this License, of making, using, or selling its contributor version, | |
|
|
499 | but do not include claims that would be infringed only as a | |
|
|
500 | consequence of further modification of the contributor version. For | |
|
|
501 | purposes of this definition, "control" includes the right to grant | |
|
|
502 | patent sublicenses in a manner consistent with the requirements of | |
|
|
503 | this License. | |
|
|
504 | ||
|
|
505 | Each contributor grants you a non-exclusive, worldwide, royalty-free | |
|
|
506 | patent license under the contributor's essential patent claims, to | |
|
|
507 | make, use, sell, offer for sale, import and otherwise run, modify and | |
|
|
508 | propagate the contents of its contributor version. | |
|
|
509 | ||
|
|
510 | In the following three paragraphs, a "patent license" is any express | |
|
|
511 | agreement or commitment, however denominated, not to enforce a patent | |
|
|
512 | (such as an express permission to practice a patent or covenant not to | |
|
|
513 | sue for patent infringement). To "grant" such a patent license to a | |
|
|
514 | party means to make such an agreement or commitment not to enforce a | |
|
|
515 | patent against the party. | |
|
|
516 | ||
|
|
517 | If you convey a covered work, knowingly relying on a patent license, | |
|
|
518 | and the Corresponding Source of the work is not available for anyone | |
|
|
519 | to copy, free of charge and under the terms of this License, through a | |
|
|
520 | publicly available network server or other readily accessible means, | |
|
|
521 | then you must either (1) cause the Corresponding Source to be so | |
|
|
522 | available, or (2) arrange to deprive yourself of the benefit of the | |
|
|
523 | patent license for this particular work, or (3) arrange, in a manner | |
|
|
524 | consistent with the requirements of this License, to extend the patent | |
|
|
525 | license to downstream recipients. "Knowingly relying" means you have | |
|
|
526 | actual knowledge that, but for the patent license, your conveying the | |
|
|
527 | covered work in a country, or your recipient's use of the covered work | |
|
|
528 | in a country, would infringe one or more identifiable patents in that | |
|
|
529 | country that you have reason to believe are valid. | |
|
|
530 | ||
|
|
531 | If, pursuant to or in connection with a single transaction or | |
|
|
532 | arrangement, you convey, or propagate by procuring conveyance of, a | |
|
|
533 | covered work, and grant a patent license to some of the parties | |
|
|
534 | receiving the covered work authorizing them to use, propagate, modify | |
|
|
535 | or convey a specific copy of the covered work, then the patent license | |
|
|
536 | you grant is automatically extended to all recipients of the covered | |
|
|
537 | work and works based on it. | |
|
|
538 | ||
|
|
539 | A patent license is "discriminatory" if it does not include within | |
|
|
540 | the scope of its coverage, prohibits the exercise of, or is | |
|
|
541 | conditioned on the non-exercise of one or more of the rights that are | |
|
|
542 | specifically granted under this License. You may not convey a covered | |
|
|
543 | work if you are a party to an arrangement with a third party that is | |
|
|
544 | in the business of distributing software, under which you make payment | |
|
|
545 | to the third party based on the extent of your activity of conveying | |
|
|
546 | the work, and under which the third party grants, to any of the | |
|
|
547 | parties who would receive the covered work from you, a discriminatory | |
|
|
548 | patent license (a) in connection with copies of the covered work | |
|
|
549 | conveyed by you (or copies made from those copies), or (b) primarily | |
|
|
550 | for and in connection with specific products or compilations that | |
|
|
551 | contain the covered work, unless you entered into that arrangement, | |
|
|
552 | or that patent license was granted, prior to 28 March 2007. | |
|
|
553 | ||
|
|
554 | Nothing in this License shall be construed as excluding or limiting | |
|
|
555 | any implied license or other defenses to infringement that may | |
|
|
556 | otherwise be available to you under applicable patent law. | |
|
|
557 | ||
|
|
558 | 12. No Surrender of Others' Freedom. | |
|
|
559 | ||
|
|
560 | If conditions are imposed on you (whether by court order, agreement or | |
|
|
561 | otherwise) that contradict the conditions of this License, they do not | |
|
|
562 | excuse you from the conditions of this License. If you cannot convey a | |
|
|
563 | covered work so as to satisfy simultaneously your obligations under this | |
|
|
564 | License and any other pertinent obligations, then as a consequence you may | |
|
|
565 | not convey it at all. For example, if you agree to terms that obligate you | |
|
|
566 | to collect a royalty for further conveying from those to whom you convey | |
|
|
567 | the Program, the only way you could satisfy both those terms and this | |
|
|
568 | License would be to refrain entirely from conveying the Program. | |
|
|
569 | ||
|
|
570 | 13. Use with the GNU Affero General Public License. | |
|
|
571 | ||
|
|
572 | Notwithstanding any other provision of this License, you have | |
|
|
573 | permission to link or combine any covered work with a work licensed | |
|
|
574 | under version 3 of the GNU Affero General Public License into a single | |
|
|
575 | combined work, and to convey the resulting work. The terms of this | |
|
|
576 | License will continue to apply to the part which is the covered work, | |
|
|
577 | but the special requirements of the GNU Affero General Public License, | |
|
|
578 | section 13, concerning interaction through a network will apply to the | |
|
|
579 | combination as such. | |
|
|
580 | ||
|
|
581 | 14. Revised Versions of this License. | |
|
|
582 | ||
|
|
583 | The Free Software Foundation may publish revised and/or new versions of | |
|
|
584 | the GNU General Public License from time to time. Such new versions will | |
|
|
585 | be similar in spirit to the present version, but may differ in detail to | |
|
|
586 | address new problems or concerns. | |
|
|
587 | ||
|
|
588 | Each version is given a distinguishing version number. If the | |
|
|
589 | Program specifies that a certain numbered version of the GNU General | |
|
|
590 | Public License "or any later version" applies to it, you have the | |
|
|
591 | option of following the terms and conditions either of that numbered | |
|
|
592 | version or of any later version published by the Free Software | |
|
|
593 | Foundation. If the Program does not specify a version number of the | |
|
|
594 | GNU General Public License, you may choose any version ever published | |
|
|
595 | by the Free Software Foundation. | |
|
|
596 | ||
|
|
597 | If the Program specifies that a proxy can decide which future | |
|
|
598 | versions of the GNU General Public License can be used, that proxy's | |
|
|
599 | public statement of acceptance of a version permanently authorizes you | |
|
|
600 | to choose that version for the Program. | |
|
|
601 | ||
|
|
602 | Later license versions may give you additional or different | |
|
|
603 | permissions. However, no additional obligations are imposed on any | |
|
|
604 | author or copyright holder as a result of your choosing to follow a | |
|
|
605 | later version. | |
|
|
606 | ||
|
|
607 | 15. Disclaimer of Warranty. | |
|
|
608 | ||
|
|
609 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | |
|
|
610 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | |
|
|
611 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | |
|
|
612 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | |
|
|
613 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
|
|
614 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | |
|
|
615 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | |
|
|
616 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |
|
|
617 | ||
|
|
618 | 16. Limitation of Liability. | |
|
|
619 | ||
|
|
620 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |
|
|
621 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | |
|
|
622 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | |
|
|
623 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | |
|
|
624 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | |
|
|
625 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | |
|
|
626 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | |
|
|
627 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | |
|
|
628 | SUCH DAMAGES. | |
|
|
629 | ||
|
|
630 | 17. Interpretation of Sections 15 and 16. | |
|
|
631 | ||
|
|
632 | If the disclaimer of warranty and limitation of liability provided | |
|
|
633 | above cannot be given local legal effect according to their terms, | |
|
|
634 | reviewing courts shall apply local law that most closely approximates | |
|
|
635 | an absolute waiver of all civil liability in connection with the | |
|
|
636 | Program, unless a warranty or assumption of liability accompanies a | |
|
|
637 | copy of the Program in return for a fee. | |
|
|
638 | ||
|
|
639 | END OF TERMS AND CONDITIONS | |
|
|
640 | ||
|
|
641 | How to Apply These Terms to Your New Programs | |
|
|
642 | ||
|
|
643 | If you develop a new program, and you want it to be of the greatest | |
|
|
644 | possible use to the public, the best way to achieve this is to make it | |
|
|
645 | free software which everyone can redistribute and change under these terms. | |
|
|
646 | ||
|
|
647 | To do so, attach the following notices to the program. It is safest | |
|
|
648 | to attach them to the start of each source file to most effectively | |
|
|
649 | state the exclusion of warranty; and each file should have at least | |
|
|
650 | the "copyright" line and a pointer to where the full notice is found. | |
|
|
651 | ||
|
|
652 | <one line to give the program's name and a brief idea of what it does.> | |
|
|
653 | Copyright (C) <year> <name of author> | |
|
|
654 | ||
|
|
655 | This program is free software: you can redistribute it and/or modify | |
|
|
656 | it under the terms of the GNU General Public License as published by | |
|
|
657 | the Free Software Foundation, either version 3 of the License, or | |
|
|
658 | (at your option) any later version. | |
|
|
659 | ||
|
|
660 | This program is distributed in the hope that it will be useful, | |
|
|
661 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
|
662 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
|
663 | GNU General Public License for more details. | |
|
|
664 | ||
|
|
665 | You should have received a copy of the GNU General Public License | |
|
|
666 | along with this program. If not, see <https://www.gnu.org/licenses/>. | |
|
|
667 | ||
|
|
668 | Also add information on how to contact you by electronic and paper mail. | |
|
|
669 | ||
|
|
670 | If the program does terminal interaction, make it output a short | |
|
|
671 | notice like this when it starts in an interactive mode: | |
|
|
672 | ||
|
|
673 | <program> Copyright (C) <year> <name of author> | |
|
|
674 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |
|
|
675 | This is free software, and you are welcome to redistribute it | |
|
|
676 | under certain conditions; type `show c' for details. | |
|
|
677 | ||
|
|
678 | The hypothetical commands `show w' and `show c' should show the appropriate | |
|
|
679 | parts of the General Public License. Of course, your program's commands | |
|
|
680 | might be different; for a GUI interface, you would use an "about box". | |
|
|
681 | ||
|
|
682 | You should also get your employer (if you work as a programmer) or school, | |
|
|
683 | if any, to sign a "copyright disclaimer" for the program, if necessary. | |
|
|
684 | For more information on this, and how to apply and follow the GNU GPL, see | |
|
|
685 | <https://www.gnu.org/licenses/>. | |
|
|
686 | ||
|
|
687 | The GNU General Public License does not permit incorporating your program | |
|
|
688 | into proprietary programs. If your program is a subroutine library, you | |
|
|
689 | may consider it more useful to permit linking proprietary applications with | |
|
|
690 | the library. If this is what you want to do, use the GNU Lesser General | |
|
|
691 | Public License instead of this License. But first, please read | |
|
|
692 | <https://www.gnu.org/licenses/why-not-lgpl.html>. No newline at end of file | |
| @@ -0,0 +1,19 | |||
|
|
1 | Copyright (c) 2016-2017 Drew DeVault | |
|
|
2 | ||
|
|
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of | |
|
|
4 | this software and associated documentation files (the "Software"), to deal in | |
|
|
5 | the Software without restriction, including without limitation the rights to | |
|
|
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |
|
|
7 | of the Software, and to permit persons to whom the Software is furnished to do | |
|
|
8 | so, subject to the following conditions: | |
|
|
9 | ||
|
|
10 | The above copyright notice and this permission notice shall be included in all | |
|
|
11 | copies or substantial portions of the Software. | |
|
|
12 | ||
|
|
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
|
|
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
|
|
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
|
|
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
|
|
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
|
|
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
|
|
19 | SOFTWARE. | |
| @@ -0,0 +1,127 | |||
|
|
1 | dwl is originally based on TinyWL, which is used under the following license: | |
|
|
2 | ||
|
|
3 | This work is licensed under CC0, which effectively puts it in the public domain. | |
|
|
4 | ||
|
|
5 | --- | |
|
|
6 | ||
|
|
7 | Creative Commons Legal Code | |
|
|
8 | ||
|
|
9 | CC0 1.0 Universal | |
|
|
10 | ||
|
|
11 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE | |
|
|
12 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN | |
|
|
13 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS | |
|
|
14 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES | |
|
|
15 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS | |
|
|
16 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM | |
|
|
17 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED | |
|
|
18 | HEREUNDER. | |
|
|
19 | ||
|
|
20 | Statement of Purpose | |
|
|
21 | ||
|
|
22 | The laws of most jurisdictions throughout the world automatically confer | |
|
|
23 | exclusive Copyright and Related Rights (defined below) upon the creator | |
|
|
24 | and subsequent owner(s) (each and all, an "owner") of an original work of | |
|
|
25 | authorship and/or a database (each, a "Work"). | |
|
|
26 | ||
|
|
27 | Certain owners wish to permanently relinquish those rights to a Work for | |
|
|
28 | the purpose of contributing to a commons of creative, cultural and | |
|
|
29 | scientific works ("Commons") that the public can reliably and without fear | |
|
|
30 | of later claims of infringement build upon, modify, incorporate in other | |
|
|
31 | works, reuse and redistribute as freely as possible in any form whatsoever | |
|
|
32 | and for any purposes, including without limitation commercial purposes. | |
|
|
33 | These owners may contribute to the Commons to promote the ideal of a free | |
|
|
34 | culture and the further production of creative, cultural and scientific | |
|
|
35 | works, or to gain reputation or greater distribution for their Work in | |
|
|
36 | part through the use and efforts of others. | |
|
|
37 | ||
|
|
38 | For these and/or other purposes and motivations, and without any | |
|
|
39 | expectation of additional consideration or compensation, the person | |
|
|
40 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she | |
|
|
41 | is an owner of Copyright and Related Rights in the Work, voluntarily | |
|
|
42 | elects to apply CC0 to the Work and publicly distribute the Work under its | |
|
|
43 | terms, with knowledge of his or her Copyright and Related Rights in the | |
|
|
44 | Work and the meaning and intended legal effect of CC0 on those rights. | |
|
|
45 | ||
|
|
46 | 1. Copyright and Related Rights. A Work made available under CC0 may be | |
|
|
47 | protected by copyright and related or neighboring rights ("Copyright and | |
|
|
48 | Related Rights"). Copyright and Related Rights include, but are not | |
|
|
49 | limited to, the following: | |
|
|
50 | ||
|
|
51 | i. the right to reproduce, adapt, distribute, perform, display, | |
|
|
52 | communicate, and translate a Work; | |
|
|
53 | ii. moral rights retained by the original author(s) and/or performer(s); | |
|
|
54 | iii. publicity and privacy rights pertaining to a person's image or | |
|
|
55 | likeness depicted in a Work; | |
|
|
56 | iv. rights protecting against unfair competition in regards to a Work, | |
|
|
57 | subject to the limitations in paragraph 4(a), below; | |
|
|
58 | v. rights protecting the extraction, dissemination, use and reuse of data | |
|
|
59 | in a Work; | |
|
|
60 | vi. database rights (such as those arising under Directive 96/9/EC of the | |
|
|
61 | European Parliament and of the Council of 11 March 1996 on the legal | |
|
|
62 | protection of databases, and under any national implementation | |
|
|
63 | thereof, including any amended or successor version of such | |
|
|
64 | directive); and | |
|
|
65 | vii. other similar, equivalent or corresponding rights throughout the | |
|
|
66 | world based on applicable law or treaty, and any national | |
|
|
67 | implementations thereof. | |
|
|
68 | ||
|
|
69 | 2. Waiver. To the greatest extent permitted by, but not in contravention | |
|
|
70 | of, applicable law, Affirmer hereby overtly, fully, permanently, | |
|
|
71 | irrevocably and unconditionally waives, abandons, and surrenders all of | |
|
|
72 | Affirmer's Copyright and Related Rights and associated claims and causes | |
|
|
73 | of action, whether now known or unknown (including existing as well as | |
|
|
74 | future claims and causes of action), in the Work (i) in all territories | |
|
|
75 | worldwide, (ii) for the maximum duration provided by applicable law or | |
|
|
76 | treaty (including future time extensions), (iii) in any current or future | |
|
|
77 | medium and for any number of copies, and (iv) for any purpose whatsoever, | |
|
|
78 | including without limitation commercial, advertising or promotional | |
|
|
79 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each | |
|
|
80 | member of the public at large and to the detriment of Affirmer's heirs and | |
|
|
81 | successors, fully intending that such Waiver shall not be subject to | |
|
|
82 | revocation, rescission, cancellation, termination, or any other legal or | |
|
|
83 | equitable action to disrupt the quiet enjoyment of the Work by the public | |
|
|
84 | as contemplated by Affirmer's express Statement of Purpose. | |
|
|
85 | ||
|
|
86 | 3. Public License Fallback. Should any part of the Waiver for any reason | |
|
|
87 | be judged legally invalid or ineffective under applicable law, then the | |
|
|
88 | Waiver shall be preserved to the maximum extent permitted taking into | |
|
|
89 | account Affirmer's express Statement of Purpose. In addition, to the | |
|
|
90 | extent the Waiver is so judged Affirmer hereby grants to each affected | |
|
|
91 | person a royalty-free, non transferable, non sublicensable, non exclusive, | |
|
|
92 | irrevocable and unconditional license to exercise Affirmer's Copyright and | |
|
|
93 | Related Rights in the Work (i) in all territories worldwide, (ii) for the | |
|
|
94 | maximum duration provided by applicable law or treaty (including future | |
|
|
95 | time extensions), (iii) in any current or future medium and for any number | |
|
|
96 | of copies, and (iv) for any purpose whatsoever, including without | |
|
|
97 | limitation commercial, advertising or promotional purposes (the | |
|
|
98 | "License"). The License shall be deemed effective as of the date CC0 was | |
|
|
99 | applied by Affirmer to the Work. Should any part of the License for any | |
|
|
100 | reason be judged legally invalid or ineffective under applicable law, such | |
|
|
101 | partial invalidity or ineffectiveness shall not invalidate the remainder | |
|
|
102 | of the License, and in such case Affirmer hereby affirms that he or she | |
|
|
103 | will not (i) exercise any of his or her remaining Copyright and Related | |
|
|
104 | Rights in the Work or (ii) assert any associated claims and causes of | |
|
|
105 | action with respect to the Work, in either case contrary to Affirmer's | |
|
|
106 | express Statement of Purpose. | |
|
|
107 | ||
|
|
108 | 4. Limitations and Disclaimers. | |
|
|
109 | ||
|
|
110 | a. No trademark or patent rights held by Affirmer are waived, abandoned, | |
|
|
111 | surrendered, licensed or otherwise affected by this document. | |
|
|
112 | b. Affirmer offers the Work as-is and makes no representations or | |
|
|
113 | warranties of any kind concerning the Work, express, implied, | |
|
|
114 | statutory or otherwise, including without limitation warranties of | |
|
|
115 | title, merchantability, fitness for a particular purpose, non | |
|
|
116 | infringement, or the absence of latent or other defects, accuracy, or | |
|
|
117 | the present or absence of errors, whether or not discoverable, all to | |
|
|
118 | the greatest extent permissible under applicable law. | |
|
|
119 | c. Affirmer disclaims responsibility for clearing rights of other persons | |
|
|
120 | that may apply to the Work or any use thereof, including without | |
|
|
121 | limitation any person's Copyright and Related Rights in the Work. | |
|
|
122 | Further, Affirmer disclaims responsibility for obtaining any necessary | |
|
|
123 | consents, permissions or other rights required for any use of the | |
|
|
124 | Work. | |
|
|
125 | d. Affirmer understands and acknowledges that Creative Commons is not a | |
|
|
126 | party to this document and has no duty or obligation with respect to | |
|
|
127 | this CC0 or use of the Work. | |
| @@ -0,0 +1,21 | |||
|
|
1 | Copyright (c) 2017, 2018 Drew DeVault | |
|
|
2 | Copyright (c) 2014 Jari Vetoniemi | |
|
|
3 | Copyright (c) 2023 The wlroots contributors | |
|
|
4 | ||
|
|
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of | |
|
|
6 | this software and associated documentation files (the "Software"), to deal in | |
|
|
7 | the Software without restriction, including without limitation the rights to | |
|
|
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |
|
|
9 | of the Software, and to permit persons to whom the Software is furnished to do | |
|
|
10 | so, subject to the following conditions: | |
|
|
11 | ||
|
|
12 | The above copyright notice and this permission notice shall be included in all | |
|
|
13 | copies or substantial portions of the Software. | |
|
|
14 | ||
|
|
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
|
|
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
|
|
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
|
|
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
|
|
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
|
|
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
|
|
21 | SOFTWARE. | |
| This diff has been collapsed as it changes many lines, (757 lines changed) Show them Hide them | |||
| @@ -0,0 +1,757 | |||
|
|
1 | /* Here be a small dragon. | |
|
|
2 | * Not as large as the monster | |
|
|
3 | * in src/swindle.c | |
|
|
4 | * but you get the idea */ | |
|
|
5 | ||
|
|
6 | #include "parser.h" | |
|
|
7 | ||
|
|
8 | #include <stdio.h> | |
|
|
9 | #include <stdlib.h> | |
|
|
10 | #include <string.h> | |
|
|
11 | #include <errno.h> | |
|
|
12 | #include <time.h> | |
|
|
13 | #include <unistd.h> | |
|
|
14 | #include <signal.h> | |
|
|
15 | #include <sys/wait.h> | |
|
|
16 | #include <sys/inotify.h> | |
|
|
17 | #include <linux/input-event-codes.h> | |
|
|
18 | #include <xkbcommon/xkbcommon.h> | |
|
|
19 | #include <wayland-server-core.h> | |
|
|
20 | ||
|
|
21 | /* Lua */ | |
|
|
22 | #include <lua.h> | |
|
|
23 | #include <lauxlib.h> | |
|
|
24 | #include <lualib.h> | |
|
|
25 | ||
|
|
26 | /* wlroots */ | |
|
|
27 | #include <wlr/util/log.h> | |
|
|
28 | #include <wlr/types/wlr_keyboard.h> | |
|
|
29 | #include <libinput.h> | |
|
|
30 | ||
|
|
31 | /* Forward declarations from src/swindle.c */ | |
|
|
32 | extern struct wl_list mons; | |
|
|
33 | extern struct wl_list clients; | |
|
|
34 | void arrange(void *m); | |
|
|
35 | ||
|
|
36 | /* Internal watcher state */ | |
|
|
37 | ||
|
|
38 | typedef struct { | |
|
|
39 | int inotify_fd; | |
|
|
40 | int watch_fd; | |
|
|
41 | char path[1024]; | |
|
|
42 | config_reload_cb cb; | |
|
|
43 | void *userdata; | |
|
|
44 | struct wl_event_source *event_src; | |
|
|
45 | } WatchState; | |
|
|
46 | ||
|
|
47 | /* Helpers */ | |
|
|
48 | ||
|
|
49 | static void | |
|
|
50 | lua_log_error(lua_State *L, const char *context) | |
|
|
51 | { | |
|
|
52 | fprintf(stderr, "swindle config [%s]: %s\n", | |
|
|
53 | context, lua_tostring(L, -1)); | |
|
|
54 | lua_pop(L, 1); | |
|
|
55 | } | |
|
|
56 | ||
|
|
57 | /* Get a string field from the table at the top of the stack | |
|
|
58 | * Writes into buf and returns false and leaves buf untouched on failure | |
|
|
59 | */ | |
|
|
60 | ||
|
|
61 | static bool | |
|
|
62 | lua_get_string(lua_State *L, const char *key, char *buf, size_t bufsz) | |
|
|
63 | { | |
|
|
64 | lua_getfield(L, -1, key); | |
|
|
65 | bool ok = lua_isstring(L, -1); | |
|
|
66 | if (ok) | |
|
|
67 | strncpy(buf, lua_tostring(L, -1), bufsz - 1); | |
|
|
68 | lua_pop(L, 1); | |
|
|
69 | return ok; | |
|
|
70 | } | |
|
|
71 | ||
|
|
72 | /* Get an integer field. It falls back to `def` if missing or wrong type */ | |
|
|
73 | ||
|
|
74 | static int | |
|
|
75 | lua_get_int(lua_State *L, const char *key, int def) | |
|
|
76 | { | |
|
|
77 | lua_getfield(L, -1, key); | |
|
|
78 | int val = lua_isnumber(L, -1) ? (int)lua_tointeger(L, -1) : def; | |
|
|
79 | lua_pop(L, 1); | |
|
|
80 | return val; | |
|
|
81 | } | |
|
|
82 | ||
|
|
83 | static double | |
|
|
84 | lua_get_double(lua_State *L, const char *key, double def) | |
|
|
85 | { | |
|
|
86 | lua_getfield(L, -1, key); | |
|
|
87 | double val = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : def; | |
|
|
88 | lua_pop(L, 1); | |
|
|
89 | return val; | |
|
|
90 | } | |
|
|
91 | ||
|
|
92 | static bool | |
|
|
93 | lua_get_bool(lua_State *L, const char *key, bool def) | |
|
|
94 | { | |
|
|
95 | lua_getfield(L, -1, key); | |
|
|
96 | bool val = lua_isboolean(L, -1) ? lua_toboolean(L, -1) : def; | |
|
|
97 | lua_pop(L, 1); | |
|
|
98 | return val; | |
|
|
99 | } | |
|
|
100 | ||
|
|
101 | /* wlroots hard-asserts opacity is in [0,1] and takes the whole thing | |
|
|
102 | * down with it if it isn't (as it should), so it might as well clamp anything | |
|
|
103 | * a user's config throws at it because users are kinda unwise */ | |
|
|
104 | ||
|
|
105 | static float | |
|
|
106 | lua_get_opacity(lua_State *L, const char *key, float def) | |
|
|
107 | { | |
|
|
108 | double v = lua_get_double(L, key, (double)def); | |
|
|
109 | if (v < 0.0) { | |
|
|
110 | fprintf(stderr, "swindle config: '%s' below 0, clamping to 0\n", key); | |
|
|
111 | v = 0.0; | |
|
|
112 | } else if (v > 1.0) { | |
|
|
113 | fprintf(stderr, "swindle config: '%s' above 1, clamping to 1\n", key); | |
|
|
114 | v = 1.0; | |
|
|
115 | } | |
|
|
116 | return (float)v; | |
|
|
117 | } | |
|
|
118 | ||
|
|
119 | static void | |
|
|
120 | parse_color_hex(uint32_t hex, float out[4]) | |
|
|
121 | { | |
|
|
122 | out[0] = ((hex >> 24) & 0xFF) / 255.0f; | |
|
|
123 | out[1] = ((hex >> 16) & 0xFF) / 255.0f; | |
|
|
124 | out[2] = ((hex >> 8) & 0xFF) / 255.0f; | |
|
|
125 | out[3] = ( hex & 0xFF) / 255.0f; | |
|
|
126 | } | |
|
|
127 | ||
|
|
128 | static void | |
|
|
129 | lua_get_color(lua_State *L, const char *key, float out[4], | |
|
|
130 | float r, float g, float b, float a) | |
|
|
131 | { | |
|
|
132 | lua_getfield(L, -1, key); | |
|
|
133 | if (lua_isnumber(L, -1)) | |
|
|
134 | parse_color_hex((uint32_t)lua_tointeger(L, -1), out); | |
|
|
135 | else { | |
|
|
136 | out[0] = r; out[1] = g; out[2] = b; out[3] = a; | |
|
|
137 | } | |
|
|
138 | lua_pop(L, 1); | |
|
|
139 | } | |
|
|
140 | ||
|
|
141 | static uint32_t | |
|
|
142 | parse_modifier(const char *name) | |
|
|
143 | { | |
|
|
144 | if (!strcmp(name, "shift")) return WLR_MODIFIER_SHIFT; | |
|
|
145 | if (!strcmp(name, "ctrl")) return WLR_MODIFIER_CTRL; | |
|
|
146 | if (!strcmp(name, "alt")) return WLR_MODIFIER_ALT; | |
|
|
147 | if (!strcmp(name, "logo")) return WLR_MODIFIER_LOGO; | |
|
|
148 | if (!strcmp(name, "mod2")) return WLR_MODIFIER_MOD2; | |
|
|
149 | if (!strcmp(name, "mod3")) return WLR_MODIFIER_MOD3; | |
|
|
150 | if (!strcmp(name, "mod5")) return WLR_MODIFIER_MOD5; | |
|
|
151 | fprintf(stderr, "swindle config: unknown modifier '%s', ignoring\n", name); | |
|
|
152 | return 0; | |
|
|
153 | } | |
|
|
154 | ||
|
|
155 | /* Section parsers */ | |
|
|
156 | ||
|
|
157 | static void | |
|
|
158 | parse_appearance(lua_State *L, CfgAppearance *a) | |
|
|
159 | { | |
|
|
160 | lua_getglobal(L, "appearance"); | |
|
|
161 | if (!lua_istable(L, -1)) { | |
|
|
162 | fprintf(stderr, "swindle config: 'appearance' table missing' \n"); | |
|
|
163 | lua_pop(L, 1); | |
|
|
164 | /* defaults */ | |
|
|
165 | a->inner_border_px = 1; | |
|
|
166 | a->outer_border_px = 1; | |
|
|
167 | a->gaps = 10; | |
|
|
168 | a->smart_gaps = false; | |
|
|
169 | parse_color_hex(0x222222ff, a->root_color); | |
|
|
170 | parse_color_hex(0x00000000, a->inner_border_color); | |
|
|
171 | parse_color_hex(0x00000000, a->outer_border_color); | |
|
|
172 | parse_color_hex(0xe8e8e8ff, a->inner_focus_color); | |
|
|
173 | parse_color_hex(0xe8e8e8ff, a->outer_focus_color); | |
|
|
174 | parse_color_hex(0xff0000ff, a->inner_urgent_color); | |
|
|
175 | parse_color_hex(0xff0000ff, a->outer_urgent_color); | |
|
|
176 | a->fullscreen_bg[3] = 1.0f; | |
|
|
177 | a->active_opacity = 1.0f; | |
|
|
178 | a->inactive_opacity = 1.0f; | |
|
|
179 | return; | |
|
|
180 | } | |
|
|
181 | ||
|
|
182 | a->inner_border_px = (unsigned int)lua_get_int(L, "inner_border_px", 1); | |
|
|
183 | a->outer_border_px = (unsigned int)lua_get_int(L, "outer_border_px", 1); | |
|
|
184 | a->gaps = (unsigned int)lua_get_int(L, "gaps", 10); | |
|
|
185 | a->smart_gaps = lua_get_bool(L, "smart_gaps", false); | |
|
|
186 | ||
|
|
187 | lua_get_color(L, "root_color", a->root_color, 0.133f,0.133f,0.133f,1.f); | |
|
|
188 | lua_get_color(L, "inner_border_color", a->inner_border_color, 0.f,0.f,0.f,0.f); | |
|
|
189 | lua_get_color(L, "outer_border_color", a->outer_border_color, 0.f,0.f,0.f,0.f); | |
|
|
190 | lua_get_color(L, "inner_focus_color", a->inner_focus_color, 0.91f,0.91f,0.91f,1.f); | |
|
|
191 | lua_get_color(L, "outer_focus_color", a->outer_focus_color, 0.91f,0.91f,0.91f,1.f); | |
|
|
192 | lua_get_color(L, "inner_urgent_color", a->inner_urgent_color, 1.f,0.f,0.f,1.f); | |
|
|
193 | lua_get_color(L, "outer_urgent_color", a->outer_urgent_color, 1.f,0.f,0.f,1.f); | |
|
|
194 | ||
|
|
195 | a->active_opacity = lua_get_opacity(L, "active_opacity", 1.0f); | |
|
|
196 | a->inactive_opacity = lua_get_opacity(L, "inactive_opacity", 1.0f); | |
|
|
197 | ||
|
|
198 | lua_getfield(L, -1, "fullscreen_bg"); | |
|
|
199 | if (lua_isnumber(L, -1)) | |
|
|
200 | parse_color_hex((uint32_t)lua_tointeger(L, -1), a->fullscreen_bg); | |
|
|
201 | else { | |
|
|
202 | a->fullscreen_bg[0] = 0.f; | |
|
|
203 | a->fullscreen_bg[1] = 0.f; | |
|
|
204 | a->fullscreen_bg[2] = 0.f; | |
|
|
205 | a->fullscreen_bg[3] = 1.f; | |
|
|
206 | } | |
|
|
207 | lua_pop(L, 1); | |
|
|
208 | ||
|
|
209 | lua_pop(L, 1); /* pop appearance table */ | |
|
|
210 | } | |
|
|
211 | ||
|
|
212 | static void | |
|
|
213 | parse_input(lua_State *L, CfgInput *inp) | |
|
|
214 | { | |
|
|
215 | lua_getglobal(L, "input"); | |
|
|
216 | if (!lua_istable(L, -1)) { | |
|
|
217 | fprintf(stderr, "swindle config: 'input' table missing, " | |
|
|
218 | "using defaults. You'll feel the repeat delay.\n"); | |
|
|
219 | lua_pop(L, 1); | |
|
|
220 | inp->repeat_rate = 50; | |
|
|
221 | inp->repeat_delay = 150; | |
|
|
222 | inp->tap_to_click = true; | |
|
|
223 | inp->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; | |
|
|
224 | strcpy(inp->layout, "us"); | |
|
|
225 | return; | |
|
|
226 | } | |
|
|
227 | ||
|
|
228 | inp->repeat_rate = lua_get_int (L, "repeat_rate", 50); | |
|
|
229 | inp->repeat_delay = lua_get_int (L, "repeat_delay", 150); | |
|
|
230 | inp->tap_to_click = lua_get_bool(L, "tap_to_click", true); | |
|
|
231 | inp->tap_and_drag = lua_get_bool(L, "tap_and_drag", true); | |
|
|
232 | inp->drag_lock = lua_get_bool(L, "drag_lock", true); | |
|
|
233 | inp->natural_scrolling = lua_get_bool(L, "natural_scrolling", false); | |
|
|
234 | inp->disable_while_typing = lua_get_bool(L, "disable_while_typing", true); | |
|
|
235 | inp->left_handed = lua_get_bool(L, "left_handed", false); | |
|
|
236 | inp->middle_button_emulation= lua_get_bool(L, "middle_button_emulation",false); | |
|
|
237 | inp->accel_speed = lua_get_double(L, "accel_speed", 0.0); | |
|
|
238 | ||
|
|
239 | lua_get_string(L, "layout", inp->layout, sizeof(inp->layout)); | |
|
|
240 | lua_get_string(L, "variant", inp->variant, sizeof(inp->variant)); | |
|
|
241 | lua_get_string(L, "model", inp->model, sizeof(inp->model)); | |
|
|
242 | lua_get_string(L, "options", inp->options, sizeof(inp->options)); | |
|
|
243 | if (!inp->layout[0]) strcpy(inp->layout, "us"); | |
|
|
244 | ||
|
|
245 | char scratch[CFG_MAX_STRLEN] = {0}; | |
|
|
246 | ||
|
|
247 | lua_get_string(L, "scroll_method", scratch, sizeof(scratch)); | |
|
|
248 | if (!strcmp(scratch, "2fg")) inp->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; | |
|
|
249 | else if (!strcmp(scratch, "edge")) inp->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE; | |
|
|
250 | else if (!strcmp(scratch, "button")) inp->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; | |
|
|
251 | else inp->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; | |
|
|
252 | ||
|
|
253 | lua_get_string(L, "accel_profile", scratch, sizeof(scratch)); | |
|
|
254 | if (!strcmp(scratch, "flat")) inp->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; | |
|
|
255 | else inp->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; | |
|
|
256 | ||
|
|
257 | lua_get_string(L, "click_method", scratch, sizeof(scratch)); | |
|
|
258 | if (!strcmp(scratch, "clickfinger")) inp->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; | |
|
|
259 | else if (!strcmp(scratch, "button_areas")) inp->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; | |
|
|
260 | else inp->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; | |
|
|
261 | ||
|
|
262 | lua_get_string(L, "send_events_mode", scratch, sizeof(scratch)); | |
|
|
263 | if (!strcmp(scratch, "disabled")) inp->send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; | |
|
|
264 | else if (!strcmp(scratch, "disabled_on_external")) inp->send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; | |
|
|
265 | else inp->send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; | |
|
|
266 | ||
|
|
267 | lua_get_string(L, "tap_button_map", scratch, sizeof(scratch)); | |
|
|
268 | if (!strcmp(scratch, "lmr")) inp->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LMR; | |
|
|
269 | else inp->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; | |
|
|
270 | ||
|
|
271 | lua_pop(L, 1); | |
|
|
272 | } | |
|
|
273 | ||
|
|
274 | static void | |
|
|
275 | parse_rules(lua_State *L, Config *cfg) | |
|
|
276 | { | |
|
|
277 | lua_getglobal(L, "rules"); | |
|
|
278 | if (!lua_istable(L, -1)) { | |
|
|
279 | lua_pop(L, 1); | |
|
|
280 | return; | |
|
|
281 | } | |
|
|
282 | ||
|
|
283 | cfg->nrules = 0; | |
|
|
284 | int n = (int)lua_rawlen(L, -1); | |
|
|
285 | for (int i = 1; i <= n && cfg->nrules < CFG_MAX_RULES; i++) { | |
|
|
286 | lua_rawgeti(L, -1, i); | |
|
|
287 | if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; } | |
|
|
288 | ||
|
|
289 | CfgRule *r = &cfg->rules[cfg->nrules++]; | |
|
|
290 | memset(r, 0, sizeof(*r)); | |
|
|
291 | lua_get_string(L, "app_id", r->app_id, sizeof(r->app_id)); | |
|
|
292 | lua_get_string(L, "title", r->title, sizeof(r->title)); | |
|
|
293 | r->tags = (uint32_t)lua_get_int(L, "tags", 0); | |
|
|
294 | r->floating = lua_get_bool(L, "floating", false); | |
|
|
295 | r->monitor = lua_get_int(L, "monitor", -1); | |
|
|
296 | ||
|
|
297 | lua_pop(L, 1); | |
|
|
298 | } | |
|
|
299 | lua_pop(L, 1); | |
|
|
300 | } | |
|
|
301 | ||
|
|
302 | static void | |
|
|
303 | parse_monitors(lua_State *L, Config *cfg) | |
|
|
304 | { | |
|
|
305 | lua_getglobal(L, "monitors"); | |
|
|
306 | if (!lua_istable(L, -1)) { | |
|
|
307 | lua_pop(L, 1); | |
|
|
308 | cfg->nmonitors = 1; | |
|
|
309 | CfgMonitorRule *m = &cfg->monitors[0]; | |
|
|
310 | memset(m, 0, sizeof(*m)); | |
|
|
311 | m->mfact = 0.55f; | |
|
|
312 | m->nmaster = 1; | |
|
|
313 | m->scale = 1.0f; | |
|
|
314 | strcpy(m->layout, "dwindle"); | |
|
|
315 | m->x = m->y = -1; | |
|
|
316 | return; | |
|
|
317 | } | |
|
|
318 | ||
|
|
319 | cfg->nmonitors = 0; | |
|
|
320 | int n = (int)lua_rawlen(L, -1); | |
|
|
321 | for (int i = 1; i <= n && cfg->nmonitors < CFG_MAX_MONITORS; i++) { | |
|
|
322 | lua_rawgeti(L, -1, i); | |
|
|
323 | if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; } | |
|
|
324 | ||
|
|
325 | CfgMonitorRule *m = &cfg->monitors[cfg->nmonitors++]; | |
|
|
326 | memset(m, 0, sizeof(*m)); | |
|
|
327 | ||
|
|
328 | lua_getfield(L, -1, "name"); | |
|
|
329 | if (lua_isstring(L, -1)) | |
|
|
330 | strncpy(m->name, lua_tostring(L, -1), sizeof(m->name)-1); | |
|
|
331 | lua_pop(L, 1); | |
|
|
332 | ||
|
|
333 | m->mfact = (float)lua_get_double(L, "mfact", 0.55); | |
|
|
334 | m->nmaster = lua_get_int (L, "nmaster", 1); | |
|
|
335 | m->scale = (float)lua_get_double(L, "scale", 1.0); | |
|
|
336 | m->x = lua_get_int (L, "x", -1); | |
|
|
337 | m->y = lua_get_int (L, "y", -1); | |
|
|
338 | m->transform = lua_get_int (L, "transform", 0); | |
|
|
339 | lua_get_string(L, "layout", m->layout, sizeof(m->layout)); | |
|
|
340 | if (!m->layout[0]) strcpy(m->layout, "dwindle"); | |
|
|
341 | ||
|
|
342 | lua_pop(L, 1); | |
|
|
343 | } | |
|
|
344 | lua_pop(L, 1); | |
|
|
345 | } | |
|
|
346 | ||
|
|
347 | static void | |
|
|
348 | parse_keybinds(lua_State *L, Config *cfg) | |
|
|
349 | { | |
|
|
350 | lua_getglobal(L, "keybinds"); | |
|
|
351 | if (!lua_istable(L, -1)) { | |
|
|
352 | lua_pop(L, 1); | |
|
|
353 | return; | |
|
|
354 | } | |
|
|
355 | ||
|
|
356 | cfg->nkeybinds = 0; | |
|
|
357 | struct xkb_context *xkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | |
|
|
358 | ||
|
|
359 | int n = (int)lua_rawlen(L, -1); | |
|
|
360 | for (int i = 1; i <= n && cfg->nkeybinds < CFG_MAX_KEYBINDS; i++) { | |
|
|
361 | lua_rawgeti(L, -1, i); | |
|
|
362 | if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; } | |
|
|
363 | ||
|
|
364 | CfgKeybind *kb = &cfg->keybinds[cfg->nkeybinds]; | |
|
|
365 | memset(kb, 0, sizeof(*kb)); | |
|
|
366 | ||
|
|
367 | /* mods: array of strings */ | |
|
|
368 | kb->mods = 0; | |
|
|
369 | lua_getfield(L, -1, "mods"); | |
|
|
370 | if (lua_istable(L, -1)) { | |
|
|
371 | int nm = (int)lua_rawlen(L, -1); | |
|
|
372 | for (int m = 1; m <= nm; m++) { | |
|
|
373 | lua_rawgeti(L, -1, m); | |
|
|
374 | if (lua_isstring(L, -1)) | |
|
|
375 | kb->mods |= parse_modifier(lua_tostring(L, -1)); | |
|
|
376 | lua_pop(L, 1); | |
|
|
377 | } | |
|
|
378 | } | |
|
|
379 | lua_pop(L, 1); | |
|
|
380 | ||
|
|
381 | /* key: string keysym name, e.g. "q", "Return", "XF86AudioMute" */ | |
|
|
382 | char keyname[CFG_MAX_STRLEN] = {0}; | |
|
|
383 | lua_get_string(L, "key", keyname, sizeof(keyname)); | |
|
|
384 | kb->key = xkb_keysym_from_name(keyname, XKB_KEYSYM_CASE_INSENSITIVE); | |
|
|
385 | if (kb->key == XKB_KEY_NoSymbol) { | |
|
|
386 | fprintf(stderr, "swindle config: unknown key '%s', skipping bind\n", | |
|
|
387 | keyname); | |
|
|
388 | lua_pop(L, 1); /* keybind entry table */ | |
|
|
389 | continue; | |
|
|
390 | } | |
|
|
391 | ||
|
|
392 | lua_get_string(L, "action", kb->action, sizeof(kb->action)); | |
|
|
393 | ||
|
|
394 | /* args: optional array of strings */ | |
|
|
395 | kb->nargs = 0; | |
|
|
396 | lua_getfield(L, -1, "args"); | |
|
|
397 | if (lua_istable(L, -1)) { | |
|
|
398 | int na = (int)lua_rawlen(L, -1); | |
|
|
399 | for (int a = 1; a <= na && kb->nargs < CFG_MAX_ARGS; a++) { | |
|
|
400 | lua_rawgeti(L, -1, a); | |
|
|
401 | if (lua_isstring(L, -1)) | |
|
|
402 | strncpy(kb->args[kb->nargs++], | |
|
|
403 | lua_tostring(L, -1), | |
|
|
404 | CFG_MAX_STRLEN - 1); | |
|
|
405 | lua_pop(L, 1); | |
|
|
406 | } | |
|
|
407 | } | |
|
|
408 | lua_pop(L, 1); /* args */ | |
|
|
409 | ||
|
|
410 | cfg->nkeybinds++; | |
|
|
411 | lua_pop(L, 1); /* keybind entry */ | |
|
|
412 | } | |
|
|
413 | ||
|
|
414 | xkb_context_unref(xkb_ctx); | |
|
|
415 | lua_pop(L, 1); /* keybinds table */ | |
|
|
416 | } | |
|
|
417 | ||
|
|
418 | static void | |
|
|
419 | parse_buttons(lua_State *L, Config *cfg) | |
|
|
420 | { | |
|
|
421 | lua_getglobal(L, "buttons"); | |
|
|
422 | if (!lua_istable(L, -1)) { | |
|
|
423 | lua_pop(L, 1); | |
|
|
424 | return; | |
|
|
425 | } | |
|
|
426 | ||
|
|
427 | cfg->nbuttons = 0; | |
|
|
428 | int n = (int)lua_rawlen(L, -1); | |
|
|
429 | for (int i = 1; i <= n && cfg->nbuttons < CFG_MAX_KEYBINDS; i++) { | |
|
|
430 | lua_rawgeti(L, -1, i); | |
|
|
431 | if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; } | |
|
|
432 | ||
|
|
433 | CfgButton *b = &cfg->buttons[cfg->nbuttons++]; | |
|
|
434 | memset(b, 0, sizeof(*b)); | |
|
|
435 | ||
|
|
436 | b->mods = 0; | |
|
|
437 | lua_getfield(L, -1, "mods"); | |
|
|
438 | if (lua_istable(L, -1)) { | |
|
|
439 | int nm = (int)lua_rawlen(L, -1); | |
|
|
440 | for (int m = 1; m <= nm; m++) { | |
|
|
441 | lua_rawgeti(L, -1, m); | |
|
|
442 | if (lua_isstring(L, -1)) | |
|
|
443 | b->mods |= parse_modifier(lua_tostring(L, -1)); | |
|
|
444 | lua_pop(L, 1); | |
|
|
445 | } | |
|
|
446 | } | |
|
|
447 | lua_pop(L, 1); | |
|
|
448 | ||
|
|
449 | char btnname[CFG_MAX_STRLEN] = {0}; | |
|
|
450 | lua_get_string(L, "button", btnname, sizeof(btnname)); | |
|
|
451 | if (!strcmp(btnname, "left")) b->button = BTN_LEFT; | |
|
|
452 | else if (!strcmp(btnname, "right")) b->button = BTN_RIGHT; | |
|
|
453 | else if (!strcmp(btnname, "middle")) b->button = BTN_MIDDLE; | |
|
|
454 | else b->button = (uint32_t)atoi(btnname); | |
|
|
455 | ||
|
|
456 | lua_get_string(L, "action", b->action, sizeof(b->action)); | |
|
|
457 | ||
|
|
458 | b->nargs = 0; | |
|
|
459 | lua_getfield(L, -1, "args"); | |
|
|
460 | if (lua_istable(L, -1)) { | |
|
|
461 | int na = (int)lua_rawlen(L, -1); | |
|
|
462 | for (int a = 1; a <= na && b->nargs < CFG_MAX_ARGS; a++) { | |
|
|
463 | lua_rawgeti(L, -1, a); | |
|
|
464 | if (lua_isstring(L, -1)) | |
|
|
465 | strncpy(b->args[b->nargs++], | |
|
|
466 | lua_tostring(L, -1), | |
|
|
467 | CFG_MAX_STRLEN - 1); | |
|
|
468 | lua_pop(L, 1); | |
|
|
469 | } | |
|
|
470 | } | |
|
|
471 | lua_pop(L, 1); /* args */ | |
|
|
472 | ||
|
|
473 | lua_pop(L, 1); | |
|
|
474 | } | |
|
|
475 | lua_pop(L, 1); | |
|
|
476 | } | |
|
|
477 | ||
|
|
478 | static void | |
|
|
479 | parse_autostart(lua_State *L, Config *cfg) | |
|
|
480 | { | |
|
|
481 | lua_getglobal(L, "autostart"); | |
|
|
482 | if (!lua_istable(L, -1)) { | |
|
|
483 | lua_pop(L, 1); | |
|
|
484 | return; | |
|
|
485 | } | |
|
|
486 | ||
|
|
487 | cfg->nautostart = 0; | |
|
|
488 | int n = (int)lua_rawlen(L, -1); | |
|
|
489 | for (int i = 1; i <= n && cfg->nautostart < CFG_MAX_AUTOSTART; i++) { | |
|
|
490 | lua_rawgeti(L, -1, i); | |
|
|
491 | if (!lua_isstring(L, -1)) { | |
|
|
492 | lua_pop(L, 1); | |
|
|
493 | continue; | |
|
|
494 | } | |
|
|
495 | strncpy(cfg->autostart[cfg->nautostart].cmd, | |
|
|
496 | lua_tostring(L, -1), | |
|
|
497 | CFG_MAX_AUTOSTART_CMD - 1); | |
|
|
498 | cfg->nautostart++; | |
|
|
499 | lua_pop(L, 1); | |
|
|
500 | } | |
|
|
501 | lua_pop(L, 1); | |
|
|
502 | } | |
|
|
503 | ||
|
|
504 | /* Public API */ | |
|
|
505 | ||
|
|
506 | char * | |
|
|
507 | config_get_path(char *buf, size_t bufsz) | |
|
|
508 | { | |
|
|
509 | const char *xdg = getenv("XDG_CONFIG_HOME"); | |
|
|
510 | if (xdg && *xdg) | |
|
|
511 | snprintf(buf, bufsz, "%s/swindle/config.lua", xdg); | |
|
|
512 | else { | |
|
|
513 | const char *home = getenv("HOME"); | |
|
|
514 | if (!home) home = "/root"; /* you're probably root, aren't you */ | |
|
|
515 | snprintf(buf, bufsz, "%s/.config/swindle/config.lua", home); | |
|
|
516 | } | |
|
|
517 | return buf; | |
|
|
518 | } | |
|
|
519 | ||
|
|
520 | int | |
|
|
521 | config_load(const char *path, Config *cfg) | |
|
|
522 | { | |
|
|
523 | memset(cfg, 0, sizeof(*cfg)); | |
|
|
524 | ||
|
|
525 | lua_State *L = luaL_newstate(); | |
|
|
526 | if (!L) { | |
|
|
527 | fprintf(stderr, "swindle config: failed to create Lua state. " | |
|
|
528 | "Truly rock bottom.\n"); | |
|
|
529 | return -1; | |
|
|
530 | } | |
|
|
531 | luaL_openlibs(L); | |
|
|
532 | ||
|
|
533 | if (luaL_dofile(L, path) != LUA_OK) { | |
|
|
534 | lua_log_error(L, "load"); | |
|
|
535 | lua_close(L); | |
|
|
536 | return -1; | |
|
|
537 | } | |
|
|
538 | ||
|
|
539 | /* Top-level booleans */ | |
|
|
540 | lua_getglobal(L, "sloppy_focus"); | |
|
|
541 | cfg->sloppyfocus = lua_isboolean(L, -1) ? lua_toboolean(L, -1) : true; | |
|
|
542 | lua_pop(L, 1); | |
|
|
543 | ||
|
|
544 | lua_getglobal(L, "bypass_surface_visibility"); | |
|
|
545 | cfg->bypass_surface_visibility = lua_isboolean(L, -1) | |
|
|
546 | ? lua_toboolean(L, -1) : false; | |
|
|
547 | lua_pop(L, 1); | |
|
|
548 | ||
|
|
549 | lua_getglobal(L, "log_level"); | |
|
|
550 | if (lua_isstring(L, -1)) { | |
|
|
551 | const char *ll = lua_tostring(L, -1); | |
|
|
552 | if (!strcmp(ll, "silent")) cfg->log_level = WLR_SILENT; | |
|
|
553 | else if (!strcmp(ll, "info")) cfg->log_level = WLR_INFO; | |
|
|
554 | else if (!strcmp(ll, "debug")) cfg->log_level = WLR_DEBUG; | |
|
|
555 | else cfg->log_level = WLR_ERROR; | |
|
|
556 | } else { | |
|
|
557 | cfg->log_level = WLR_ERROR; | |
|
|
558 | } | |
|
|
559 | lua_pop(L, 1); | |
|
|
560 | ||
|
|
561 | parse_appearance(L, &cfg->appearance); | |
|
|
562 | parse_input (L, &cfg->input); | |
|
|
563 | parse_rules (L, cfg); | |
|
|
564 | parse_monitors (L, cfg); | |
|
|
565 | parse_keybinds (L, cfg); | |
|
|
566 | parse_buttons (L, cfg); | |
|
|
567 | parse_autostart (L, cfg); | |
|
|
568 | ||
|
|
569 | lua_close(L); | |
|
|
570 | return 0; | |
|
|
571 | } | |
|
|
572 | ||
|
|
573 | /* Apply functions */ | |
|
|
574 | ||
|
|
575 | void | |
|
|
576 | config_apply_appearance(const Config *cfg) | |
|
|
577 | { | |
|
|
578 | (void)cfg; | |
|
|
579 | } | |
|
|
580 | ||
|
|
581 | void | |
|
|
582 | config_apply_input(const Config *cfg) | |
|
|
583 | { | |
|
|
584 | (void)cfg; | |
|
|
585 | } | |
|
|
586 | ||
|
|
587 | void | |
|
|
588 | config_apply_keybinds(const Config *cfg) | |
|
|
589 | { | |
|
|
590 | (void)cfg; | |
|
|
591 | } | |
|
|
592 | ||
|
|
593 | void | |
|
|
594 | config_autostart_run(const Config *cfg) | |
|
|
595 | { | |
|
|
596 | if (cfg->nautostart == 0) | |
|
|
597 | return; | |
|
|
598 | ||
|
|
599 | pid_t pid = fork(); | |
|
|
600 | if (pid < 0) { | |
|
|
601 | perror("swindle autostart: fork"); | |
|
|
602 | return; | |
|
|
603 | } | |
|
|
604 | if (pid != 0) | |
|
|
605 | return; /* compositor continues (sequencer runs in child) */ | |
|
|
606 | ||
|
|
607 | /* The sequencer child resets any inherited signal handlers and becomes | |
|
|
608 | * a new session so the compositor's SIGCHLD handling doesn't | |
|
|
609 | * interfere with our waitpid calls. */ | |
|
|
610 | signal(SIGCHLD, SIG_DFL); | |
|
|
611 | setsid(); | |
|
|
612 | ||
|
|
613 | for (int i = 0; i < cfg->nautostart; i++) { | |
|
|
614 | const char *cmd = cfg->autostart[i].cmd; | |
|
|
615 | ||
|
|
616 | pid_t cpid = fork(); | |
|
|
617 | if (cpid < 0) { | |
|
|
618 | fprintf(stderr, "swindle autostart: fork for '%s': %s\n", | |
|
|
619 | cmd, strerror(errno)); | |
|
|
620 | continue; | |
|
|
621 | } | |
|
|
622 | if (cpid == 0) { | |
|
|
623 | execl("/bin/sh", "sh", "-c", cmd, NULL); | |
|
|
624 | fprintf(stderr, "swindle autostart: exec '%s': %s\n", | |
|
|
625 | cmd, strerror(errno)); | |
|
|
626 | _exit(1); | |
|
|
627 | } | |
|
|
628 | ||
|
|
629 | /* wait a second because one shotters will fly past, but | |
|
|
630 | * daemon processes (some, like swaybg) won't because of | |
|
|
631 | * daemon black magic. To say the least, it's good for the soul */ | |
|
|
632 | struct timespec deadline, now; | |
|
|
633 | clock_gettime(CLOCK_MONOTONIC, &deadline); | |
|
|
634 | deadline.tv_sec += 0.5; | |
|
|
635 | ||
|
|
636 | int status; | |
|
|
637 | int done = 0; | |
|
|
638 | while (!done) { | |
|
|
639 | pid_t r = waitpid(cpid, &status, WNOHANG); | |
|
|
640 | if (r == cpid) { | |
|
|
641 | done = 1; | |
|
|
642 | if (WIFEXITED(status) && WEXITSTATUS(status) != 0) | |
|
|
643 | fprintf(stderr, "swindle autostart: '%s' exited with status %d\n", | |
|
|
644 | cmd, WEXITSTATUS(status)); | |
|
|
645 | } else { | |
|
|
646 | clock_gettime(CLOCK_MONOTONIC, &now); | |
|
|
647 | if (now.tv_sec > deadline.tv_sec || | |
|
|
648 | (now.tv_sec == deadline.tv_sec && | |
|
|
649 | now.tv_nsec >= deadline.tv_nsec)) | |
|
|
650 | break; /* looks like a daemon, move on */ | |
|
|
651 | struct timespec sl = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000 }; | |
|
|
652 | nanosleep(&sl, NULL); | |
|
|
653 | } | |
|
|
654 | } | |
|
|
655 | } | |
|
|
656 | ||
|
|
657 | _exit(0); | |
|
|
658 | } | |
|
|
659 | ||
|
|
660 | /* inotify watcher */ | |
|
|
661 | ||
|
|
662 | static int | |
|
|
663 | watch_dispatch(int fd, uint32_t mask, void *data) | |
|
|
664 | { | |
|
|
665 | WatchState *ws = data; | |
|
|
666 | ||
|
|
667 | /* Drain the inotify events */ | |
|
|
668 | _Alignas(struct inotify_event) char buf[4096]; | |
|
|
669 | ssize_t len = read(fd, buf, sizeof(buf)); | |
|
|
670 | if (len < 0) { | |
|
|
671 | if (errno != EAGAIN) | |
|
|
672 | perror("swindle config: inotify read"); | |
|
|
673 | return 0; | |
|
|
674 | } | |
|
|
675 | ||
|
|
676 | /* Re-parse */ | |
|
|
677 | Config *fresh = calloc(1, sizeof(Config)); | |
|
|
678 | if (!fresh) return 0; | |
|
|
679 | ||
|
|
680 | if (config_load(ws->path, fresh) == 0) { | |
|
|
681 | fprintf(stderr, "swindle config: reloaded '%s'\n", ws->path); | |
|
|
682 | if (ws->cb) | |
|
|
683 | ws->cb(fresh, ws->userdata); | |
|
|
684 | } else { | |
|
|
685 | fprintf(stderr, "swindle config: reload failed, keeping old config. " | |
|
|
686 | "Story of my life.\n"); | |
|
|
687 | } | |
|
|
688 | ||
|
|
689 | free(fresh); | |
|
|
690 | ||
|
|
691 | /* | |
|
|
692 | * Some editors (vim, nano) delete-and-recreate files on save, | |
|
|
693 | * which removes our watch (which is a pain in the ass. | |
|
|
694 | * Hence, re-add it defensively. It's good for the soul) | |
|
|
695 | */ | |
|
|
696 | inotify_rm_watch(ws->inotify_fd, ws->watch_fd); | |
|
|
697 | ws->watch_fd = inotify_add_watch(ws->inotify_fd, ws->path, | |
|
|
698 | IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE); | |
|
|
699 | ||
|
|
700 | return 0; | |
|
|
701 | } | |
|
|
702 | ||
|
|
703 | struct wl_event_source * | |
|
|
704 | config_watch_start(struct wl_event_loop *loop, const char *path, | |
|
|
705 | config_reload_cb cb, void *userdata) | |
|
|
706 | { | |
|
|
707 | WatchState *ws = calloc(1, sizeof(*ws)); | |
|
|
708 | if (!ws) return NULL; | |
|
|
709 | ||
|
|
710 | ws->inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); | |
|
|
711 | if (ws->inotify_fd < 0) { | |
|
|
712 | perror("swindle config: inotify_init1"); | |
|
|
713 | free(ws); | |
|
|
714 | return NULL; | |
|
|
715 | } | |
|
|
716 | ||
|
|
717 | ws->watch_fd = inotify_add_watch(ws->inotify_fd, path, | |
|
|
718 | IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE); | |
|
|
719 | if (ws->watch_fd < 0) { | |
|
|
720 | perror("swindle config: inotify_add_watch"); | |
|
|
721 | close(ws->inotify_fd); | |
|
|
722 | free(ws); | |
|
|
723 | return NULL; | |
|
|
724 | } | |
|
|
725 | ||
|
|
726 | strncpy(ws->path, path, sizeof(ws->path) - 1); | |
|
|
727 | ws->cb = cb; | |
|
|
728 | ws->userdata = userdata; | |
|
|
729 | ||
|
|
730 | struct wl_event_source *src = wl_event_loop_add_fd( | |
|
|
731 | loop, ws->inotify_fd, | |
|
|
732 | WL_EVENT_READABLE, | |
|
|
733 | watch_dispatch, ws | |
|
|
734 | ); | |
|
|
735 | ||
|
|
736 | if (!src) { | |
|
|
737 | fprintf(stderr, "swindle config: failed to add inotify to event loop. " | |
|
|
738 | "Classic.\n"); | |
|
|
739 | close(ws->inotify_fd); | |
|
|
740 | free(ws); | |
|
|
741 | return NULL; | |
|
|
742 | } | |
|
|
743 | ||
|
|
744 | ws->event_src = src; | |
|
|
745 | fprintf(stderr, "swindle config: watching '%s'\n", path); | |
|
|
746 | return (struct wl_event_source *)ws; | |
|
|
747 | } | |
|
|
748 | ||
|
|
749 | void | |
|
|
750 | config_watch_stop(struct wl_event_source *src) | |
|
|
751 | { | |
|
|
752 | if (!src) return; | |
|
|
753 | WatchState *ws = (WatchState *)src; | |
|
|
754 | wl_event_source_remove(ws->event_src); | |
|
|
755 | close(ws->inotify_fd); | |
|
|
756 | free(ws); | |
|
|
757 | } | |
| @@ -0,0 +1,160 | |||
|
|
1 | #ifndef SWINDLE_PARSER_H | |
|
|
2 | #define SWINDLE_PARSER_H | |
|
|
3 | ||
|
|
4 | #include <stdint.h> | |
|
|
5 | #include <stdbool.h> | |
|
|
6 | #include <wayland-server-core.h> | |
|
|
7 | ||
|
|
8 | /* Maximum lengths. Good for the soul, they say */ | |
|
|
9 | #define CFG_MAX_RULES 64 | |
|
|
10 | #define CFG_MAX_MONITORS 16 | |
|
|
11 | #define CFG_MAX_KEYBINDS 256 | |
|
|
12 | #define CFG_MAX_ARGS 16 | |
|
|
13 | #define CFG_MAX_STRLEN 256 | |
|
|
14 | #define CFG_MAX_AUTOSTART 32 | |
|
|
15 | #define CFG_MAX_AUTOSTART_CMD 512 | |
|
|
16 | ||
|
|
17 | /* Appearance */ | |
|
|
18 | ||
|
|
19 | typedef struct { | |
|
|
20 | unsigned int inner_border_px; | |
|
|
21 | unsigned int outer_border_px; | |
|
|
22 | unsigned int gaps; | |
|
|
23 | bool smart_gaps; | |
|
|
24 | float inner_border_color[4]; | |
|
|
25 | float outer_border_color[4]; | |
|
|
26 | float inner_focus_color[4]; | |
|
|
27 | float outer_focus_color[4]; | |
|
|
28 | float inner_urgent_color[4]; | |
|
|
29 | float outer_urgent_color[4]; | |
|
|
30 | float root_color[4]; | |
|
|
31 | float fullscreen_bg[4]; | |
|
|
32 | float active_opacity; | |
|
|
33 | float inactive_opacity; | |
|
|
34 | } CfgAppearance; | |
|
|
35 | ||
|
|
36 | /* Input */ | |
|
|
37 | ||
|
|
38 | typedef struct { | |
|
|
39 | int repeat_rate; | |
|
|
40 | int repeat_delay; | |
|
|
41 | bool tap_to_click; | |
|
|
42 | bool tap_and_drag; | |
|
|
43 | bool drag_lock; | |
|
|
44 | bool natural_scrolling; | |
|
|
45 | bool disable_while_typing; | |
|
|
46 | bool left_handed; | |
|
|
47 | bool middle_button_emulation; | |
|
|
48 | int scroll_method; /* libinput enum value */ | |
|
|
49 | int click_method; /* libinput enum value */ | |
|
|
50 | int send_events_mode; | |
|
|
51 | int accel_profile; /* libinput enum value */ | |
|
|
52 | double accel_speed; | |
|
|
53 | int tap_button_map; /* libinput enum value */ | |
|
|
54 | char layout[CFG_MAX_STRLEN]; /* "us", "de", "de,us", ... */ | |
|
|
55 | char variant[CFG_MAX_STRLEN]; /* "nodeadkeys", "colemak", ... */ | |
|
|
56 | char model[CFG_MAX_STRLEN]; /* "pc105", ... */ | |
|
|
57 | char options[CFG_MAX_STRLEN]; /* "grp:alt_shift_toggle", ... */ | |
|
|
58 | } CfgInput; | |
|
|
59 | ||
|
|
60 | /* Window Rules */ | |
|
|
61 | ||
|
|
62 | typedef struct { | |
|
|
63 | char app_id[CFG_MAX_STRLEN]; | |
|
|
64 | char title[CFG_MAX_STRLEN]; /* empty string = wildcard */ | |
|
|
65 | uint32_t tags; | |
|
|
66 | bool floating; | |
|
|
67 | int monitor; /* -1 = current */ | |
|
|
68 | } CfgRule; | |
|
|
69 | ||
|
|
70 | /* Monitor Rules */ | |
|
|
71 | ||
|
|
72 | typedef struct { | |
|
|
73 | char name[CFG_MAX_STRLEN]; /* empty = catch-all */ | |
|
|
74 | float mfact; | |
|
|
75 | int nmaster; | |
|
|
76 | float scale; | |
|
|
77 | char layout[CFG_MAX_STRLEN]; /* "dwindle", "floating", etc. */ | |
|
|
78 | int transform; /* WL_OUTPUT_TRANSFORM_* */ | |
|
|
79 | int x, y; /* -1,-1 = autoconfigure */ | |
|
|
80 | } CfgMonitorRule; | |
|
|
81 | ||
|
|
82 | /* keybinds */ | |
|
|
83 | ||
|
|
84 | typedef struct { | |
|
|
85 | uint32_t mods; /* WLR_MODIFIER_* bitmask */ | |
|
|
86 | uint32_t key; /* XKB keysym */ | |
|
|
87 | char action[CFG_MAX_STRLEN]; /* "spawn", "killclient", etc. */ | |
|
|
88 | char args[CFG_MAX_ARGS][CFG_MAX_STRLEN]; | |
|
|
89 | int nargs; | |
|
|
90 | } CfgKeybind; | |
|
|
91 | ||
|
|
92 | /* mouse buttons */ | |
|
|
93 | ||
|
|
94 | typedef struct { | |
|
|
95 | uint32_t mods; | |
|
|
96 | uint32_t button; | |
|
|
97 | char action[CFG_MAX_STRLEN]; | |
|
|
98 | char args[CFG_MAX_ARGS][CFG_MAX_STRLEN]; | |
|
|
99 | int nargs; | |
|
|
100 | } CfgButton; | |
|
|
101 | ||
|
|
102 | /* Autostart */ | |
|
|
103 | ||
|
|
104 | typedef struct { | |
|
|
105 | char cmd[CFG_MAX_AUTOSTART_CMD]; | |
|
|
106 | } CfgAutostart; | |
|
|
107 | ||
|
|
108 | /* the whole shebang */ | |
|
|
109 | ||
|
|
110 | typedef struct { | |
|
|
111 | CfgAppearance appearance; | |
|
|
112 | ||
|
|
113 | CfgInput input; | |
|
|
114 | ||
|
|
115 | CfgRule rules[CFG_MAX_RULES]; | |
|
|
116 | int nrules; | |
|
|
117 | ||
|
|
118 | CfgMonitorRule monitors[CFG_MAX_MONITORS]; | |
|
|
119 | int nmonitors; | |
|
|
120 | ||
|
|
121 | CfgKeybind keybinds[CFG_MAX_KEYBINDS]; | |
|
|
122 | int nkeybinds; | |
|
|
123 | ||
|
|
124 | CfgButton buttons[CFG_MAX_KEYBINDS]; | |
|
|
125 | int nbuttons; | |
|
|
126 | ||
|
|
127 | bool sloppyfocus; | |
|
|
128 | bool bypass_surface_visibility; | |
|
|
129 | int log_level; /* WLR_* log level */ | |
|
|
130 | ||
|
|
131 | CfgAutostart autostart[CFG_MAX_AUTOSTART]; | |
|
|
132 | int nautostart; | |
|
|
133 | } Config; | |
|
|
134 | ||
|
|
135 | /* Public API */ | |
|
|
136 | ||
|
|
137 | int config_load(const char *path, Config *cfg); | |
|
|
138 | ||
|
|
139 | char *config_get_path(char *buf, size_t bufsz); | |
|
|
140 | ||
|
|
141 | void config_apply_appearance(const Config *cfg); | |
|
|
142 | ||
|
|
143 | void config_apply_input(const Config *cfg); | |
|
|
144 | ||
|
|
145 | void config_apply_keybinds(const Config *cfg); | |
|
|
146 | ||
|
|
147 | void config_autostart_run(const Config *cfg); | |
|
|
148 | ||
|
|
149 | typedef void (*config_reload_cb)(const Config *cfg, void *userdata); | |
|
|
150 | ||
|
|
151 | struct wl_event_source *config_watch_start( | |
|
|
152 | struct wl_event_loop *loop, | |
|
|
153 | const char *path, | |
|
|
154 | config_reload_cb cb, | |
|
|
155 | void *userdata | |
|
|
156 | ); | |
|
|
157 | ||
|
|
158 | void config_watch_stop(struct wl_event_source *src); | |
|
|
159 | ||
|
|
160 | #endif | |
| @@ -0,0 +1,184 | |||
|
|
1 | <?xml version="1.0" encoding="UTF-8"?> | |
|
|
2 | <protocol name="dwl_ipc_unstable_v2"> | |
|
|
3 | <copyright> | |
|
|
4 | Copyright (C) 2022 Russell Newcomb | |
|
|
5 | ||
|
|
6 | Permission is hereby granted, free of charge, to any person obtaining a | |
|
|
7 | copy of this software and associated documentation files (the "Software"), | |
|
|
8 | to deal in the Software without restriction, including without limitation | |
|
|
9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
|
|
10 | and/or sell copies of the Software, and to permit persons to whom the | |
|
|
11 | Software is furnished to do so, subject to the following conditions: | |
|
|
12 | ||
|
|
13 | The above copyright notice and this permission notice (including the next | |
|
|
14 | paragraph) shall be included in all copies or substantial portions of the | |
|
|
15 | Software. | |
|
|
16 | ||
|
|
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
|
|
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
|
|
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
|
|
20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
|
|
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
|
|
22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
|
|
23 | DEALINGS IN THE SOFTWARE. | |
|
|
24 | </copyright> | |
|
|
25 | ||
|
|
26 | <interface name="zdwl_ipc_manager_v2" version="2"> | |
|
|
27 | <description summary="manage dwl state"> | |
|
|
28 | This interface is exposed as a global in the Wayland registry and allows | |
|
|
29 | clients to query and set dwl state. | |
|
|
30 | ||
|
|
31 | Warning! The protocol described in this file is experimental and | |
|
|
32 | backward incompatible changes may be made. Backward compatible changes | |
|
|
33 | may be added together with the corresponding interface version bump. | |
|
|
34 | Backward incompatible changes are done by bumping the version number in | |
|
|
35 | the protocol and interface names and resetting the interface version. | |
|
|
36 | Once the protocol is to be declared stable, the 'z' prefix and the | |
|
|
37 | version number in the protocol and interface names are removed and the | |
|
|
38 | interface version is reset. | |
|
|
39 | </description> | |
|
|
40 | ||
|
|
41 | <request name="release" type="destructor"> | |
|
|
42 | <description summary="release dwl_ipc_manager"> | |
|
|
43 | Indicates that the client will not use the manager object anymore. | |
|
|
44 | Objects created through this interface remain valid. | |
|
|
45 | </description> | |
|
|
46 | </request> | |
|
|
47 | ||
|
|
48 | <request name="get_output"> | |
|
|
49 | <description summary="get a dwl_ipc_output for a wl_output"> | |
|
|
50 | Get a dwl_ipc_output for the given wl_output. | |
|
|
51 | </description> | |
|
|
52 | <arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/> | |
|
|
53 | <arg name="output" type="object" interface="wl_output"/> | |
|
|
54 | </request> | |
|
|
55 | ||
|
|
56 | <event name="tags"> | |
|
|
57 | <description summary="announces number of tags"> | |
|
|
58 | This event is sent after binding and announces the number of tags. | |
|
|
59 | </description> | |
|
|
60 | <arg name="amount" type="uint"/> | |
|
|
61 | </event> | |
|
|
62 | ||
|
|
63 | <event name="layout"> | |
|
|
64 | <description summary="announces a layout"> | |
|
|
65 | This event is sent after binding and announces a layout. | |
|
|
66 | Layouts are announced in order. | |
|
|
67 | </description> | |
|
|
68 | <arg name="name" type="string"/> | |
|
|
69 | </event> | |
|
|
70 | </interface> | |
|
|
71 | ||
|
|
72 | <interface name="zdwl_ipc_output_v2" version="2"> | |
|
|
73 | <description summary="interact with dwl output state"> | |
|
|
74 | Observe and control a dwl output. | |
|
|
75 | </description> | |
|
|
76 | ||
|
|
77 | <enum name="tag_state"> | |
|
|
78 | <entry name="none" value="0" summary="no state"/> | |
|
|
79 | <entry name="active" value="1" summary="tag is active"/> | |
|
|
80 | <entry name="urgent" value="2" summary="tag has urgent client"/> | |
|
|
81 | </enum> | |
|
|
82 | ||
|
|
83 | <request name="release" type="destructor"> | |
|
|
84 | <description summary="release dwl_ipc_output"> | |
|
|
85 | Indicates that the client will not use the dwl_ipc_output object | |
|
|
86 | anymore. Objects created through this interface remain valid. | |
|
|
87 | </description> | |
|
|
88 | </request> | |
|
|
89 | ||
|
|
90 | <request name="set_tags"> | |
|
|
91 | <description summary="set the active tags of this output"> | |
|
|
92 | set the active tags of this output. | |
|
|
93 | </description> | |
|
|
94 | <arg name="tagmask" type="uint" summary="bitmask of the tags that should be set"/> | |
|
|
95 | <arg name="toggle_tagset" type="uint" summary="whether to toggle the tagset"/> | |
|
|
96 | </request> | |
|
|
97 | ||
|
|
98 | <request name="set_client_tags"> | |
|
|
99 | <description summary="set the tags of the focused client"> | |
|
|
100 | Set the tags of the focused client. | |
|
|
101 | </description> | |
|
|
102 | <arg name="and_tags" type="uint"/> | |
|
|
103 | <arg name="xor_tags" type="uint"/> | |
|
|
104 | </request> | |
|
|
105 | ||
|
|
106 | <request name="set_layout"> | |
|
|
107 | <description summary="set the layout of this output"> | |
|
|
108 | Set the layout of this output. | |
|
|
109 | </description> | |
|
|
110 | <arg name="index" type="uint"/> | |
|
|
111 | </request> | |
|
|
112 | ||
|
|
113 | <event name="toggle_visibility"> | |
|
|
114 | <description summary="dwl visibility has been toggled"> | |
|
|
115 | Indicates that dwl visibility has been toggled. | |
|
|
116 | </description> | |
|
|
117 | </event> | |
|
|
118 | ||
|
|
119 | <event name="active"> | |
|
|
120 | <description summary="output is active"> | |
|
|
121 | Indicates the output is active (selected monitor). | |
|
|
122 | </description> | |
|
|
123 | <arg name="active" type="uint"/> | |
|
|
124 | </event> | |
|
|
125 | ||
|
|
126 | <event name="tag"> | |
|
|
127 | <description summary="tag state changed"> | |
|
|
128 | Indicates a tag state change. | |
|
|
129 | </description> | |
|
|
130 | <arg name="tag" type="uint" summary="index of the tag"/> | |
|
|
131 | <arg name="state" type="uint" enum="tag_state" summary="state of the tag"/> | |
|
|
132 | <arg name="clients" type="uint" summary="number of clients in tag"/> | |
|
|
133 | <arg name="focused" type="uint" summary="1 if focused client is in this tag"/> | |
|
|
134 | </event> | |
|
|
135 | ||
|
|
136 | <event name="layout"> | |
|
|
137 | <description summary="layout changed"> | |
|
|
138 | Indicates the layout changed. | |
|
|
139 | </description> | |
|
|
140 | <arg name="layout" type="uint" summary="index of the layout"/> | |
|
|
141 | </event> | |
|
|
142 | ||
|
|
143 | <event name="title"> | |
|
|
144 | <description summary="title changed"> | |
|
|
145 | Indicates the focused client title changed. | |
|
|
146 | </description> | |
|
|
147 | <arg name="title" type="string"/> | |
|
|
148 | </event> | |
|
|
149 | ||
|
|
150 | <event name="appid"> | |
|
|
151 | <description summary="appid changed"> | |
|
|
152 | Indicates the focused client appid changed. | |
|
|
153 | </description> | |
|
|
154 | <arg name="appid" type="string"/> | |
|
|
155 | </event> | |
|
|
156 | ||
|
|
157 | <event name="layout_symbol"> | |
|
|
158 | <description summary="layout symbol changed"> | |
|
|
159 | Indicates the layout symbol changed. | |
|
|
160 | </description> | |
|
|
161 | <arg name="layout" type="string"/> | |
|
|
162 | </event> | |
|
|
163 | ||
|
|
164 | <event name="frame"> | |
|
|
165 | <description summary="frame event"> | |
|
|
166 | Sent after all state events have been sent for a given state change. | |
|
|
167 | </description> | |
|
|
168 | </event> | |
|
|
169 | ||
|
|
170 | <event name="fullscreen" since="2"> | |
|
|
171 | <description summary="fullscreen state changed"> | |
|
|
172 | Indicates the fullscreen state changed. | |
|
|
173 | </description> | |
|
|
174 | <arg name="is_fullscreen" type="uint"/> | |
|
|
175 | </event> | |
|
|
176 | ||
|
|
177 | <event name="floating" since="2"> | |
|
|
178 | <description summary="floating state changed"> | |
|
|
179 | Indicates the floating state changed. | |
|
|
180 | </description> | |
|
|
181 | <arg name="is_floating" type="uint"/> | |
|
|
182 | </event> | |
|
|
183 | </interface> | |
|
|
184 | </protocol> | |
| @@ -0,0 +1,422 | |||
|
|
1 | <?xml version="1.0" encoding="UTF-8"?> | |
|
|
2 | <protocol name="ext_workspace_v1"> | |
|
|
3 | <copyright> | |
|
|
4 | Copyright Β© 2019 Christopher Billington | |
|
|
5 | Copyright Β© 2020 Ilia Bozhinov | |
|
|
6 | Copyright Β© 2022 Victoria Brekenfeld | |
|
|
7 | ||
|
|
8 | Permission to use, copy, modify, distribute, and sell this | |
|
|
9 | software and its documentation for any purpose is hereby granted | |
|
|
10 | without fee, provided that the above copyright notice appear in | |
|
|
11 | all copies and that both that copyright notice and this permission | |
|
|
12 | notice appear in supporting documentation, and that the name of | |
|
|
13 | the copyright holders not be used in advertising or publicity | |
|
|
14 | pertaining to distribution of the software without specific, | |
|
|
15 | written prior permission. The copyright holders make no | |
|
|
16 | representations about the suitability of this software for any | |
|
|
17 | purpose. It is provided "as is" without express or implied | |
|
|
18 | warranty. | |
|
|
19 | ||
|
|
20 | THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | |
|
|
21 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
|
|
22 | FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
|
|
23 | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
|
|
24 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |
|
|
25 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
|
|
26 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | |
|
|
27 | THIS SOFTWARE. | |
|
|
28 | </copyright> | |
|
|
29 | ||
|
|
30 | <interface name="ext_workspace_manager_v1" version="1"> | |
|
|
31 | <description summary="list and control workspaces"> | |
|
|
32 | Workspaces, also called virtual desktops, are groups of surfaces. A | |
|
|
33 | compositor with a concept of workspaces may only show some such groups of | |
|
|
34 | surfaces (those of 'active' workspaces) at a time.Β 'Activating' a | |
|
|
35 | workspace is a request for the compositor to display that workspace's | |
|
|
36 | surfaces as normal, whereas the compositor may hide or otherwise | |
|
|
37 | de-emphasise surfaces that are associated only with 'inactive' workspaces. | |
|
|
38 | Workspaces are grouped by which sets of outputs they correspond to, and | |
|
|
39 | may contain surfaces only from those outputs. In this way, it is possible | |
|
|
40 | for each output to have its own set of workspaces, or for all outputs (or | |
|
|
41 | any other arbitrary grouping) to share workspaces. Compositors may | |
|
|
42 | optionally conceptually arrange each group of workspaces in an | |
|
|
43 | N-dimensional grid. | |
|
|
44 | ||
|
|
45 | The purpose of this protocol is to enable the creation of taskbars and | |
|
|
46 | docks by providing them with a list of workspaces and their properties, | |
|
|
47 | and allowing them to activate and deactivate workspaces. | |
|
|
48 | ||
|
|
49 | After a client binds the ext_workspace_manager_v1, each workspace will be | |
|
|
50 | sent via the workspace event. | |
|
|
51 | </description> | |
|
|
52 | ||
|
|
53 | <event name="workspace_group"> | |
|
|
54 | <description summary="a workspace group has been created"> | |
|
|
55 | This event is emitted whenever a new workspace group has been created. | |
|
|
56 | ||
|
|
57 | All initial details of the workspace group (outputs) will be | |
|
|
58 | sent immediately after this event via the corresponding events in | |
|
|
59 | ext_workspace_group_handle_v1 and ext_workspace_handle_v1. | |
|
|
60 | </description> | |
|
|
61 | <arg name="workspace_group" type="new_id" interface="ext_workspace_group_handle_v1"/> | |
|
|
62 | </event> | |
|
|
63 | ||
|
|
64 | <event name="workspace"> | |
|
|
65 | <description summary="workspace has been created"> | |
|
|
66 | This event is emitted whenever a new workspace has been created. | |
|
|
67 | ||
|
|
68 | All initial details of the workspace (name, coordinates, state) will | |
|
|
69 | be sent immediately after this event via the corresponding events in | |
|
|
70 | ext_workspace_handle_v1. | |
|
|
71 | ||
|
|
72 | Workspaces start off unassigned to any workspace group. | |
|
|
73 | </description> | |
|
|
74 | <arg name="workspace" type="new_id" interface="ext_workspace_handle_v1"/> | |
|
|
75 | </event> | |
|
|
76 | ||
|
|
77 | <request name="commit"> | |
|
|
78 | <description summary="all requests about the workspaces have been sent"> | |
|
|
79 | The client must send this request after it has finished sending other | |
|
|
80 | requests. The compositor must process a series of requests preceding a | |
|
|
81 | commit request atomically. | |
|
|
82 | ||
|
|
83 | This allows changes to the workspace properties to be seen as atomic, | |
|
|
84 | even if they happen via multiple events, and even if they involve | |
|
|
85 | multiple ext_workspace_handle_v1 objects, for example, deactivating one | |
|
|
86 | workspace and activating another. | |
|
|
87 | </description> | |
|
|
88 | </request> | |
|
|
89 | ||
|
|
90 | <event name="done"> | |
|
|
91 | <description summary="all information about the workspaces and workspace groups has been sent"> | |
|
|
92 | This event is sent after all changes in all workspaces and workspace groups have been | |
|
|
93 | sent. | |
|
|
94 | ||
|
|
95 | This allows changes to one or more ext_workspace_group_handle_v1 | |
|
|
96 | properties and ext_workspace_handle_v1 properties | |
|
|
97 | to be seen as atomic, even if they happen via multiple events. | |
|
|
98 | In particular, an output moving from one workspace group to | |
|
|
99 | another sends an output_enter event and an output_leave event to the two | |
|
|
100 | ext_workspace_group_handle_v1 objects in question. The compositor sends | |
|
|
101 | the done event only after updating the output information in both | |
|
|
102 | workspace groups. | |
|
|
103 | </description> | |
|
|
104 | </event> | |
|
|
105 | ||
|
|
106 | <event name="finished" type="destructor"> | |
|
|
107 | <description summary="the compositor has finished with the workspace_manager"> | |
|
|
108 | This event indicates that the compositor is done sending events to the | |
|
|
109 | ext_workspace_manager_v1. The server will destroy the object | |
|
|
110 | immediately after sending this request. | |
|
|
111 | </description> | |
|
|
112 | </event> | |
|
|
113 | ||
|
|
114 | <request name="stop"> | |
|
|
115 | <description summary="stop sending events"> | |
|
|
116 | Indicates the client no longer wishes to receive events for new | |
|
|
117 | workspace groups. However the compositor may emit further workspace | |
|
|
118 | events, until the finished event is emitted. The compositor is expected | |
|
|
119 | to send the finished event eventually once the stop request has been processed. | |
|
|
120 | ||
|
|
121 | The client must not send any requests after this one, doing so will raise a wl_display | |
|
|
122 | invalid_object error. | |
|
|
123 | </description> | |
|
|
124 | </request> | |
|
|
125 | ||
|
|
126 | </interface> | |
|
|
127 | ||
|
|
128 | <interface name="ext_workspace_group_handle_v1" version="1"> | |
|
|
129 | <description summary="a workspace group assigned to a set of outputs"> | |
|
|
130 | A ext_workspace_group_handle_v1 object represents a workspace group | |
|
|
131 | that is assigned a set of outputs and contains a number of workspaces. | |
|
|
132 | ||
|
|
133 | The set of outputs assigned to the workspace group is conveyed to the client via | |
|
|
134 | output_enter and output_leave events, and its workspaces are conveyed with | |
|
|
135 | workspace events. | |
|
|
136 | ||
|
|
137 | For example, a compositor which has a set of workspaces for each output may | |
|
|
138 | advertise a workspace group (and its workspaces) per output, whereas a compositor | |
|
|
139 | where a workspace spans all outputs may advertise a single workspace group for all | |
|
|
140 | outputs. | |
|
|
141 | </description> | |
|
|
142 | ||
|
|
143 | <enum name="group_capabilities" bitfield="true"> | |
|
|
144 | <entry name="create_workspace" value="1" summary="create_workspace request is available"/> | |
|
|
145 | </enum> | |
|
|
146 | ||
|
|
147 | <event name="capabilities"> | |
|
|
148 | <description summary="compositor capabilities"> | |
|
|
149 | This event advertises the capabilities supported by the compositor. If | |
|
|
150 | a capability isn't supported, clients should hide or disable the UI | |
|
|
151 | elements that expose this functionality. For instance, if the | |
|
|
152 | compositor doesn't advertise support for creating workspaces, a button | |
|
|
153 | triggering the create_workspace request should not be displayed. | |
|
|
154 | ||
|
|
155 | The compositor will ignore requests it doesn't support. For instance, | |
|
|
156 | a compositor which doesn't advertise support for creating workspaces will ignore | |
|
|
157 | create_workspace requests. | |
|
|
158 | ||
|
|
159 | Compositors must send this event once after creation of an | |
|
|
160 | ext_workspace_group_handle_v1. When the capabilities change, compositors | |
|
|
161 | must send this event again. | |
|
|
162 | </description> | |
|
|
163 | <arg name="capabilities" type="uint" summary="capabilities" enum="group_capabilities"/> | |
|
|
164 | </event> | |
|
|
165 | ||
|
|
166 | <event name="output_enter"> | |
|
|
167 | <description summary="output assigned to workspace group"> | |
|
|
168 | This event is emitted whenever an output is assigned to the workspace | |
|
|
169 | group or a new `wl_output` object is bound by the client, which was already | |
|
|
170 | assigned to this workspace_group. | |
|
|
171 | </description> | |
|
|
172 | <arg name="output" type="object" interface="wl_output"/> | |
|
|
173 | </event> | |
|
|
174 | ||
|
|
175 | <event name="output_leave"> | |
|
|
176 | <description summary="output removed from workspace group"> | |
|
|
177 | This event is emitted whenever an output is removed from the workspace | |
|
|
178 | group. | |
|
|
179 | </description> | |
|
|
180 | <arg name="output" type="object" interface="wl_output"/> | |
|
|
181 | </event> | |
|
|
182 | ||
|
|
183 | <event name="workspace_enter"> | |
|
|
184 | <description summary="workspace added to workspace group"> | |
|
|
185 | This event is emitted whenever a workspace is assigned to this group. | |
|
|
186 | A workspace may only ever be assigned to a single group at a single point | |
|
|
187 | in time, but can be re-assigned during its lifetime. | |
|
|
188 | </description> | |
|
|
189 | <arg name="workspace" type="object" interface="ext_workspace_handle_v1"/> | |
|
|
190 | </event> | |
|
|
191 | ||
|
|
192 | <event name="workspace_leave"> | |
|
|
193 | <description summary="workspace removed from workspace group"> | |
|
|
194 | This event is emitted whenever a workspace is removed from this group. | |
|
|
195 | </description> | |
|
|
196 | <arg name="workspace" type="object" interface="ext_workspace_handle_v1"/> | |
|
|
197 | </event> | |
|
|
198 | ||
|
|
199 | <event name="removed"> | |
|
|
200 | <description summary="this workspace group has been removed"> | |
|
|
201 | This event is send when the group associated with the ext_workspace_group_handle_v1 | |
|
|
202 | has been removed. After sending this request the compositor will immediately consider | |
|
|
203 | the object inert. Any requests will be ignored except the destroy request. | |
|
|
204 | It is guaranteed there won't be any more events referencing this | |
|
|
205 | ext_workspace_group_handle_v1. | |
|
|
206 | ||
|
|
207 | The compositor must remove all workspaces belonging to a workspace group | |
|
|
208 | via a workspace_leave event before removing the workspace group. | |
|
|
209 | </description> | |
|
|
210 | </event> | |
|
|
211 | ||
|
|
212 | <request name="create_workspace"> | |
|
|
213 | <description summary="create a new workspace"> | |
|
|
214 | Request that the compositor create a new workspace with the given name | |
|
|
215 | and assign it to this group. | |
|
|
216 | ||
|
|
217 | There is no guarantee that the compositor will create a new workspace, | |
|
|
218 | or that the created workspace will have the provided name. | |
|
|
219 | </description> | |
|
|
220 | <arg name="workspace" type="string"/> | |
|
|
221 | </request> | |
|
|
222 | ||
|
|
223 | <request name="destroy" type="destructor"> | |
|
|
224 | <description summary="destroy the ext_workspace_group_handle_v1 object"> | |
|
|
225 | Destroys the ext_workspace_group_handle_v1 object. | |
|
|
226 | ||
|
|
227 | This request should be send either when the client does not want to | |
|
|
228 | use the workspace group object any more or after the removed event to finalize | |
|
|
229 | the destruction of the object. | |
|
|
230 | </description> | |
|
|
231 | </request> | |
|
|
232 | </interface> | |
|
|
233 | ||
|
|
234 | <interface name="ext_workspace_handle_v1" version="1"> | |
|
|
235 | <description summary="a workspace handing a group of surfaces"> | |
|
|
236 | A ext_workspace_handle_v1 object represents a workspace that handles a | |
|
|
237 | group of surfaces. | |
|
|
238 | ||
|
|
239 | Each workspace has: | |
|
|
240 | - a name, conveyed to the client with the name event | |
|
|
241 | - potentially an id conveyed with the id event | |
|
|
242 | - a list of states, conveyed to the client with the state event | |
|
|
243 | - and optionally a set of coordinates, conveyed to the client with the | |
|
|
244 | coordinates event | |
|
|
245 | ||
|
|
246 | The client may request that the compositor activate or deactivate the workspace. | |
|
|
247 | ||
|
|
248 | Each workspace can belong to only a single workspace group. | |
|
|
249 | Depending on the compositor policy, there might be workspaces with | |
|
|
250 | the same name in different workspace groups, but these workspaces are still | |
|
|
251 | separate (e.g. one of them might be active while the other is not). | |
|
|
252 | </description> | |
|
|
253 | ||
|
|
254 | <event name="id"> | |
|
|
255 | <description summary="workspace id"> | |
|
|
256 | If this event is emitted, it will be send immediately after the | |
|
|
257 | ext_workspace_handle_v1 is created or when an id is assigned to | |
|
|
258 | a workspace (at most once during its lifetime). | |
|
|
259 | ||
|
|
260 | An id will never change during the lifetime of the `ext_workspace_handle_v1` | |
|
|
261 | and is guaranteed to be unique during its lifetime. | |
|
|
262 | ||
|
|
263 | Ids are not human-readable and shouldn't be displayed, use `name` for that purpose. | |
|
|
264 | ||
|
|
265 | Compositors are expected to only send ids for workspaces likely stable across multiple | |
|
|
266 | sessions and can be used by clients to store preferences for workspaces. Workspaces without | |
|
|
267 | ids should be considered temporary and any data associated with them should be deleted once | |
|
|
268 | the respective object is lost. | |
|
|
269 | </description> | |
|
|
270 | <arg name="id" type="string"/> | |
|
|
271 | </event> | |
|
|
272 | ||
|
|
273 | <event name="name"> | |
|
|
274 | <description summary="workspace name changed"> | |
|
|
275 | This event is emitted immediately after the ext_workspace_handle_v1 is | |
|
|
276 | created and whenever the name of the workspace changes. | |
|
|
277 | ||
|
|
278 | A name is meant to be human-readable and can be displayed to a user. | |
|
|
279 | Unlike the id it is neither stable nor unique. | |
|
|
280 | </description> | |
|
|
281 | <arg name="name" type="string"/> | |
|
|
282 | </event> | |
|
|
283 | ||
|
|
284 | <event name="coordinates"> | |
|
|
285 | <description summary="workspace coordinates changed"> | |
|
|
286 | This event is used to organize workspaces into an N-dimensional grid | |
|
|
287 | within a workspace group, and if supported, is emitted immediately after | |
|
|
288 | the ext_workspace_handle_v1 is created and whenever the coordinates of | |
|
|
289 | the workspace change. Compositors may not send this event if they do not | |
|
|
290 | conceptually arrange workspaces in this way. If compositors simply | |
|
|
291 | number workspaces, without any geometric interpretation, they may send | |
|
|
292 | 1D coordinates, which clients should not interpret as implying any | |
|
|
293 | geometry. Sending an empty array means that the compositor no longer | |
|
|
294 | orders the workspace geometrically. | |
|
|
295 | ||
|
|
296 | Coordinates have an arbitrary number of dimensions N with an uint32 | |
|
|
297 | position along each dimension. By convention if N > 1, the first | |
|
|
298 | dimension is X, the second Y, the third Z, and so on. The compositor may | |
|
|
299 | chose to utilize these events for a more novel workspace layout | |
|
|
300 | convention, however. No guarantee is made about the grid being filled or | |
|
|
301 | bounded; there may be a workspace at coordinate 1 and another at | |
|
|
302 | coordinate 1000 and none in between. Within a workspace group, however, | |
|
|
303 | workspaces must have unique coordinates of equal dimensionality. | |
|
|
304 | </description> | |
|
|
305 | <arg name="coordinates" type="array"/> | |
|
|
306 | </event> | |
|
|
307 | ||
|
|
308 | <enum name="state" bitfield="true"> | |
|
|
309 | <description summary="types of states on the workspace"> | |
|
|
310 | The different states that a workspace can have. | |
|
|
311 | </description> | |
|
|
312 | ||
|
|
313 | <entry name="active" value="1" summary="the workspace is active"/> | |
|
|
314 | <entry name="urgent" value="2" summary="the workspace requests attention"/> | |
|
|
315 | <entry name="hidden" value="4"> | |
|
|
316 | <description summary="the workspace is not visible"> | |
|
|
317 | The workspace is not visible in its workspace group, and clients | |
|
|
318 | attempting to visualize the compositor workspace state should not | |
|
|
319 | display such workspaces. | |
|
|
320 | </description> | |
|
|
321 | </entry> | |
|
|
322 | </enum> | |
|
|
323 | ||
|
|
324 | <event name="state"> | |
|
|
325 | <description summary="the state of the workspace changed"> | |
|
|
326 | This event is emitted immediately after the ext_workspace_handle_v1 is | |
|
|
327 | created and each time the workspace state changes, either because of a | |
|
|
328 | compositor action or because of a request in this protocol. | |
|
|
329 | ||
|
|
330 | Missing states convey the opposite meaning, e.g. an unset active bit | |
|
|
331 | means the workspace is currently inactive. | |
|
|
332 | </description> | |
|
|
333 | <arg name="state" type="uint" enum="state"/> | |
|
|
334 | </event> | |
|
|
335 | ||
|
|
336 | <enum name="workspace_capabilities" bitfield="true"> | |
|
|
337 | <entry name="activate" value="1" summary="activate request is available"/> | |
|
|
338 | <entry name="deactivate" value="2" summary="deactivate request is available"/> | |
|
|
339 | <entry name="remove" value="4" summary="remove request is available"/> | |
|
|
340 | <entry name="assign" value="8" summary="assign request is available"/> | |
|
|
341 | </enum> | |
|
|
342 | ||
|
|
343 | <event name="capabilities"> | |
|
|
344 | <description summary="compositor capabilities"> | |
|
|
345 | This event advertises the capabilities supported by the compositor. If | |
|
|
346 | a capability isn't supported, clients should hide or disable the UI | |
|
|
347 | elements that expose this functionality. For instance, if the | |
|
|
348 | compositor doesn't advertise support for removing workspaces, a button | |
|
|
349 | triggering the remove request should not be displayed. | |
|
|
350 | ||
|
|
351 | The compositor will ignore requests it doesn't support. For instance, | |
|
|
352 | a compositor which doesn't advertise support for remove will ignore | |
|
|
353 | remove requests. | |
|
|
354 | ||
|
|
355 | Compositors must send this event once after creation of an | |
|
|
356 | ext_workspace_handle_v1 . When the capabilities change, compositors | |
|
|
357 | must send this event again. | |
|
|
358 | </description> | |
|
|
359 | <arg name="capabilities" type="uint" summary="capabilities" enum="workspace_capabilities"/> | |
|
|
360 | </event> | |
|
|
361 | ||
|
|
362 | <event name="removed"> | |
|
|
363 | <description summary="this workspace has been removed"> | |
|
|
364 | This event is send when the workspace associated with the ext_workspace_handle_v1 | |
|
|
365 | has been removed. After sending this request, the compositor will immediately consider | |
|
|
366 | the object inert. Any requests will be ignored except the destroy request. | |
|
|
367 | ||
|
|
368 | It is guaranteed there won't be any more events referencing this | |
|
|
369 | ext_workspace_handle_v1. | |
|
|
370 | ||
|
|
371 | The compositor must only remove a workspaces not currently belonging to any | |
|
|
372 | workspace_group. | |
|
|
373 | </description> | |
|
|
374 | </event> | |
|
|
375 | ||
|
|
376 | <request name="destroy" type="destructor"> | |
|
|
377 | <description summary="destroy the ext_workspace_handle_v1 object"> | |
|
|
378 | Destroys the ext_workspace_handle_v1 object. | |
|
|
379 | ||
|
|
380 | This request should be made either when the client does not want to | |
|
|
381 | use the workspace object any more or after the remove event to finalize | |
|
|
382 | the destruction of the object. | |
|
|
383 | </description> | |
|
|
384 | </request> | |
|
|
385 | ||
|
|
386 | <request name="activate"> | |
|
|
387 | <description summary="activate the workspace"> | |
|
|
388 | Request that this workspace be activated. | |
|
|
389 | ||
|
|
390 | There is no guarantee the workspace will be actually activated, and | |
|
|
391 | behaviour may be compositor-dependent. For example, activating a | |
|
|
392 | workspace may or may not deactivate all other workspaces in the same | |
|
|
393 | group. | |
|
|
394 | </description> | |
|
|
395 | </request> | |
|
|
396 | ||
|
|
397 | <request name="deactivate"> | |
|
|
398 | <description summary="deactivate the workspace"> | |
|
|
399 | Request that this workspace be deactivated. | |
|
|
400 | ||
|
|
401 | There is no guarantee the workspace will be actually deactivated. | |
|
|
402 | </description> | |
|
|
403 | </request> | |
|
|
404 | ||
|
|
405 | <request name="assign"> | |
|
|
406 | <description summary="assign workspace to group"> | |
|
|
407 | Requests that this workspace is assigned to the given workspace group. | |
|
|
408 | ||
|
|
409 | There is no guarantee the workspace will be assigned. | |
|
|
410 | </description> | |
|
|
411 | <arg name="workspace_group" type="object" interface="ext_workspace_group_handle_v1"/> | |
|
|
412 | </request> | |
|
|
413 | ||
|
|
414 | <request name="remove"> | |
|
|
415 | <description summary="remove the workspace"> | |
|
|
416 | Request that this workspace be removed. | |
|
|
417 | ||
|
|
418 | There is no guarantee the workspace will be actually removed. | |
|
|
419 | </description> | |
|
|
420 | </request> | |
|
|
421 | </interface> | |
|
|
422 | </protocol> | |
| @@ -0,0 +1,390 | |||
|
|
1 | <?xml version="1.0" encoding="UTF-8"?> | |
|
|
2 | <protocol name="wlr_layer_shell_unstable_v1"> | |
|
|
3 | <copyright> | |
|
|
4 | Copyright Β© 2017 Drew DeVault | |
|
|
5 | ||
|
|
6 | Permission to use, copy, modify, distribute, and sell this | |
|
|
7 | software and its documentation for any purpose is hereby granted | |
|
|
8 | without fee, provided that the above copyright notice appear in | |
|
|
9 | all copies and that both that copyright notice and this permission | |
|
|
10 | notice appear in supporting documentation, and that the name of | |
|
|
11 | the copyright holders not be used in advertising or publicity | |
|
|
12 | pertaining to distribution of the software without specific, | |
|
|
13 | written prior permission. The copyright holders make no | |
|
|
14 | representations about the suitability of this software for any | |
|
|
15 | purpose. It is provided "as is" without express or implied | |
|
|
16 | warranty. | |
|
|
17 | ||
|
|
18 | THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | |
|
|
19 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
|
|
20 | FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
|
|
21 | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
|
|
22 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |
|
|
23 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
|
|
24 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | |
|
|
25 | THIS SOFTWARE. | |
|
|
26 | </copyright> | |
|
|
27 | ||
|
|
28 | <interface name="zwlr_layer_shell_v1" version="4"> | |
|
|
29 | <description summary="create surfaces that are layers of the desktop"> | |
|
|
30 | Clients can use this interface to assign the surface_layer role to | |
|
|
31 | wl_surfaces. Such surfaces are assigned to a "layer" of the output and | |
|
|
32 | rendered with a defined z-depth respective to each other. They may also be | |
|
|
33 | anchored to the edges and corners of a screen and specify input handling | |
|
|
34 | semantics. This interface should be suitable for the implementation of | |
|
|
35 | many desktop shell components, and a broad number of other applications | |
|
|
36 | that interact with the desktop. | |
|
|
37 | </description> | |
|
|
38 | ||
|
|
39 | <request name="get_layer_surface"> | |
|
|
40 | <description summary="create a layer_surface from a surface"> | |
|
|
41 | Create a layer surface for an existing surface. This assigns the role of | |
|
|
42 | layer_surface, or raises a protocol error if another role is already | |
|
|
43 | assigned. | |
|
|
44 | ||
|
|
45 | Creating a layer surface from a wl_surface which has a buffer attached | |
|
|
46 | or committed is a client error, and any attempts by a client to attach | |
|
|
47 | or manipulate a buffer prior to the first layer_surface.configure call | |
|
|
48 | must also be treated as errors. | |
|
|
49 | ||
|
|
50 | After creating a layer_surface object and setting it up, the client | |
|
|
51 | must perform an initial commit without any buffer attached. | |
|
|
52 | The compositor will reply with a layer_surface.configure event. | |
|
|
53 | The client must acknowledge it and is then allowed to attach a buffer | |
|
|
54 | to map the surface. | |
|
|
55 | ||
|
|
56 | You may pass NULL for output to allow the compositor to decide which | |
|
|
57 | output to use. Generally this will be the one that the user most | |
|
|
58 | recently interacted with. | |
|
|
59 | ||
|
|
60 | Clients can specify a namespace that defines the purpose of the layer | |
|
|
61 | surface. | |
|
|
62 | </description> | |
|
|
63 | <arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/> | |
|
|
64 | <arg name="surface" type="object" interface="wl_surface"/> | |
|
|
65 | <arg name="output" type="object" interface="wl_output" allow-null="true"/> | |
|
|
66 | <arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/> | |
|
|
67 | <arg name="namespace" type="string" summary="namespace for the layer surface"/> | |
|
|
68 | </request> | |
|
|
69 | ||
|
|
70 | <enum name="error"> | |
|
|
71 | <entry name="role" value="0" summary="wl_surface has another role"/> | |
|
|
72 | <entry name="invalid_layer" value="1" summary="layer value is invalid"/> | |
|
|
73 | <entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/> | |
|
|
74 | </enum> | |
|
|
75 | ||
|
|
76 | <enum name="layer"> | |
|
|
77 | <description summary="available layers for surfaces"> | |
|
|
78 | These values indicate which layers a surface can be rendered in. They | |
|
|
79 | are ordered by z depth, bottom-most first. Traditional shell surfaces | |
|
|
80 | will typically be rendered between the bottom and top layers. | |
|
|
81 | Fullscreen shell surfaces are typically rendered at the top layer. | |
|
|
82 | Multiple surfaces can share a single layer, and ordering within a | |
|
|
83 | single layer is undefined. | |
|
|
84 | </description> | |
|
|
85 | ||
|
|
86 | <entry name="background" value="0"/> | |
|
|
87 | <entry name="bottom" value="1"/> | |
|
|
88 | <entry name="top" value="2"/> | |
|
|
89 | <entry name="overlay" value="3"/> | |
|
|
90 | </enum> | |
|
|
91 | ||
|
|
92 | <!-- Version 3 additions --> | |
|
|
93 | ||
|
|
94 | <request name="destroy" type="destructor" since="3"> | |
|
|
95 | <description summary="destroy the layer_shell object"> | |
|
|
96 | This request indicates that the client will not use the layer_shell | |
|
|
97 | object any more. Objects that have been created through this instance | |
|
|
98 | are not affected. | |
|
|
99 | </description> | |
|
|
100 | </request> | |
|
|
101 | </interface> | |
|
|
102 | ||
|
|
103 | <interface name="zwlr_layer_surface_v1" version="4"> | |
|
|
104 | <description summary="layer metadata interface"> | |
|
|
105 | An interface that may be implemented by a wl_surface, for surfaces that | |
|
|
106 | are designed to be rendered as a layer of a stacked desktop-like | |
|
|
107 | environment. | |
|
|
108 | ||
|
|
109 | Layer surface state (layer, size, anchor, exclusive zone, | |
|
|
110 | margin, interactivity) is double-buffered, and will be applied at the | |
|
|
111 | time wl_surface.commit of the corresponding wl_surface is called. | |
|
|
112 | ||
|
|
113 | Attaching a null buffer to a layer surface unmaps it. | |
|
|
114 | ||
|
|
115 | Unmapping a layer_surface means that the surface cannot be shown by the | |
|
|
116 | compositor until it is explicitly mapped again. The layer_surface | |
|
|
117 | returns to the state it had right after layer_shell.get_layer_surface. | |
|
|
118 | The client can re-map the surface by performing a commit without any | |
|
|
119 | buffer attached, waiting for a configure event and handling it as usual. | |
|
|
120 | </description> | |
|
|
121 | ||
|
|
122 | <request name="set_size"> | |
|
|
123 | <description summary="sets the size of the surface"> | |
|
|
124 | Sets the size of the surface in surface-local coordinates. The | |
|
|
125 | compositor will display the surface centered with respect to its | |
|
|
126 | anchors. | |
|
|
127 | ||
|
|
128 | If you pass 0 for either value, the compositor will assign it and | |
|
|
129 | inform you of the assignment in the configure event. You must set your | |
|
|
130 | anchor to opposite edges in the dimensions you omit; not doing so is a | |
|
|
131 | protocol error. Both values are 0 by default. | |
|
|
132 | ||
|
|
133 | Size is double-buffered, see wl_surface.commit. | |
|
|
134 | </description> | |
|
|
135 | <arg name="width" type="uint"/> | |
|
|
136 | <arg name="height" type="uint"/> | |
|
|
137 | </request> | |
|
|
138 | ||
|
|
139 | <request name="set_anchor"> | |
|
|
140 | <description summary="configures the anchor point of the surface"> | |
|
|
141 | Requests that the compositor anchor the surface to the specified edges | |
|
|
142 | and corners. If two orthogonal edges are specified (e.g. 'top' and | |
|
|
143 | 'left'), then the anchor point will be the intersection of the edges | |
|
|
144 | (e.g. the top left corner of the output); otherwise the anchor point | |
|
|
145 | will be centered on that edge, or in the center if none is specified. | |
|
|
146 | ||
|
|
147 | Anchor is double-buffered, see wl_surface.commit. | |
|
|
148 | </description> | |
|
|
149 | <arg name="anchor" type="uint" enum="anchor"/> | |
|
|
150 | </request> | |
|
|
151 | ||
|
|
152 | <request name="set_exclusive_zone"> | |
|
|
153 | <description summary="configures the exclusive geometry of this surface"> | |
|
|
154 | Requests that the compositor avoids occluding an area with other | |
|
|
155 | surfaces. The compositor's use of this information is | |
|
|
156 | implementation-dependent - do not assume that this region will not | |
|
|
157 | actually be occluded. | |
|
|
158 | ||
|
|
159 | A positive value is only meaningful if the surface is anchored to one | |
|
|
160 | edge or an edge and both perpendicular edges. If the surface is not | |
|
|
161 | anchored, anchored to only two perpendicular edges (a corner), anchored | |
|
|
162 | to only two parallel edges or anchored to all edges, a positive value | |
|
|
163 | will be treated the same as zero. | |
|
|
164 | ||
|
|
165 | A positive zone is the distance from the edge in surface-local | |
|
|
166 | coordinates to consider exclusive. | |
|
|
167 | ||
|
|
168 | Surfaces that do not wish to have an exclusive zone may instead specify | |
|
|
169 | how they should interact with surfaces that do. If set to zero, the | |
|
|
170 | surface indicates that it would like to be moved to avoid occluding | |
|
|
171 | surfaces with a positive exclusive zone. If set to -1, the surface | |
|
|
172 | indicates that it would not like to be moved to accommodate for other | |
|
|
173 | surfaces, and the compositor should extend it all the way to the edges | |
|
|
174 | it is anchored to. | |
|
|
175 | ||
|
|
176 | For example, a panel might set its exclusive zone to 10, so that | |
|
|
177 | maximized shell surfaces are not shown on top of it. A notification | |
|
|
178 | might set its exclusive zone to 0, so that it is moved to avoid | |
|
|
179 | occluding the panel, but shell surfaces are shown underneath it. A | |
|
|
180 | wallpaper or lock screen might set their exclusive zone to -1, so that | |
|
|
181 | they stretch below or over the panel. | |
|
|
182 | ||
|
|
183 | The default value is 0. | |
|
|
184 | ||
|
|
185 | Exclusive zone is double-buffered, see wl_surface.commit. | |
|
|
186 | </description> | |
|
|
187 | <arg name="zone" type="int"/> | |
|
|
188 | </request> | |
|
|
189 | ||
|
|
190 | <request name="set_margin"> | |
|
|
191 | <description summary="sets a margin from the anchor point"> | |
|
|
192 | Requests that the surface be placed some distance away from the anchor | |
|
|
193 | point on the output, in surface-local coordinates. Setting this value | |
|
|
194 | for edges you are not anchored to has no effect. | |
|
|
195 | ||
|
|
196 | The exclusive zone includes the margin. | |
|
|
197 | ||
|
|
198 | Margin is double-buffered, see wl_surface.commit. | |
|
|
199 | </description> | |
|
|
200 | <arg name="top" type="int"/> | |
|
|
201 | <arg name="right" type="int"/> | |
|
|
202 | <arg name="bottom" type="int"/> | |
|
|
203 | <arg name="left" type="int"/> | |
|
|
204 | </request> | |
|
|
205 | ||
|
|
206 | <enum name="keyboard_interactivity"> | |
|
|
207 | <description summary="types of keyboard interaction possible for a layer shell surface"> | |
|
|
208 | Types of keyboard interaction possible for layer shell surfaces. The | |
|
|
209 | rationale for this is twofold: (1) some applications are not interested | |
|
|
210 | in keyboard events and not allowing them to be focused can improve the | |
|
|
211 | desktop experience; (2) some applications will want to take exclusive | |
|
|
212 | keyboard focus. | |
|
|
213 | </description> | |
|
|
214 | ||
|
|
215 | <entry name="none" value="0"> | |
|
|
216 | <description summary="no keyboard focus is possible"> | |
|
|
217 | This value indicates that this surface is not interested in keyboard | |
|
|
218 | events and the compositor should never assign it the keyboard focus. | |
|
|
219 | ||
|
|
220 | This is the default value, set for newly created layer shell surfaces. | |
|
|
221 | ||
|
|
222 | This is useful for e.g. desktop widgets that display information or | |
|
|
223 | only have interaction with non-keyboard input devices. | |
|
|
224 | </description> | |
|
|
225 | </entry> | |
|
|
226 | <entry name="exclusive" value="1"> | |
|
|
227 | <description summary="request exclusive keyboard focus"> | |
|
|
228 | Request exclusive keyboard focus if this surface is above the shell surface layer. | |
|
|
229 | ||
|
|
230 | For the top and overlay layers, the seat will always give | |
|
|
231 | exclusive keyboard focus to the top-most layer which has keyboard | |
|
|
232 | interactivity set to exclusive. If this layer contains multiple | |
|
|
233 | surfaces with keyboard interactivity set to exclusive, the compositor | |
|
|
234 | determines the one receiving keyboard events in an implementation- | |
|
|
235 | defined manner. In this case, no guarantee is made when this surface | |
|
|
236 | will receive keyboard focus (if ever). | |
|
|
237 | ||
|
|
238 | For the bottom and background layers, the compositor is allowed to use | |
|
|
239 | normal focus semantics. | |
|
|
240 | ||
|
|
241 | This setting is mainly intended for applications that need to ensure | |
|
|
242 | they receive all keyboard events, such as a lock screen or a password | |
|
|
243 | prompt. | |
|
|
244 | </description> | |
|
|
245 | </entry> | |
|
|
246 | <entry name="on_demand" value="2" since="4"> | |
|
|
247 | <description summary="request regular keyboard focus semantics"> | |
|
|
248 | This requests the compositor to allow this surface to be focused and | |
|
|
249 | unfocused by the user in an implementation-defined manner. The user | |
|
|
250 | should be able to unfocus this surface even regardless of the layer | |
|
|
251 | it is on. | |
|
|
252 | ||
|
|
253 | Typically, the compositor will want to use its normal mechanism to | |
|
|
254 | manage keyboard focus between layer shell surfaces with this setting | |
|
|
255 | and regular toplevels on the desktop layer (e.g. click to focus). | |
|
|
256 | Nevertheless, it is possible for a compositor to require a special | |
|
|
257 | interaction to focus or unfocus layer shell surfaces (e.g. requiring | |
|
|
258 | a click even if focus follows the mouse normally, or providing a | |
|
|
259 | keybinding to switch focus between layers). | |
|
|
260 | ||
|
|
261 | This setting is mainly intended for desktop shell components (e.g. | |
|
|
262 | panels) that allow keyboard interaction. Using this option can allow | |
|
|
263 | implementing a desktop shell that can be fully usable without the | |
|
|
264 | mouse. | |
|
|
265 | </description> | |
|
|
266 | </entry> | |
|
|
267 | </enum> | |
|
|
268 | ||
|
|
269 | <request name="set_keyboard_interactivity"> | |
|
|
270 | <description summary="requests keyboard events"> | |
|
|
271 | Set how keyboard events are delivered to this surface. By default, | |
|
|
272 | layer shell surfaces do not receive keyboard events; this request can | |
|
|
273 | be used to change this. | |
|
|
274 | ||
|
|
275 | This setting is inherited by child surfaces set by the get_popup | |
|
|
276 | request. | |
|
|
277 | ||
|
|
278 | Layer surfaces receive pointer, touch, and tablet events normally. If | |
|
|
279 | you do not want to receive them, set the input region on your surface | |
|
|
280 | to an empty region. | |
|
|
281 | ||
|
|
282 | Keyboard interactivity is double-buffered, see wl_surface.commit. | |
|
|
283 | </description> | |
|
|
284 | <arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/> | |
|
|
285 | </request> | |
|
|
286 | ||
|
|
287 | <request name="get_popup"> | |
|
|
288 | <description summary="assign this layer_surface as an xdg_popup parent"> | |
|
|
289 | This assigns an xdg_popup's parent to this layer_surface. This popup | |
|
|
290 | should have been created via xdg_surface::get_popup with the parent set | |
|
|
291 | to NULL, and this request must be invoked before committing the popup's | |
|
|
292 | initial state. | |
|
|
293 | ||
|
|
294 | See the documentation of xdg_popup for more details about what an | |
|
|
295 | xdg_popup is and how it is used. | |
|
|
296 | </description> | |
|
|
297 | <arg name="popup" type="object" interface="xdg_popup"/> | |
|
|
298 | </request> | |
|
|
299 | ||
|
|
300 | <request name="ack_configure"> | |
|
|
301 | <description summary="ack a configure event"> | |
|
|
302 | When a configure event is received, if a client commits the | |
|
|
303 | surface in response to the configure event, then the client | |
|
|
304 | must make an ack_configure request sometime before the commit | |
|
|
305 | request, passing along the serial of the configure event. | |
|
|
306 | ||
|
|
307 | If the client receives multiple configure events before it | |
|
|
308 | can respond to one, it only has to ack the last configure event. | |
|
|
309 | ||
|
|
310 | A client is not required to commit immediately after sending | |
|
|
311 | an ack_configure request - it may even ack_configure several times | |
|
|
312 | before its next surface commit. | |
|
|
313 | ||
|
|
314 | A client may send multiple ack_configure requests before committing, but | |
|
|
315 | only the last request sent before a commit indicates which configure | |
|
|
316 | event the client really is responding to. | |
|
|
317 | </description> | |
|
|
318 | <arg name="serial" type="uint" summary="the serial from the configure event"/> | |
|
|
319 | </request> | |
|
|
320 | ||
|
|
321 | <request name="destroy" type="destructor"> | |
|
|
322 | <description summary="destroy the layer_surface"> | |
|
|
323 | This request destroys the layer surface. | |
|
|
324 | </description> | |
|
|
325 | </request> | |
|
|
326 | ||
|
|
327 | <event name="configure"> | |
|
|
328 | <description summary="suggest a surface change"> | |
|
|
329 | The configure event asks the client to resize its surface. | |
|
|
330 | ||
|
|
331 | Clients should arrange their surface for the new states, and then send | |
|
|
332 | an ack_configure request with the serial sent in this configure event at | |
|
|
333 | some point before committing the new surface. | |
|
|
334 | ||
|
|
335 | The client is free to dismiss all but the last configure event it | |
|
|
336 | received. | |
|
|
337 | ||
|
|
338 | The width and height arguments specify the size of the window in | |
|
|
339 | surface-local coordinates. | |
|
|
340 | ||
|
|
341 | The size is a hint, in the sense that the client is free to ignore it if | |
|
|
342 | it doesn't resize, pick a smaller size (to satisfy aspect ratio or | |
|
|
343 | resize in steps of NxM pixels). If the client picks a smaller size and | |
|
|
344 | is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the | |
|
|
345 | surface will be centered on this axis. | |
|
|
346 | ||
|
|
347 | If the width or height arguments are zero, it means the client should | |
|
|
348 | decide its own window dimension. | |
|
|
349 | </description> | |
|
|
350 | <arg name="serial" type="uint"/> | |
|
|
351 | <arg name="width" type="uint"/> | |
|
|
352 | <arg name="height" type="uint"/> | |
|
|
353 | </event> | |
|
|
354 | ||
|
|
355 | <event name="closed"> | |
|
|
356 | <description summary="surface should be closed"> | |
|
|
357 | The closed event is sent by the compositor when the surface will no | |
|
|
358 | longer be shown. The output may have been destroyed or the user may | |
|
|
359 | have asked for it to be removed. Further changes to the surface will be | |
|
|
360 | ignored. The client should destroy the resource after receiving this | |
|
|
361 | event, and create a new surface if they so choose. | |
|
|
362 | </description> | |
|
|
363 | </event> | |
|
|
364 | ||
|
|
365 | <enum name="error"> | |
|
|
366 | <entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/> | |
|
|
367 | <entry name="invalid_size" value="1" summary="size is invalid"/> | |
|
|
368 | <entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/> | |
|
|
369 | <entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/> | |
|
|
370 | </enum> | |
|
|
371 | ||
|
|
372 | <enum name="anchor" bitfield="true"> | |
|
|
373 | <entry name="top" value="1" summary="the top edge of the anchor rectangle"/> | |
|
|
374 | <entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/> | |
|
|
375 | <entry name="left" value="4" summary="the left edge of the anchor rectangle"/> | |
|
|
376 | <entry name="right" value="8" summary="the right edge of the anchor rectangle"/> | |
|
|
377 | </enum> | |
|
|
378 | ||
|
|
379 | <!-- Version 2 additions --> | |
|
|
380 | ||
|
|
381 | <request name="set_layer" since="2"> | |
|
|
382 | <description summary="change the layer of the surface"> | |
|
|
383 | Change the layer that the surface is rendered on. | |
|
|
384 | ||
|
|
385 | Layer is double-buffered, see wl_surface.commit. | |
|
|
386 | </description> | |
|
|
387 | <arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/> | |
|
|
388 | </request> | |
|
|
389 | </interface> | |
|
|
390 | </protocol> | |
| @@ -0,0 +1,128 | |||
|
|
1 | <?xml version="1.0" encoding="UTF-8"?> | |
|
|
2 | <protocol name="wlr_output_power_management_unstable_v1"> | |
|
|
3 | <copyright> | |
|
|
4 | Copyright Β© 2019 Purism SPC | |
|
|
5 | ||
|
|
6 | Permission is hereby granted, free of charge, to any person obtaining a | |
|
|
7 | copy of this software and associated documentation files (the "Software"), | |
|
|
8 | to deal in the Software without restriction, including without limitation | |
|
|
9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
|
|
10 | and/or sell copies of the Software, and to permit persons to whom the | |
|
|
11 | Software is furnished to do so, subject to the following conditions: | |
|
|
12 | ||
|
|
13 | The above copyright notice and this permission notice (including the next | |
|
|
14 | paragraph) shall be included in all copies or substantial portions of the | |
|
|
15 | Software. | |
|
|
16 | ||
|
|
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
|
|
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
|
|
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
|
|
20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
|
|
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
|
|
22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
|
|
23 | DEALINGS IN THE SOFTWARE. | |
|
|
24 | </copyright> | |
|
|
25 | ||
|
|
26 | <description summary="Control power management modes of outputs"> | |
|
|
27 | This protocol allows clients to control power management modes | |
|
|
28 | of outputs that are currently part of the compositor space. The | |
|
|
29 | intent is to allow special clients like desktop shells to power | |
|
|
30 | down outputs when the system is idle. | |
|
|
31 | ||
|
|
32 | To modify outputs not currently part of the compositor space see | |
|
|
33 | wlr-output-management. | |
|
|
34 | ||
|
|
35 | Warning! The protocol described in this file is experimental and | |
|
|
36 | backward incompatible changes may be made. Backward compatible changes | |
|
|
37 | may be added together with the corresponding interface version bump. | |
|
|
38 | Backward incompatible changes are done by bumping the version number in | |
|
|
39 | the protocol and interface names and resetting the interface version. | |
|
|
40 | Once the protocol is to be declared stable, the 'z' prefix and the | |
|
|
41 | version number in the protocol and interface names are removed and the | |
|
|
42 | interface version number is reset. | |
|
|
43 | </description> | |
|
|
44 | ||
|
|
45 | <interface name="zwlr_output_power_manager_v1" version="1"> | |
|
|
46 | <description summary="manager to create per-output power management"> | |
|
|
47 | This interface is a manager that allows creating per-output power | |
|
|
48 | management mode controls. | |
|
|
49 | </description> | |
|
|
50 | ||
|
|
51 | <request name="get_output_power"> | |
|
|
52 | <description summary="get a power management for an output"> | |
|
|
53 | Create a output power management mode control that can be used to | |
|
|
54 | adjust the power management mode for a given output. | |
|
|
55 | </description> | |
|
|
56 | <arg name="id" type="new_id" interface="zwlr_output_power_v1"/> | |
|
|
57 | <arg name="output" type="object" interface="wl_output"/> | |
|
|
58 | </request> | |
|
|
59 | ||
|
|
60 | <request name="destroy" type="destructor"> | |
|
|
61 | <description summary="destroy the manager"> | |
|
|
62 | All objects created by the manager will still remain valid, until their | |
|
|
63 | appropriate destroy request has been called. | |
|
|
64 | </description> | |
|
|
65 | </request> | |
|
|
66 | </interface> | |
|
|
67 | ||
|
|
68 | <interface name="zwlr_output_power_v1" version="1"> | |
|
|
69 | <description summary="adjust power management mode for an output"> | |
|
|
70 | This object offers requests to set the power management mode of | |
|
|
71 | an output. | |
|
|
72 | </description> | |
|
|
73 | ||
|
|
74 | <enum name="mode"> | |
|
|
75 | <entry name="off" value="0" | |
|
|
76 | summary="Output is turned off."/> | |
|
|
77 | <entry name="on" value="1" | |
|
|
78 | summary="Output is turned on, no power saving"/> | |
|
|
79 | </enum> | |
|
|
80 | ||
|
|
81 | <enum name="error"> | |
|
|
82 | <entry name="invalid_mode" value="1" summary="inexistent power save mode"/> | |
|
|
83 | </enum> | |
|
|
84 | ||
|
|
85 | <request name="set_mode"> | |
|
|
86 | <description summary="Set an outputs power save mode"> | |
|
|
87 | Set an output's power save mode to the given mode. The mode change | |
|
|
88 | is effective immediately. If the output does not support the given | |
|
|
89 | mode a failed event is sent. | |
|
|
90 | </description> | |
|
|
91 | <arg name="mode" type="uint" enum="mode" summary="the power save mode to set"/> | |
|
|
92 | </request> | |
|
|
93 | ||
|
|
94 | <event name="mode"> | |
|
|
95 | <description summary="Report a power management mode change"> | |
|
|
96 | Report the power management mode change of an output. | |
|
|
97 | ||
|
|
98 | The mode event is sent after an output changed its power | |
|
|
99 | management mode. The reason can be a client using set_mode or the | |
|
|
100 | compositor deciding to change an output's mode. | |
|
|
101 | This event is also sent immediately when the object is created | |
|
|
102 | so the client is informed about the current power management mode. | |
|
|
103 | </description> | |
|
|
104 | <arg name="mode" type="uint" enum="mode" | |
|
|
105 | summary="the output's new power management mode"/> | |
|
|
106 | </event> | |
|
|
107 | ||
|
|
108 | <event name="failed"> | |
|
|
109 | <description summary="object no longer valid"> | |
|
|
110 | This event indicates that the output power management mode control | |
|
|
111 | is no longer valid. This can happen for a number of reasons, | |
|
|
112 | including: | |
|
|
113 | - The output doesn't support power management | |
|
|
114 | - Another client already has exclusive power management mode control | |
|
|
115 | for this output | |
|
|
116 | - The output disappeared | |
|
|
117 | ||
|
|
118 | Upon receiving this event, the client should destroy this object. | |
|
|
119 | </description> | |
|
|
120 | </event> | |
|
|
121 | ||
|
|
122 | <request name="destroy" type="destructor"> | |
|
|
123 | <description summary="destroy this power management"> | |
|
|
124 | Destroys the output power management mode control object. | |
|
|
125 | </description> | |
|
|
126 | </request> | |
|
|
127 | </interface> | |
|
|
128 | </protocol> | |
| @@ -0,0 +1,55 | |||
|
|
1 | **smsg** - send ipc messages to swindle (forked from [this repository](https://codeberg.org/notchoc/dwlmsg)) | |
|
|
2 | ||
|
|
3 | ``` | |
|
|
4 | usage: smsg [-OTLPF] | |
|
|
5 | smsg [-o <output>] -s [-t <tags>] [-l <layout>] [-c <tags>] | |
|
|
6 | smsg [-o <output>] (-g | -w) [-FOotlcvmf] | |
|
|
7 | ``` | |
|
|
8 | ||
|
|
9 | ``` | |
|
|
10 | options: | |
|
|
11 | -g get | |
|
|
12 | -s set | |
|
|
13 | -w watch | |
|
|
14 | -O get all outputs | |
|
|
15 | -T get number of tags | |
|
|
16 | -L get all available layouts | |
|
|
17 | -P get compositor pid | |
|
|
18 | -F get focused output | |
|
|
19 | -o select output | |
|
|
20 | -t get/set selected tags (set with [+-^.], overwrite with ! prefix) | |
|
|
21 | -l get/set current layout | |
|
|
22 | -c get title and appid of focused client | |
|
|
23 | -v get visibility of statusbar | |
|
|
24 | -m get fullscreen status | |
|
|
25 | -f get floating status | |
|
|
26 | ``` | |
|
|
27 | ||
|
|
28 | ``` | |
|
|
29 | examples: | |
|
|
30 | # act like dwl stdout | |
|
|
31 | smsg -w | |
|
|
32 | # watch focused client appid and title | |
|
|
33 | smsg -w -c | |
|
|
34 | # get currently focused output | |
|
|
35 | smsg -F | |
|
|
36 | # watch for focused output changes | |
|
|
37 | smsg -w -F | |
|
|
38 | # get all available outputs | |
|
|
39 | smsg -O | |
|
|
40 | # watch available outputs | |
|
|
41 | smsg -w -O | |
|
|
42 | # select tag 1, deselect tag 2, toggle tag 4 on output eDP-1 | |
|
|
43 | smsg -o eDP-1 -s -t +-.^ | |
|
|
44 | # toggle tag 3, overwriting current tagset (yes, zero-indexed) | |
|
|
45 | smsg -t !2^ | |
|
|
46 | # select tag 8 on current output | |
|
|
47 | smsg -s -t 7 | |
|
|
48 | # deselect tag 8 on current output | |
|
|
49 | smsg -s -t 7- | |
|
|
50 | # switch to first layout (order given by smsg -L) | |
|
|
51 | smsg -l 0 | |
|
|
52 | # switch to floating layout | |
|
|
53 | smsg -l '><>' | |
|
|
54 | ``` | |
|
|
55 | ||
| @@ -0,0 +1,58 | |||
|
|
1 | #ifndef ARG_H__ | |
|
|
2 | #define ARG_H__ | |
|
|
3 | ||
|
|
4 | extern char *argv0; | |
|
|
5 | ||
|
|
6 | #define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ | |
|
|
7 | argv[0] && argv[0][0] == '-'\ | |
|
|
8 | && argv[0][1];\ | |
|
|
9 | argc--, argv++) {\ | |
|
|
10 | char argc_;\ | |
|
|
11 | char **argv_;\ | |
|
|
12 | int brk_;\ | |
|
|
13 | if (argv[0][1] == '-' && argv[0][2] == '\0') {\ | |
|
|
14 | argv++;\ | |
|
|
15 | argc--;\ | |
|
|
16 | break;\ | |
|
|
17 | }\ | |
|
|
18 | for (brk_ = 0, argv[0]++, argv_ = argv;\ | |
|
|
19 | argv[0][0] && !brk_;\ | |
|
|
20 | argv[0]++) {\ | |
|
|
21 | if (argv_ != argv)\ | |
|
|
22 | break;\ | |
|
|
23 | argc_ = argv[0][0];\ | |
|
|
24 | switch (argc_) | |
|
|
25 | ||
|
|
26 | #define ARGNUM case '0':\ | |
|
|
27 | case '1':\ | |
|
|
28 | case '2':\ | |
|
|
29 | case '3':\ | |
|
|
30 | case '4':\ | |
|
|
31 | case '5':\ | |
|
|
32 | case '6':\ | |
|
|
33 | case '7':\ | |
|
|
34 | case '8':\ | |
|
|
35 | case '9' | |
|
|
36 | ||
|
|
37 | #define ARGEND }\ | |
|
|
38 | } | |
|
|
39 | ||
|
|
40 | #define ARGC() argc_ | |
|
|
41 | ||
|
|
42 | #define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX)) | |
|
|
43 | ||
|
|
44 | #define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ | |
|
|
45 | ((x), abort(), (char *)0) :\ | |
|
|
46 | (brk_ = 1, (argv[0][1] != '\0')?\ | |
|
|
47 | (&argv[0][1]) :\ | |
|
|
48 | (argc--, argv++, argv[0]))) | |
|
|
49 | ||
|
|
50 | #define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ | |
|
|
51 | (char *)0 :\ | |
|
|
52 | (brk_ = 1, (argv[0][1] != '\0')?\ | |
|
|
53 | (&argv[0][1]) :\ | |
|
|
54 | (argc--, argv++, argv[0]))) | |
|
|
55 | ||
|
|
56 | #define LNGARG() &argv[0][0] | |
|
|
57 | ||
|
|
58 | #endif | |
| @@ -0,0 +1,181 | |||
|
|
1 | <?xml version="1.0" encoding="utf-8"?> | |
|
|
2 | <!-- | |
|
|
3 | This is largely ripped from somebar's ipc patchset; just with some personal modifications. | |
|
|
4 | I would probably just submit raphi's patchset but I don't think that would be polite. | |
|
|
5 | --> | |
|
|
6 | <protocol name="dwl_ipc_unstable_v2"> | |
|
|
7 | <description summary="inter-proccess-communication about dwl's state"> | |
|
|
8 | This protocol allows clients to update and get updates from dwl. | |
|
|
9 | ||
|
|
10 | Warning! The protocol described in this file is experimental and | |
|
|
11 | backward incompatible changes may be made. Backward compatible | |
|
|
12 | changes may be added together with the corresponding interface | |
|
|
13 | version bump. | |
|
|
14 | Backward incompatible changes are done by bumping the version | |
|
|
15 | number in the protocol and interface names and resetting the | |
|
|
16 | interface version. Once the protocol is to be declared stable, | |
|
|
17 | the 'z' prefix and the version number in the protocol and | |
|
|
18 | interface names are removed and the interface version number is | |
|
|
19 | reset. | |
|
|
20 | </description> | |
|
|
21 | ||
|
|
22 | <interface name="zdwl_ipc_manager_v2" version="2"> | |
|
|
23 | <description summary="manage dwl state"> | |
|
|
24 | This interface is exposed as a global in wl_registry. | |
|
|
25 | ||
|
|
26 | Clients can use this interface to get a dwl_ipc_output. | |
|
|
27 | After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events. | |
|
|
28 | The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client. | |
|
|
29 | </description> | |
|
|
30 | ||
|
|
31 | <request name="release" type="destructor"> | |
|
|
32 | <description summary="release dwl_ipc_manager"> | |
|
|
33 | Indicates that the client will not the dwl_ipc_manager object anymore. | |
|
|
34 | Objects created through this instance are not affected. | |
|
|
35 | </description> | |
|
|
36 | </request> | |
|
|
37 | ||
|
|
38 | <request name="get_output"> | |
|
|
39 | <description summary="get a dwl_ipc_outout for a wl_output"> | |
|
|
40 | Get a dwl_ipc_outout for the specified wl_output. | |
|
|
41 | </description> | |
|
|
42 | <arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/> | |
|
|
43 | <arg name="output" type="object" interface="wl_output"/> | |
|
|
44 | </request> | |
|
|
45 | ||
|
|
46 | <event name="tags"> | |
|
|
47 | <description summary="Announces tag amount"> | |
|
|
48 | This event is sent after binding. | |
|
|
49 | A roundtrip after binding guarantees the client recieved all tags. | |
|
|
50 | </description> | |
|
|
51 | <arg name="amount" type="uint"/> | |
|
|
52 | </event> | |
|
|
53 | ||
|
|
54 | <event name="layout"> | |
|
|
55 | <description summary="Announces a layout"> | |
|
|
56 | This event is sent after binding. | |
|
|
57 | A roundtrip after binding guarantees the client recieved all layouts. | |
|
|
58 | </description> | |
|
|
59 | <arg name="name" type="string"/> | |
|
|
60 | </event> | |
|
|
61 | </interface> | |
|
|
62 | ||
|
|
63 | <interface name="zdwl_ipc_output_v2" version="2"> | |
|
|
64 | <description summary="control dwl output"> | |
|
|
65 | Observe and control a dwl output. | |
|
|
66 | ||
|
|
67 | Events are double-buffered: | |
|
|
68 | Clients should cache events and redraw when a dwl_ipc_output.frame event is sent. | |
|
|
69 | ||
|
|
70 | Request are not double-buffered: | |
|
|
71 | The compositor will update immediately upon request. | |
|
|
72 | </description> | |
|
|
73 | ||
|
|
74 | <enum name="tag_state"> | |
|
|
75 | <entry name="none" value="0" summary="no state"/> | |
|
|
76 | <entry name="active" value="1" summary="tag is active"/> | |
|
|
77 | <entry name="urgent" value="2" summary="tag has at least one urgent client"/> | |
|
|
78 | </enum> | |
|
|
79 | ||
|
|
80 | <request name="release" type="destructor"> | |
|
|
81 | <description summary="release dwl_ipc_outout"> | |
|
|
82 | Indicates to that the client no longer needs this dwl_ipc_output. | |
|
|
83 | </description> | |
|
|
84 | </request> | |
|
|
85 | ||
|
|
86 | <event name="toggle_visibility"> | |
|
|
87 | <description summary="Toggle client visibilty"> | |
|
|
88 | Indicates the client should hide or show themselves. | |
|
|
89 | If the client is visible then hide, if hidden then show. | |
|
|
90 | </description> | |
|
|
91 | </event> | |
|
|
92 | ||
|
|
93 | <event name="active"> | |
|
|
94 | <description summary="Update the selected output."> | |
|
|
95 | Indicates if the output is active. Zero is invalid, nonzero is valid. | |
|
|
96 | </description> | |
|
|
97 | <arg name="active" type="uint"/> | |
|
|
98 | </event> | |
|
|
99 | ||
|
|
100 | <event name="tag"> | |
|
|
101 | <description summary="Update the state of a tag."> | |
|
|
102 | Indicates that a tag has been updated. | |
|
|
103 | </description> | |
|
|
104 | <arg name="tag" type="uint" summary="Index of the tag"/> | |
|
|
105 | <arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/> | |
|
|
106 | <arg name="clients" type="uint" summary="The number of clients in the tag."/> | |
|
|
107 | <arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/> | |
|
|
108 | </event> | |
|
|
109 | ||
|
|
110 | <event name="layout"> | |
|
|
111 | <description summary="Update the layout."> | |
|
|
112 | Indicates a new layout is selected. | |
|
|
113 | </description> | |
|
|
114 | <arg name="layout" type="uint" summary="Index of the layout."/> | |
|
|
115 | </event> | |
|
|
116 | ||
|
|
117 | <event name="title"> | |
|
|
118 | <description summary="Update the title."> | |
|
|
119 | Indicates the title has changed. | |
|
|
120 | </description> | |
|
|
121 | <arg name="title" type="string" summary="The new title name."/> | |
|
|
122 | </event> | |
|
|
123 | ||
|
|
124 | <event name="appid" since="1"> | |
|
|
125 | <description summary="Update the appid."> | |
|
|
126 | Indicates the appid has changed. | |
|
|
127 | </description> | |
|
|
128 | <arg name="appid" type="string" summary="The new appid."/> | |
|
|
129 | </event> | |
|
|
130 | ||
|
|
131 | <event name="layout_symbol" since="1"> | |
|
|
132 | <description summary="Update the current layout symbol"> | |
|
|
133 | Indicates the layout has changed. Since layout symbols are dynamic. | |
|
|
134 | As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying. | |
|
|
135 | You can ignore the zdwl_ipc_output.layout event. | |
|
|
136 | </description> | |
|
|
137 | <arg name="layout" type="string" summary="The new layout"/> | |
|
|
138 | </event> | |
|
|
139 | ||
|
|
140 | <event name="frame"> | |
|
|
141 | <description summary="The update sequence is done."> | |
|
|
142 | Indicates that a sequence of status updates have finished and the client should redraw. | |
|
|
143 | </description> | |
|
|
144 | </event> | |
|
|
145 | ||
|
|
146 | <request name="set_tags"> | |
|
|
147 | <description summary="Set the active tags of this output"/> | |
|
|
148 | <arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/> | |
|
|
149 | <arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/> | |
|
|
150 | </request> | |
|
|
151 | ||
|
|
152 | <request name="set_client_tags"> | |
|
|
153 | <description summary="Set the tags of the focused client."> | |
|
|
154 | The tags are updated as follows: | |
|
|
155 | new_tags = (current_tags AND and_tags) XOR xor_tags | |
|
|
156 | </description> | |
|
|
157 | <arg name="and_tags" type="uint"/> | |
|
|
158 | <arg name="xor_tags" type="uint"/> | |
|
|
159 | </request> | |
|
|
160 | ||
|
|
161 | <request name="set_layout"> | |
|
|
162 | <description summary="Set the layout of this output"/> | |
|
|
163 | <arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/> | |
|
|
164 | </request> | |
|
|
165 | ||
|
|
166 | <!-- Version 2 --> | |
|
|
167 | <event name="fullscreen" since="2"> | |
|
|
168 | <description summary="Update fullscreen status"> | |
|
|
169 | Indicates if the selected client on this output is fullscreen. | |
|
|
170 | </description> | |
|
|
171 | <arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/> | |
|
|
172 | </event> | |
|
|
173 | ||
|
|
174 | <event name="floating" since="2"> | |
|
|
175 | <description summary="Update the floating status"> | |
|
|
176 | Indicates if the selected client on this output is floating. | |
|
|
177 | </description> | |
|
|
178 | <arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/> | |
|
|
179 | </event> | |
|
|
180 | </interface> | |
|
|
181 | </protocol> | |
| This diff has been collapsed as it changes many lines, (516 lines changed) Show them Hide them | |||
| @@ -0,0 +1,516 | |||
|
|
1 | #define _GNU_SOURCE | |
|
|
2 | #include "arg.h" | |
|
|
3 | #include <poll.h> | |
|
|
4 | #include <stdio.h> | |
|
|
5 | #include <stdlib.h> | |
|
|
6 | #include <string.h> | |
|
|
7 | #include <sys/socket.h> | |
|
|
8 | #include <wayland-client.h> | |
|
|
9 | #include <wayland-util.h> | |
|
|
10 | #include "dwl-ipc-unstable-v2-protocol.h" | |
|
|
11 | ||
|
|
12 | #define die(fmt, ...) do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); } while (0) | |
|
|
13 | ||
|
|
14 | char *argv0; | |
|
|
15 | ||
|
|
16 | static enum { | |
|
|
17 | NONE = 0, | |
|
|
18 | SET = 1<<0, | |
|
|
19 | GET = 1<<1, | |
|
|
20 | WATCH = 1<<2 | GET, | |
|
|
21 | } mode = NONE; | |
|
|
22 | ||
|
|
23 | static int Oflag; | |
|
|
24 | static int Tflag; | |
|
|
25 | static int Lflag; | |
|
|
26 | static int Pflag; | |
|
|
27 | static int Fflag; | |
|
|
28 | static int oflag; | |
|
|
29 | static int tflag; | |
|
|
30 | static int lflag; | |
|
|
31 | static int cflag; | |
|
|
32 | static int vflag; | |
|
|
33 | static int mflag; | |
|
|
34 | static int fflag; | |
|
|
35 | ||
|
|
36 | static uint32_t occ, seltags, sel, urg; | |
|
|
37 | ||
|
|
38 | static char *output_name; | |
|
|
39 | static char *focused_output; | |
|
|
40 | static uint32_t tagcount; | |
|
|
41 | static char *tagset; | |
|
|
42 | static char *layout_name; | |
|
|
43 | static size_t layoutcount, layout_idx; | |
|
|
44 | static char *client_tags; | |
|
|
45 | ||
|
|
46 | struct output { | |
|
|
47 | char *output_name; | |
|
|
48 | uint32_t name; | |
|
|
49 | }; | |
|
|
50 | static size_t outputs_buflen = 4; | |
|
|
51 | static struct output *outputs; | |
|
|
52 | static size_t outputcount; | |
|
|
53 | ||
|
|
54 | static struct wl_display *display; | |
|
|
55 | static struct wl_registry *registry; | |
|
|
56 | static struct zdwl_ipc_manager_v2 *dwl_ipc_manager; | |
|
|
57 | ||
|
|
58 | static void | |
|
|
59 | dwl_ipc_tags(void *data, struct zdwl_ipc_manager_v2 *dwl_ipc_manager, uint32_t count) | |
|
|
60 | { | |
|
|
61 | tagcount = count; | |
|
|
62 | if (Tflag && mode & GET) printf("%d\n", tagcount); | |
|
|
63 | } | |
|
|
64 | ||
|
|
65 | static void | |
|
|
66 | dwl_ipc_layout(void *data, struct zdwl_ipc_manager_v2 *dwl_ipc_manager, const char *name) | |
|
|
67 | { | |
|
|
68 | if (lflag && mode & SET && strcmp(layout_name, name) == 0) | |
|
|
69 | layout_idx = layoutcount; | |
|
|
70 | if (Lflag && mode & GET) printf("%s\n", name); | |
|
|
71 | layoutcount++; | |
|
|
72 | } | |
|
|
73 | ||
|
|
74 | static const struct zdwl_ipc_manager_v2_listener dwl_ipc_listener = { | |
|
|
75 | .tags = dwl_ipc_tags, | |
|
|
76 | .layout = dwl_ipc_layout | |
|
|
77 | }; | |
|
|
78 | ||
|
|
79 | static void | |
|
|
80 | dwl_ipc_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output) | |
|
|
81 | { | |
|
|
82 | if (!vflag) return; | |
|
|
83 | char *oname = data; | |
|
|
84 | if (oname) printf("%s ", oname); | |
|
|
85 | printf("toggle\n"); | |
|
|
86 | } | |
|
|
87 | ||
|
|
88 | static void | |
|
|
89 | dwl_ipc_output_active(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, | |
|
|
90 | uint32_t active) | |
|
|
91 | { | |
|
|
92 | if (active && (!output_name || !*output_name)) | |
|
|
93 | output_name = strdup(data); | |
|
|
94 | if (active) { | |
|
|
95 | free(focused_output); | |
|
|
96 | focused_output = data ? strdup(data) : NULL; | |
|
|
97 | } | |
|
|
98 | if (!oflag) return; | |
|
|
99 | char *oname = data; | |
|
|
100 | if (oname) printf("%s ", oname); | |
|
|
101 | printf("selmon %u\n", !!active); | |
|
|
102 | } | |
|
|
103 | ||
|
|
104 | static void | |
|
|
105 | dwl_ipc_output_tag(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, | |
|
|
106 | uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) | |
|
|
107 | { | |
|
|
108 | if (!tflag) return; | |
|
|
109 | if (state != ZDWL_IPC_OUTPUT_V2_TAG_STATE_NONE) seltags |= 1<<tag; | |
|
|
110 | if (state == ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE) urg |= 1<<tag; | |
|
|
111 | if (clients > 0) occ |= 1<<tag; | |
|
|
112 | if (!(mode & GET)) return; | |
|
|
113 | if (data) printf("%s ", (char *)data); | |
|
|
114 | printf("tag %u %u %u %u\n", tag, state, clients, focused); | |
|
|
115 | } | |
|
|
116 | ||
|
|
117 | static void | |
|
|
118 | dwl_ipc_output_layout(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, | |
|
|
119 | uint32_t layout) | |
|
|
120 | { | |
|
|
121 | } | |
|
|
122 | ||
|
|
123 | static void | |
|
|
124 | dwl_ipc_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, | |
|
|
125 | const char *layout) | |
|
|
126 | { | |
|
|
127 | if (!(lflag && mode & GET)) return; | |
|
|
128 | if (data) printf("%s ", (char *)data); | |
|
|
129 | printf("layout %s\n", layout); | |
|
|
130 | } | |
|
|
131 | ||
|
|
132 | static void | |
|
|
133 | dwl_ipc_output_title(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, | |
|
|
134 | const char *title) | |
|
|
135 | { | |
|
|
136 | if (!(cflag && mode & GET)) return; | |
|
|
137 | if (data) printf("%s ", (char *)data); | |
|
|
138 | printf("title %s\n", title); | |
|
|
139 | } | |
|
|
140 | ||
|
|
141 | static void | |
|
|
142 | dwl_ipc_output_appid(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, | |
|
|
143 | const char *appid) | |
|
|
144 | { | |
|
|
145 | if (!(cflag && mode & GET)) return; | |
|
|
146 | if (data) printf("%s ", (char *)data); | |
|
|
147 | printf("appid %s\n", appid); | |
|
|
148 | } | |
|
|
149 | ||
|
|
150 | static void | |
|
|
151 | dwl_ipc_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, | |
|
|
152 | uint32_t is_fullscreen) | |
|
|
153 | { | |
|
|
154 | if (!mflag) return; | |
|
|
155 | if (data) printf("%s ", (char *)data); | |
|
|
156 | printf("fullscreen %u\n", is_fullscreen); | |
|
|
157 | } | |
|
|
158 | ||
|
|
159 | static void | |
|
|
160 | dwl_ipc_output_floating(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output, | |
|
|
161 | uint32_t is_floating) | |
|
|
162 | { | |
|
|
163 | if (!fflag) return; | |
|
|
164 | if (data) printf("%s ", (char *)data); | |
|
|
165 | printf("floating %u\n", is_floating); | |
|
|
166 | } | |
|
|
167 | ||
|
|
168 | static void | |
|
|
169 | dwl_ipc_output_frame(void *data, struct zdwl_ipc_output_v2 *dwl_ipc_output) | |
|
|
170 | { | |
|
|
171 | if (mode & SET) { | |
|
|
172 | if (data && !(output_name && strcmp(output_name, (char *)data) == 0)) return; | |
|
|
173 | if (lflag) { | |
|
|
174 | if (layout_idx == 0) { | |
|
|
175 | for (char *c = layout_name; *c; c++) { | |
|
|
176 | if (*c < '0' || *c > '9') | |
|
|
177 | die("bad layout %s", layout_name); | |
|
|
178 | layout_idx = *c-'0' + layout_idx*10; | |
|
|
179 | } | |
|
|
180 | } | |
|
|
181 | if (layout_idx >= layoutcount) | |
|
|
182 | die("bad layout %s", layout_name); | |
|
|
183 | zdwl_ipc_output_v2_set_layout(dwl_ipc_output, layout_idx); | |
|
|
184 | } | |
|
|
185 | if (tflag) { | |
|
|
186 | uint32_t mask = seltags; | |
|
|
187 | char *t = tagset; | |
|
|
188 | uint32_t i = 0; | |
|
|
189 | int toggle = 1; | |
|
|
190 | ||
|
|
191 | if (*t == '!') { | |
|
|
192 | toggle = 0; | |
|
|
193 | t++; | |
|
|
194 | } | |
|
|
195 | ||
|
|
196 | for (; *t && *t >= '0' && *t <= '9'; t++) | |
|
|
197 | i = *t-'0' + i*10; | |
|
|
198 | ||
|
|
199 | if (toggle && !*t) mask = 1<<i; | |
|
|
200 | ||
|
|
201 | for (; *t; t++, i++) { | |
|
|
202 | switch (*t) { | |
|
|
203 | case '-': | |
|
|
204 | mask &= ~(1<<i); | |
|
|
205 | break; | |
|
|
206 | case '+': | |
|
|
207 | mask |= 1<<i; | |
|
|
208 | break; | |
|
|
209 | case '^': | |
|
|
210 | mask ^= 1<<i; | |
|
|
211 | break; | |
|
|
212 | } | |
|
|
213 | } | |
|
|
214 | ||
|
|
215 | if (i > tagcount) die("bad tagset %s", tagset); | |
|
|
216 | ||
|
|
217 | zdwl_ipc_output_v2_set_tags(dwl_ipc_output, mask, toggle); | |
|
|
218 | } | |
|
|
219 | if (cflag) { | |
|
|
220 | uint32_t and = ~0, xor = 0; | |
|
|
221 | char *t = client_tags; | |
|
|
222 | uint32_t i = 0; | |
|
|
223 | ||
|
|
224 | for (; *t && *t >= '0' && *t <= '9'; t++) | |
|
|
225 | i = *t-'0' + i*10; | |
|
|
226 | ||
|
|
227 | if (!*t) { | |
|
|
228 | and = 0; | |
|
|
229 | xor = 1<<i; | |
|
|
230 | } | |
|
|
231 | ||
|
|
232 | for (; *t; t++, i++) { | |
|
|
233 | switch (*t) { | |
|
|
234 | case '-': | |
|
|
235 | and &= ~(1<<i); | |
|
|
236 | break; | |
|
|
237 | case '+': | |
|
|
238 | and &= ~(1<<i); | |
|
|
239 | xor |= 1<<i; | |
|
|
240 | break; | |
|
|
241 | case '^': | |
|
|
242 | xor |= 1<<i; | |
|
|
243 | break; | |
|
|
244 | } | |
|
|
245 | } | |
|
|
246 | if (i > tagcount) die("bad client tagset %s", client_tags); | |
|
|
247 | ||
|
|
248 | zdwl_ipc_output_v2_set_client_tags(dwl_ipc_output, and, xor); | |
|
|
249 | } | |
|
|
250 | wl_display_flush(display); | |
|
|
251 | exit(0); | |
|
|
252 | } else { | |
|
|
253 | if (Fflag && mode == WATCH && focused_output) | |
|
|
254 | printf("focusmon %s\n", focused_output); | |
|
|
255 | if (tflag) { | |
|
|
256 | if (data) printf("%s ", (char *)data); | |
|
|
257 | printf("tags %u %u %u %u\n", occ, seltags, sel, urg); | |
|
|
258 | occ = seltags = sel = urg = 0; | |
|
|
259 | } | |
|
|
260 | } | |
|
|
261 | fflush(stdout); | |
|
|
262 | } | |
|
|
263 | ||
|
|
264 | static const struct zdwl_ipc_output_v2_listener dwl_ipc_output_listener = { | |
|
|
265 | .toggle_visibility = dwl_ipc_output_toggle_visibility, | |
|
|
266 | .active = dwl_ipc_output_active, | |
|
|
267 | .tag = dwl_ipc_output_tag, | |
|
|
268 | .layout = dwl_ipc_output_layout, | |
|
|
269 | .title = dwl_ipc_output_title, | |
|
|
270 | .appid = dwl_ipc_output_appid, | |
|
|
271 | .layout_symbol = dwl_ipc_output_layout_symbol, | |
|
|
272 | .fullscreen = dwl_ipc_output_fullscreen, | |
|
|
273 | .floating = dwl_ipc_output_floating, | |
|
|
274 | .frame = dwl_ipc_output_frame, | |
|
|
275 | }; | |
|
|
276 | ||
|
|
277 | static void | |
|
|
278 | wl_output_name(void *data, struct wl_output *output, const char *name) | |
|
|
279 | { | |
|
|
280 | if (outputs) { | |
|
|
281 | struct output *o = (struct output *)data; | |
|
|
282 | o->output_name = strdup(name); | |
|
|
283 | printf("+ "); | |
|
|
284 | } | |
|
|
285 | if (Oflag) printf("%s\n", name); | |
|
|
286 | if (output_name && *output_name && strcmp(output_name, name) != 0) { | |
|
|
287 | wl_output_release(output); | |
|
|
288 | return; | |
|
|
289 | } | |
|
|
290 | if (dwl_ipc_manager) { | |
|
|
291 | struct zdwl_ipc_output_v2 *dwl_ipc_output = | |
|
|
292 | zdwl_ipc_manager_v2_get_output(dwl_ipc_manager, output); | |
|
|
293 | zdwl_ipc_output_v2_add_listener(dwl_ipc_output, &dwl_ipc_output_listener, | |
|
|
294 | output_name && *output_name ? NULL : strdup(name)); | |
|
|
295 | } | |
|
|
296 | } | |
|
|
297 | ||
|
|
298 | static void | |
|
|
299 | wl_output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t w, int32_t h, int32_t subpixel, const char *make, const char *model, int32_t transform) { | |
|
|
300 | } | |
|
|
301 | ||
|
|
302 | static void | |
|
|
303 | wl_output_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) | |
|
|
304 | { | |
|
|
305 | } | |
|
|
306 | ||
|
|
307 | static void | |
|
|
308 | wl_output_done(void *data, struct wl_output *wl_output) | |
|
|
309 | { | |
|
|
310 | } | |
|
|
311 | ||
|
|
312 | static void | |
|
|
313 | wl_output_scale(void *data, struct wl_output *wl_output, int32_t factor) | |
|
|
314 | { | |
|
|
315 | } | |
|
|
316 | ||
|
|
317 | static void | |
|
|
318 | wl_output_description(void *data, struct wl_output *output, const char *description) | |
|
|
319 | { | |
|
|
320 | } | |
|
|
321 | ||
|
|
322 | static const struct wl_output_listener output_listener = { | |
|
|
323 | .geometry = wl_output_geometry, | |
|
|
324 | .mode = wl_output_mode, | |
|
|
325 | .done = wl_output_done, | |
|
|
326 | .scale = wl_output_scale, | |
|
|
327 | .name = wl_output_name, | |
|
|
328 | .description = wl_output_description, | |
|
|
329 | }; | |
|
|
330 | ||
|
|
331 | static void | |
|
|
332 | global_add(void *data, struct wl_registry *wl_registry, | |
|
|
333 | uint32_t name, const char *interface, uint32_t version) | |
|
|
334 | { | |
|
|
335 | if (strcmp(interface, wl_output_interface.name) == 0) { | |
|
|
336 | struct wl_output *o = wl_registry_bind( | |
|
|
337 | wl_registry, name, &wl_output_interface, | |
|
|
338 | WL_OUTPUT_NAME_SINCE_VERSION); | |
|
|
339 | wl_output_add_listener(o, &output_listener, outputs ? &outputs[outputcount] : NULL); | |
|
|
340 | if (!outputs) return; | |
|
|
341 | if (outputcount >= outputs_buflen) { | |
|
|
342 | outputs_buflen *= 2; | |
|
|
343 | outputs = reallocarray(outputs, outputs_buflen, sizeof(struct output)); | |
|
|
344 | } | |
|
|
345 | outputs[outputcount].name = name; | |
|
|
346 | outputcount++; | |
|
|
347 | } else if (strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) { | |
|
|
348 | dwl_ipc_manager = wl_registry_bind(wl_registry, name, | |
|
|
349 | &zdwl_ipc_manager_v2_interface, version < 2 ? version : 2); | |
|
|
350 | zdwl_ipc_manager_v2_add_listener(dwl_ipc_manager, &dwl_ipc_listener, NULL); | |
|
|
351 | } | |
|
|
352 | } | |
|
|
353 | ||
|
|
354 | static void | |
|
|
355 | global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) | |
|
|
356 | { | |
|
|
357 | if (!outputs) return; | |
|
|
358 | for (size_t i = 0; i < outputcount; i++) { | |
|
|
359 | if (outputs[i].name == name) { | |
|
|
360 | printf("- %s\n", outputs[i].output_name); | |
|
|
361 | free(outputs[i].output_name); | |
|
|
362 | outputs[i] = outputs[--outputcount]; | |
|
|
363 | } | |
|
|
364 | } | |
|
|
365 | } | |
|
|
366 | ||
|
|
367 | static const struct wl_registry_listener registry_listener = { | |
|
|
368 | .global = global_add, | |
|
|
369 | .global_remove = global_remove, | |
|
|
370 | }; | |
|
|
371 | ||
|
|
372 | static void | |
|
|
373 | usage(int code) | |
|
|
374 | { | |
|
|
375 | fprintf(code ? stderr : stdout, | |
|
|
376 | "usage:" | |
|
|
377 | "\t%1$s [-OTLPF]\n" | |
|
|
378 | "\t%1$s [-o <output>] -s [-t <tags>] [-l <layout>] [-c <tags>]\n" | |
|
|
379 | "\t%1$s [-o <output>] (-g | -w) [-FOotlcvmf]\n", | |
|
|
380 | argv0); | |
|
|
381 | exit(code); | |
|
|
382 | } | |
|
|
383 | ||
|
|
384 | int | |
|
|
385 | main(int argc, char *argv[]) | |
|
|
386 | { | |
|
|
387 | ARGBEGIN { | |
|
|
388 | case '?': case 'h': | |
|
|
389 | usage(0); break; | |
|
|
390 | case 's': | |
|
|
391 | if (mode != NONE) usage(1); | |
|
|
392 | mode = SET; | |
|
|
393 | break; | |
|
|
394 | case 'g': | |
|
|
395 | if (mode != NONE) usage(1); | |
|
|
396 | mode = GET; | |
|
|
397 | break; | |
|
|
398 | case 'w': | |
|
|
399 | if (mode != NONE) usage(1); | |
|
|
400 | mode = WATCH; | |
|
|
401 | break; | |
|
|
402 | case 'o': | |
|
|
403 | if (mode & SET) | |
|
|
404 | output_name = EARGF(usage(1)); | |
|
|
405 | else if (mode & GET || !(output_name = ARGF())) | |
|
|
406 | oflag = 1; | |
|
|
407 | break; | |
|
|
408 | case 't': | |
|
|
409 | tflag = 1; | |
|
|
410 | if (mode & GET) break; | |
|
|
411 | mode = SET; | |
|
|
412 | tagset = EARGF(usage(1)); | |
|
|
413 | break; | |
|
|
414 | case 'l': | |
|
|
415 | lflag = 1; | |
|
|
416 | if (mode & GET) break; | |
|
|
417 | mode = SET; | |
|
|
418 | layout_name = EARGF(usage(1)); | |
|
|
419 | break; | |
|
|
420 | case 'c': | |
|
|
421 | cflag = 1; | |
|
|
422 | if (mode & GET) break; | |
|
|
423 | mode = SET; | |
|
|
424 | client_tags = EARGF(usage(1)); | |
|
|
425 | break; | |
|
|
426 | case 'O': | |
|
|
427 | Oflag = 1; | |
|
|
428 | if (mode & SET) usage(1); | |
|
|
429 | if (mode & WATCH) | |
|
|
430 | outputs = malloc(outputs_buflen * sizeof(struct output)); | |
|
|
431 | else | |
|
|
432 | mode = GET; | |
|
|
433 | break; | |
|
|
434 | case 'T': | |
|
|
435 | Tflag = 1; | |
|
|
436 | if (mode && mode != GET) usage(1); | |
|
|
437 | mode = GET; | |
|
|
438 | break; | |
|
|
439 | case 'L': | |
|
|
440 | Lflag = 1; | |
|
|
441 | if (mode && mode != GET) usage(1); | |
|
|
442 | mode = GET; | |
|
|
443 | break; | |
|
|
444 | case 'P': | |
|
|
445 | Pflag = 1; | |
|
|
446 | if (mode && mode != GET) usage(1); | |
|
|
447 | mode = GET; | |
|
|
448 | break; | |
|
|
449 | case 'F': | |
|
|
450 | Fflag = 1; | |
|
|
451 | if (mode && mode != GET) usage(1); | |
|
|
452 | mode = GET; | |
|
|
453 | break; | |
|
|
454 | case 'v': | |
|
|
455 | vflag = 1; | |
|
|
456 | if (mode & SET) usage(1); | |
|
|
457 | mode |= GET; | |
|
|
458 | break; | |
|
|
459 | case 'm': | |
|
|
460 | mflag = 1; | |
|
|
461 | if (mode & SET) usage(1); | |
|
|
462 | mode |= GET; | |
|
|
463 | break; | |
|
|
464 | case 'f': | |
|
|
465 | fflag = 1; | |
|
|
466 | if (mode & SET) usage(1); | |
|
|
467 | mode |= GET; | |
|
|
468 | break; | |
|
|
469 | default: | |
|
|
470 | fprintf(stderr, "%s: bad option: -%c\n", argv0, ARGC()); | |
|
|
471 | usage(1); | |
|
|
472 | } ARGEND | |
|
|
473 | if (argc > 0) { | |
|
|
474 | fprintf(stderr, "%s: bad args:", argv0); | |
|
|
475 | for (; *argv; argv++) | |
|
|
476 | fprintf(stderr, " %s", argv[0]); | |
|
|
477 | fprintf(stderr, "\n"); | |
|
|
478 | usage(1); | |
|
|
479 | } | |
|
|
480 | if (mode == NONE) usage(1); | |
|
|
481 | if (mode & GET && !(oflag || tflag || lflag || Oflag || Tflag || Lflag || Pflag || Fflag || cflag || vflag || mflag || fflag)) | |
|
|
482 | oflag = tflag = lflag = cflag = vflag = mflag = fflag = Fflag = 1; | |
|
|
483 | ||
|
|
484 | display = wl_display_connect(NULL); | |
|
|
485 | if (!display) die("bad display"); | |
|
|
486 | ||
|
|
487 | if (Pflag) { | |
|
|
488 | int fd = wl_display_get_fd(display); | |
|
|
489 | struct ucred ucred; | |
|
|
490 | socklen_t len = sizeof(struct ucred); | |
|
|
491 | if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) | |
|
|
492 | die("bad getsockopt"); | |
|
|
493 | printf("%d\n", ucred.pid); | |
|
|
494 | } | |
|
|
495 | ||
|
|
496 | registry = wl_display_get_registry(display); | |
|
|
497 | if (!registry) die("bad registry"); | |
|
|
498 | ||
|
|
499 | wl_registry_add_listener(registry, ®istry_listener, NULL); | |
|
|
500 | ||
|
|
501 | wl_display_dispatch(display); | |
|
|
502 | wl_display_roundtrip(display); | |
|
|
503 | ||
|
|
504 | if (!dwl_ipc_manager && (mode & SET || tflag || lflag || Tflag || Lflag || cflag || vflag || mflag || fflag)) | |
|
|
505 | die("bad dwl-ipc protocol"); | |
|
|
506 | ||
|
|
507 | wl_display_roundtrip(display); | |
|
|
508 | ||
|
|
509 | if (Fflag && !(mode == WATCH) && focused_output) | |
|
|
510 | printf("focusmon %s\n", focused_output); | |
|
|
511 | ||
|
|
512 | if (mode == WATCH) | |
|
|
513 | while (wl_display_dispatch(display) != -1); | |
|
|
514 | ||
|
|
515 | return 0; | |
|
|
516 | } | |
|
|
1 | NO CONTENT: new file 100644 | |
| The requested commit or file is too big and content was truncated. Show full diff | |||
| @@ -0,0 +1,51 | |||
|
|
1 | /* See LICENSE.dwm file for copyright and license details. */ | |
|
|
2 | #include <stdarg.h> | |
|
|
3 | #include <stdio.h> | |
|
|
4 | #include <stdlib.h> | |
|
|
5 | #include <string.h> | |
|
|
6 | #include <fcntl.h> | |
|
|
7 | ||
|
|
8 | #include "util.h" | |
|
|
9 | ||
|
|
10 | void | |
|
|
11 | die(const char *fmt, ...) { | |
|
|
12 | va_list ap; | |
|
|
13 | ||
|
|
14 | va_start(ap, fmt); | |
|
|
15 | vfprintf(stderr, fmt, ap); | |
|
|
16 | va_end(ap); | |
|
|
17 | ||
|
|
18 | if (fmt[0] && fmt[strlen(fmt)-1] == ':') { | |
|
|
19 | fputc(' ', stderr); | |
|
|
20 | perror(NULL); | |
|
|
21 | } else { | |
|
|
22 | fputc('\n', stderr); | |
|
|
23 | } | |
|
|
24 | ||
|
|
25 | exit(1); | |
|
|
26 | } | |
|
|
27 | ||
|
|
28 | void * | |
|
|
29 | ecalloc(size_t nmemb, size_t size) | |
|
|
30 | { | |
|
|
31 | void *p; | |
|
|
32 | ||
|
|
33 | if (!(p = calloc(nmemb, size))) | |
|
|
34 | die("calloc:"); | |
|
|
35 | return p; | |
|
|
36 | } | |
|
|
37 | ||
|
|
38 | int | |
|
|
39 | fd_set_nonblock(int fd) { | |
|
|
40 | int flags = fcntl(fd, F_GETFL); | |
|
|
41 | if (flags < 0) { | |
|
|
42 | perror("fcntl(F_GETFL):"); | |
|
|
43 | return -1; | |
|
|
44 | } | |
|
|
45 | if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { | |
|
|
46 | perror("fcntl(F_SETFL):"); | |
|
|
47 | return -1; | |
|
|
48 | } | |
|
|
49 | ||
|
|
50 | return 0; | |
|
|
51 | } | |
| @@ -0,0 +1,5 | |||
|
|
1 | /* See LICENSE.dwm file for copyright and license details. */ | |
|
|
2 | ||
|
|
3 | void die(const char *fmt, ...); | |
|
|
4 | void *ecalloc(size_t nmemb, size_t size); | |
|
|
5 | int fd_set_nonblock(int fd); | |
| This diff has been collapsed as it changes many lines, (975 lines changed) Show them Hide them | |||
| @@ -0,0 +1,975 | |||
|
|
1 | #include "wlr_ext_workspace_v1.h" | |
|
|
2 | #include "ext-workspace-v1-protocol.h" | |
|
|
3 | #include <assert.h> | |
|
|
4 | #include <stdlib.h> | |
|
|
5 | #include <string.h> | |
|
|
6 | #include <wlr/types/wlr_output.h> | |
|
|
7 | ||
|
|
8 | #define EXT_WORKSPACE_V1_VERSION 1 | |
|
|
9 | ||
|
|
10 | struct wlr_ext_workspace_v1_group_output { | |
|
|
11 | struct wlr_output *output; | |
|
|
12 | struct wlr_ext_workspace_group_handle_v1 *group; | |
|
|
13 | struct wl_listener output_bind; | |
|
|
14 | struct wl_listener output_destroy; | |
|
|
15 | struct wl_list link; | |
|
|
16 | }; | |
|
|
17 | ||
|
|
18 | // These structs wrap wl_resource of each interface to access the request queue | |
|
|
19 | // (wlr_ext_workspace_manager_v1_resource.requests) assigned per manager | |
|
|
20 | // resource | |
|
|
21 | ||
|
|
22 | struct wlr_ext_workspace_manager_v1_resource { | |
|
|
23 | struct wl_resource *resource; | |
|
|
24 | struct wlr_ext_workspace_manager_v1 *manager; | |
|
|
25 | struct wl_list requests; // wlr_ext_workspace_v1_request.link | |
|
|
26 | struct wl_list workspace_resources; // wlr_ext_workspace_v1_resource.link | |
|
|
27 | struct wl_list group_resources; // wlr_ext_workspace_group_v1_resource.link | |
|
|
28 | struct wl_list link; // wlr_ext_workspace_manager_v1.resources | |
|
|
29 | }; | |
|
|
30 | ||
|
|
31 | struct wlr_ext_workspace_group_v1_resource { | |
|
|
32 | struct wl_resource *resource; | |
|
|
33 | struct wlr_ext_workspace_group_handle_v1 *group; | |
|
|
34 | struct wlr_ext_workspace_manager_v1_resource *manager; | |
|
|
35 | struct wl_list link; // wlr_ext_workspace_group_v1.resources | |
|
|
36 | struct wl_list | |
|
|
37 | manager_resource_link; // wlr_ext_workspace_manager_v1_resource.group_resources | |
|
|
38 | }; | |
|
|
39 | ||
|
|
40 | struct wlr_ext_workspace_v1_resource { | |
|
|
41 | struct wl_resource *resource; | |
|
|
42 | struct wlr_ext_workspace_handle_v1 *workspace; | |
|
|
43 | struct wlr_ext_workspace_manager_v1_resource *manager; | |
|
|
44 | struct wl_list link; // wlr_ext_workspace_v1.resources | |
|
|
45 | struct wl_list | |
|
|
46 | manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources | |
|
|
47 | }; | |
|
|
48 | ||
|
|
49 | static const struct ext_workspace_group_handle_v1_interface group_impl; | |
|
|
50 | ||
|
|
51 | static struct wlr_ext_workspace_group_v1_resource * | |
|
|
52 | group_resource_from_resource(struct wl_resource *resource) { | |
|
|
53 | assert(wl_resource_instance_of( | |
|
|
54 | resource, &ext_workspace_group_handle_v1_interface, &group_impl)); | |
|
|
55 | return wl_resource_get_user_data(resource); | |
|
|
56 | } | |
|
|
57 | ||
|
|
58 | static const struct ext_workspace_handle_v1_interface workspace_impl; | |
|
|
59 | ||
|
|
60 | static struct wlr_ext_workspace_v1_resource * | |
|
|
61 | workspace_resource_from_resource(struct wl_resource *resource) { | |
|
|
62 | assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface, | |
|
|
63 | &workspace_impl)); | |
|
|
64 | return wl_resource_get_user_data(resource); | |
|
|
65 | } | |
|
|
66 | ||
|
|
67 | static const struct ext_workspace_manager_v1_interface manager_impl; | |
|
|
68 | ||
|
|
69 | static struct wlr_ext_workspace_manager_v1_resource * | |
|
|
70 | manager_resource_from_resource(struct wl_resource *resource) { | |
|
|
71 | assert(wl_resource_instance_of( | |
|
|
72 | resource, &ext_workspace_manager_v1_interface, &manager_impl)); | |
|
|
73 | return wl_resource_get_user_data(resource); | |
|
|
74 | } | |
|
|
75 | ||
|
|
76 | static void workspace_handle_destroy(struct wl_client *client, | |
|
|
77 | struct wl_resource *resource) { | |
|
|
78 | wl_resource_destroy(resource); | |
|
|
79 | } | |
|
|
80 | ||
|
|
81 | static void workspace_handle_activate(struct wl_client *client, | |
|
|
82 | struct wl_resource *workspace_resource) { | |
|
|
83 | struct wlr_ext_workspace_v1_resource *workspace_res = | |
|
|
84 | workspace_resource_from_resource(workspace_resource); | |
|
|
85 | if (!workspace_res) { | |
|
|
86 | return; | |
|
|
87 | } | |
|
|
88 | ||
|
|
89 | struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req)); | |
|
|
90 | if (!req) { | |
|
|
91 | wl_resource_post_no_memory(workspace_resource); | |
|
|
92 | return; | |
|
|
93 | } | |
|
|
94 | req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE; | |
|
|
95 | req->activate.workspace = workspace_res->workspace; | |
|
|
96 | wl_list_insert(workspace_res->manager->requests.prev, &req->link); | |
|
|
97 | } | |
|
|
98 | ||
|
|
99 | static void | |
|
|
100 | workspace_handle_deactivate(struct wl_client *client, | |
|
|
101 | struct wl_resource *workspace_resource) { | |
|
|
102 | struct wlr_ext_workspace_v1_resource *workspace_res = | |
|
|
103 | workspace_resource_from_resource(workspace_resource); | |
|
|
104 | if (!workspace_res) { | |
|
|
105 | return; | |
|
|
106 | } | |
|
|
107 | ||
|
|
108 | struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req)); | |
|
|
109 | if (!req) { | |
|
|
110 | wl_resource_post_no_memory(workspace_resource); | |
|
|
111 | return; | |
|
|
112 | } | |
|
|
113 | req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE; | |
|
|
114 | req->deactivate.workspace = workspace_res->workspace; | |
|
|
115 | wl_list_insert(workspace_res->manager->requests.prev, &req->link); | |
|
|
116 | } | |
|
|
117 | ||
|
|
118 | static void workspace_handle_assign(struct wl_client *client, | |
|
|
119 | struct wl_resource *workspace_resource, | |
|
|
120 | struct wl_resource *group_resource) { | |
|
|
121 | struct wlr_ext_workspace_v1_resource *workspace_res = | |
|
|
122 | workspace_resource_from_resource(workspace_resource); | |
|
|
123 | struct wlr_ext_workspace_group_v1_resource *group_res = | |
|
|
124 | group_resource_from_resource(group_resource); | |
|
|
125 | if (!workspace_res || !group_res) { | |
|
|
126 | return; | |
|
|
127 | } | |
|
|
128 | ||
|
|
129 | struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req)); | |
|
|
130 | if (!req) { | |
|
|
131 | wl_resource_post_no_memory(workspace_resource); | |
|
|
132 | return; | |
|
|
133 | } | |
|
|
134 | req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN; | |
|
|
135 | req->assign.group = group_res->group; | |
|
|
136 | req->assign.workspace = workspace_res->workspace; | |
|
|
137 | wl_list_insert(workspace_res->manager->requests.prev, &req->link); | |
|
|
138 | } | |
|
|
139 | ||
|
|
140 | static void workspace_handle_remove(struct wl_client *client, | |
|
|
141 | struct wl_resource *workspace_resource) { | |
|
|
142 | struct wlr_ext_workspace_v1_resource *workspace_res = | |
|
|
143 | workspace_resource_from_resource(workspace_resource); | |
|
|
144 | if (!workspace_res) { | |
|
|
145 | return; | |
|
|
146 | } | |
|
|
147 | ||
|
|
148 | struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req)); | |
|
|
149 | if (!req) { | |
|
|
150 | wl_resource_post_no_memory(workspace_resource); | |
|
|
151 | return; | |
|
|
152 | } | |
|
|
153 | req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE; | |
|
|
154 | req->remove.workspace = workspace_res->workspace; | |
|
|
155 | wl_list_insert(workspace_res->manager->requests.prev, &req->link); | |
|
|
156 | } | |
|
|
157 | ||
|
|
158 | static const struct ext_workspace_handle_v1_interface workspace_impl = { | |
|
|
159 | .destroy = workspace_handle_destroy, | |
|
|
160 | .activate = workspace_handle_activate, | |
|
|
161 | .deactivate = workspace_handle_deactivate, | |
|
|
162 | .assign = workspace_handle_assign, | |
|
|
163 | .remove = workspace_handle_remove, | |
|
|
164 | }; | |
|
|
165 | ||
|
|
166 | static void group_handle_create_workspace(struct wl_client *client, | |
|
|
167 | struct wl_resource *group_resource, | |
|
|
168 | const char *name) { | |
|
|
169 | struct wlr_ext_workspace_group_v1_resource *group_res = | |
|
|
170 | group_resource_from_resource(group_resource); | |
|
|
171 | if (!group_res) { | |
|
|
172 | return; | |
|
|
173 | } | |
|
|
174 | ||
|
|
175 | struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req)); | |
|
|
176 | if (!req) { | |
|
|
177 | wl_resource_post_no_memory(group_resource); | |
|
|
178 | return; | |
|
|
179 | } | |
|
|
180 | req->create_workspace.name = strdup(name); | |
|
|
181 | if (!req->create_workspace.name) { | |
|
|
182 | free(req); | |
|
|
183 | wl_resource_post_no_memory(group_resource); | |
|
|
184 | return; | |
|
|
185 | } | |
|
|
186 | req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE; | |
|
|
187 | req->create_workspace.group = group_res->group; | |
|
|
188 | wl_list_insert(group_res->manager->requests.prev, &req->link); | |
|
|
189 | } | |
|
|
190 | ||
|
|
191 | static void group_handle_destroy(struct wl_client *client, | |
|
|
192 | struct wl_resource *resource) { | |
|
|
193 | wl_resource_destroy(resource); | |
|
|
194 | } | |
|
|
195 | ||
|
|
196 | static const struct ext_workspace_group_handle_v1_interface group_impl = { | |
|
|
197 | .create_workspace = group_handle_create_workspace, | |
|
|
198 | .destroy = group_handle_destroy, | |
|
|
199 | }; | |
|
|
200 | ||
|
|
201 | static void destroy_workspace_resource( | |
|
|
202 | struct wlr_ext_workspace_v1_resource *workspace_res) { | |
|
|
203 | wl_list_remove(&workspace_res->link); | |
|
|
204 | wl_list_remove(&workspace_res->manager_resource_link); | |
|
|
205 | wl_resource_set_user_data(workspace_res->resource, NULL); | |
|
|
206 | free(workspace_res); | |
|
|
207 | } | |
|
|
208 | ||
|
|
209 | static void workspace_resource_destroy(struct wl_resource *resource) { | |
|
|
210 | struct wlr_ext_workspace_v1_resource *workspace_res = | |
|
|
211 | workspace_resource_from_resource(resource); | |
|
|
212 | if (workspace_res) { | |
|
|
213 | destroy_workspace_resource(workspace_res); | |
|
|
214 | } | |
|
|
215 | } | |
|
|
216 | ||
|
|
217 | static struct wlr_ext_workspace_v1_resource *create_workspace_resource( | |
|
|
218 | struct wlr_ext_workspace_handle_v1 *workspace, | |
|
|
219 | struct wlr_ext_workspace_manager_v1_resource *manager_res) { | |
|
|
220 | struct wlr_ext_workspace_v1_resource *workspace_res = | |
|
|
221 | calloc(1, sizeof(*workspace_res)); | |
|
|
222 | if (!workspace_res) { | |
|
|
223 | return NULL; | |
|
|
224 | } | |
|
|
225 | ||
|
|
226 | struct wl_client *client = wl_resource_get_client(manager_res->resource); | |
|
|
227 | workspace_res->resource = | |
|
|
228 | wl_resource_create(client, &ext_workspace_handle_v1_interface, | |
|
|
229 | wl_resource_get_version(manager_res->resource), 0); | |
|
|
230 | if (!workspace_res->resource) { | |
|
|
231 | free(workspace_res); | |
|
|
232 | return NULL; | |
|
|
233 | } | |
|
|
234 | wl_resource_set_implementation(workspace_res->resource, &workspace_impl, | |
|
|
235 | workspace_res, workspace_resource_destroy); | |
|
|
236 | ||
|
|
237 | workspace_res->workspace = workspace; | |
|
|
238 | workspace_res->manager = manager_res; | |
|
|
239 | wl_list_insert(&workspace->resources, &workspace_res->link); | |
|
|
240 | wl_list_insert(&manager_res->workspace_resources, | |
|
|
241 | &workspace_res->manager_resource_link); | |
|
|
242 | ||
|
|
243 | return workspace_res; | |
|
|
244 | } | |
|
|
245 | ||
|
|
246 | static void | |
|
|
247 | destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) { | |
|
|
248 | wl_list_remove(&group_res->link); | |
|
|
249 | wl_list_remove(&group_res->manager_resource_link); | |
|
|
250 | wl_resource_set_user_data(group_res->resource, NULL); | |
|
|
251 | free(group_res); | |
|
|
252 | } | |
|
|
253 | ||
|
|
254 | static void group_handle_resource_destroy(struct wl_resource *resource) { | |
|
|
255 | struct wlr_ext_workspace_group_v1_resource *group_res = | |
|
|
256 | group_resource_from_resource(resource); | |
|
|
257 | if (group_res) { | |
|
|
258 | destroy_group_resource(group_res); | |
|
|
259 | } | |
|
|
260 | } | |
|
|
261 | ||
|
|
262 | static struct wlr_ext_workspace_group_v1_resource *create_group_resource( | |
|
|
263 | struct wlr_ext_workspace_group_handle_v1 *group, | |
|
|
264 | struct wlr_ext_workspace_manager_v1_resource *manager_res) { | |
|
|
265 | struct wlr_ext_workspace_group_v1_resource *group_res = | |
|
|
266 | calloc(1, sizeof(*group_res)); | |
|
|
267 | if (!group_res) { | |
|
|
268 | return NULL; | |
|
|
269 | } | |
|
|
270 | ||
|
|
271 | struct wl_client *client = wl_resource_get_client(manager_res->resource); | |
|
|
272 | uint32_t version = wl_resource_get_version(manager_res->resource); | |
|
|
273 | group_res->resource = wl_resource_create( | |
|
|
274 | client, &ext_workspace_group_handle_v1_interface, version, 0); | |
|
|
275 | if (group_res->resource == NULL) { | |
|
|
276 | free(group_res); | |
|
|
277 | return NULL; | |
|
|
278 | } | |
|
|
279 | wl_resource_set_implementation(group_res->resource, &group_impl, group_res, | |
|
|
280 | group_handle_resource_destroy); | |
|
|
281 | ||
|
|
282 | group_res->group = group; | |
|
|
283 | group_res->manager = manager_res; | |
|
|
284 | wl_list_insert(&group->resources, &group_res->link); | |
|
|
285 | wl_list_insert(&manager_res->group_resources, | |
|
|
286 | &group_res->manager_resource_link); | |
|
|
287 | ||
|
|
288 | return group_res; | |
|
|
289 | } | |
|
|
290 | ||
|
|
291 | static void | |
|
|
292 | destroy_requests(struct wlr_ext_workspace_manager_v1_resource *manager_res) { | |
|
|
293 | struct wlr_ext_workspace_v1_request *req, *tmp; | |
|
|
294 | wl_list_for_each_safe(req, tmp, &manager_res->requests, link) { | |
|
|
295 | if (req->type == WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE) { | |
|
|
296 | free(req->create_workspace.name); | |
|
|
297 | } | |
|
|
298 | wl_list_remove(&req->link); | |
|
|
299 | free(req); | |
|
|
300 | } | |
|
|
301 | } | |
|
|
302 | ||
|
|
303 | static void | |
|
|
304 | clear_requests_by(struct wlr_ext_workspace_manager_v1_resource *manager_res, | |
|
|
305 | struct wlr_ext_workspace_group_handle_v1 *group, | |
|
|
306 | struct wlr_ext_workspace_handle_v1 *workspace) { | |
|
|
307 | struct wlr_ext_workspace_v1_request *req, *tmp; | |
|
|
308 | wl_list_for_each_safe(req, tmp, &manager_res->requests, link) { | |
|
|
309 | switch (req->type) { | |
|
|
310 | case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE: | |
|
|
311 | if (group && req->create_workspace.group == group) { | |
|
|
312 | req->create_workspace.group = NULL; | |
|
|
313 | } | |
|
|
314 | break; | |
|
|
315 | case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE: | |
|
|
316 | if (workspace && req->activate.workspace == workspace) { | |
|
|
317 | req->activate.workspace = NULL; | |
|
|
318 | } | |
|
|
319 | break; | |
|
|
320 | case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE: | |
|
|
321 | if (workspace && req->deactivate.workspace == workspace) { | |
|
|
322 | req->deactivate.workspace = NULL; | |
|
|
323 | } | |
|
|
324 | break; | |
|
|
325 | case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN: | |
|
|
326 | if (workspace && req->assign.workspace == workspace) { | |
|
|
327 | req->assign.workspace = NULL; | |
|
|
328 | } | |
|
|
329 | if (group && req->assign.group == group) { | |
|
|
330 | req->assign.group = NULL; | |
|
|
331 | } | |
|
|
332 | break; | |
|
|
333 | case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE: | |
|
|
334 | if (workspace && req->remove.workspace == workspace) { | |
|
|
335 | req->remove.workspace = NULL; | |
|
|
336 | } | |
|
|
337 | break; | |
|
|
338 | } | |
|
|
339 | } | |
|
|
340 | } | |
|
|
341 | ||
|
|
342 | static void manager_handle_commit(struct wl_client *client, | |
|
|
343 | struct wl_resource *resource) { | |
|
|
344 | struct wlr_ext_workspace_manager_v1_resource *manager_res = | |
|
|
345 | manager_resource_from_resource(resource); | |
|
|
346 | if (!manager_res) { | |
|
|
347 | return; | |
|
|
348 | } | |
|
|
349 | ||
|
|
350 | struct wlr_ext_workspace_v1_commit_event commit_event = { | |
|
|
351 | .requests = &manager_res->requests, | |
|
|
352 | }; | |
|
|
353 | wl_signal_emit_mutable(&manager_res->manager->events.commit, &commit_event); | |
|
|
354 | destroy_requests(manager_res); | |
|
|
355 | } | |
|
|
356 | ||
|
|
357 | static void handle_idle(void *data) { | |
|
|
358 | struct wlr_ext_workspace_manager_v1 *manager = data; | |
|
|
359 | ||
|
|
360 | struct wlr_ext_workspace_manager_v1_resource *manager_res; | |
|
|
361 | wl_list_for_each(manager_res, &manager->resources, link) { | |
|
|
362 | ext_workspace_manager_v1_send_done(manager_res->resource); | |
|
|
363 | } | |
|
|
364 | manager->idle_source = NULL; | |
|
|
365 | } | |
|
|
366 | ||
|
|
367 | static void | |
|
|
368 | manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) { | |
|
|
369 | if (!manager->idle_source) { | |
|
|
370 | manager->idle_source = | |
|
|
371 | wl_event_loop_add_idle(manager->event_loop, handle_idle, manager); | |
|
|
372 | } | |
|
|
373 | } | |
|
|
374 | ||
|
|
375 | static void | |
|
|
376 | workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) { | |
|
|
377 | struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace; | |
|
|
378 | struct wl_resource *resource = workspace_res->resource; | |
|
|
379 | ||
|
|
380 | ext_workspace_handle_v1_send_capabilities(resource, workspace->caps); | |
|
|
381 | if (workspace->coordinates.size > 0) { | |
|
|
382 | ext_workspace_handle_v1_send_coordinates(resource, | |
|
|
383 | &workspace->coordinates); | |
|
|
384 | } | |
|
|
385 | if (workspace->name) { | |
|
|
386 | ext_workspace_handle_v1_send_name(resource, workspace->name); | |
|
|
387 | } | |
|
|
388 | if (workspace->id) { | |
|
|
389 | ext_workspace_handle_v1_send_id(resource, workspace->id); | |
|
|
390 | } | |
|
|
391 | ext_workspace_handle_v1_send_state(resource, workspace->state); | |
|
|
392 | manager_schedule_done(workspace->manager); | |
|
|
393 | } | |
|
|
394 | ||
|
|
395 | static void manager_handle_stop(struct wl_client *client, | |
|
|
396 | struct wl_resource *resource) { | |
|
|
397 | ext_workspace_manager_v1_send_finished(resource); | |
|
|
398 | wl_resource_destroy(resource); | |
|
|
399 | } | |
|
|
400 | ||
|
|
401 | static const struct ext_workspace_manager_v1_interface manager_impl = { | |
|
|
402 | .commit = manager_handle_commit, | |
|
|
403 | .stop = manager_handle_stop, | |
|
|
404 | }; | |
|
|
405 | ||
|
|
406 | static void destroy_manager_resource( | |
|
|
407 | struct wlr_ext_workspace_manager_v1_resource *manager_res) { | |
|
|
408 | destroy_requests(manager_res); | |
|
|
409 | ||
|
|
410 | struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2; | |
|
|
411 | wl_list_for_each_safe(workspace_res, tmp2, | |
|
|
412 | &manager_res->workspace_resources, | |
|
|
413 | manager_resource_link) { | |
|
|
414 | destroy_workspace_resource(workspace_res); | |
|
|
415 | } | |
|
|
416 | struct wlr_ext_workspace_group_v1_resource *group_res, *tmp3; | |
|
|
417 | wl_list_for_each_safe(group_res, tmp3, &manager_res->group_resources, | |
|
|
418 | manager_resource_link) { | |
|
|
419 | destroy_group_resource(group_res); | |
|
|
420 | } | |
|
|
421 | ||
|
|
422 | wl_list_remove(&manager_res->link); | |
|
|
423 | wl_resource_set_user_data(manager_res->resource, NULL); | |
|
|
424 | free(manager_res); | |
|
|
425 | } | |
|
|
426 | ||
|
|
427 | static void manager_resource_destroy(struct wl_resource *resource) { | |
|
|
428 | struct wlr_ext_workspace_manager_v1_resource *manager_res = | |
|
|
429 | manager_resource_from_resource(resource); | |
|
|
430 | if (manager_res) { | |
|
|
431 | destroy_manager_resource(manager_res); | |
|
|
432 | } | |
|
|
433 | } | |
|
|
434 | ||
|
|
435 | static void | |
|
|
436 | group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) { | |
|
|
437 | struct wlr_ext_workspace_group_handle_v1 *group = group_res->group; | |
|
|
438 | struct wl_resource *resource = group_res->resource; | |
|
|
439 | struct wl_client *client = wl_resource_get_client(resource); | |
|
|
440 | ||
|
|
441 | ext_workspace_group_handle_v1_send_capabilities(resource, group->caps); | |
|
|
442 | ||
|
|
443 | struct wlr_ext_workspace_v1_group_output *group_output; | |
|
|
444 | wl_list_for_each(group_output, &group->outputs, link) { | |
|
|
445 | struct wl_resource *output_resource; | |
|
|
446 | wl_resource_for_each(output_resource, | |
|
|
447 | &group_output->output->resources) { | |
|
|
448 | if (wl_resource_get_client(output_resource) == client) { | |
|
|
449 | ext_workspace_group_handle_v1_send_output_enter( | |
|
|
450 | resource, output_resource); | |
|
|
451 | } | |
|
|
452 | } | |
|
|
453 | } | |
|
|
454 | ||
|
|
455 | manager_schedule_done(group->manager); | |
|
|
456 | } | |
|
|
457 | ||
|
|
458 | static void manager_bind(struct wl_client *client, void *data, uint32_t version, | |
|
|
459 | uint32_t id) { | |
|
|
460 | struct wlr_ext_workspace_manager_v1 *manager = data; | |
|
|
461 | ||
|
|
462 | struct wlr_ext_workspace_manager_v1_resource *manager_res = | |
|
|
463 | calloc(1, sizeof(*manager_res)); | |
|
|
464 | if (!manager_res) { | |
|
|
465 | wl_client_post_no_memory(client); | |
|
|
466 | return; | |
|
|
467 | } | |
|
|
468 | ||
|
|
469 | manager_res->manager = manager; | |
|
|
470 | wl_list_init(&manager_res->requests); | |
|
|
471 | wl_list_init(&manager_res->workspace_resources); | |
|
|
472 | wl_list_init(&manager_res->group_resources); | |
|
|
473 | ||
|
|
474 | manager_res->resource = wl_resource_create( | |
|
|
475 | client, &ext_workspace_manager_v1_interface, version, id); | |
|
|
476 | if (!manager_res->resource) { | |
|
|
477 | free(manager_res); | |
|
|
478 | wl_client_post_no_memory(client); | |
|
|
479 | return; | |
|
|
480 | } | |
|
|
481 | wl_resource_set_implementation(manager_res->resource, &manager_impl, | |
|
|
482 | manager_res, manager_resource_destroy); | |
|
|
483 | wl_list_insert(&manager->resources, &manager_res->link); | |
|
|
484 | ||
|
|
485 | struct wlr_ext_workspace_group_handle_v1 *group; | |
|
|
486 | wl_list_for_each(group, &manager->groups, link) { | |
|
|
487 | struct wlr_ext_workspace_group_v1_resource *group_res = | |
|
|
488 | create_group_resource(group, manager_res); | |
|
|
489 | if (!group_res) { | |
|
|
490 | wl_resource_post_no_memory(manager_res->resource); | |
|
|
491 | continue; | |
|
|
492 | } | |
|
|
493 | ext_workspace_manager_v1_send_workspace_group(manager_res->resource, | |
|
|
494 | group_res->resource); | |
|
|
495 | group_send_details(group_res); | |
|
|
496 | } | |
|
|
497 | ||
|
|
498 | struct wlr_ext_workspace_handle_v1 *workspace; | |
|
|
499 | wl_list_for_each(workspace, &manager->workspaces, link) { | |
|
|
500 | struct wlr_ext_workspace_v1_resource *workspace_res = | |
|
|
501 | create_workspace_resource(workspace, manager_res); | |
|
|
502 | if (!workspace_res) { | |
|
|
503 | wl_resource_post_no_memory(manager_res->resource); | |
|
|
504 | continue; | |
|
|
505 | } | |
|
|
506 | ext_workspace_manager_v1_send_workspace(manager_res->resource, | |
|
|
507 | workspace_res->resource); | |
|
|
508 | workspace_send_details(workspace_res); | |
|
|
509 | ||
|
|
510 | if (!workspace->group) { | |
|
|
511 | continue; | |
|
|
512 | } | |
|
|
513 | struct wlr_ext_workspace_group_v1_resource *group_res; | |
|
|
514 | wl_list_for_each(group_res, &workspace->group->resources, link) { | |
|
|
515 | if (group_res->manager == manager_res) { | |
|
|
516 | ext_workspace_group_handle_v1_send_workspace_enter( | |
|
|
517 | group_res->resource, workspace_res->resource); | |
|
|
518 | } | |
|
|
519 | } | |
|
|
520 | } | |
|
|
521 | ||
|
|
522 | ext_workspace_manager_v1_send_done(manager_res->resource); | |
|
|
523 | } | |
|
|
524 | ||
|
|
525 | static void manager_handle_display_destroy(struct wl_listener *listener, | |
|
|
526 | void *data) { | |
|
|
527 | struct wlr_ext_workspace_manager_v1 *manager = | |
|
|
528 | wl_container_of(listener, manager, display_destroy); | |
|
|
529 | ||
|
|
530 | wl_signal_emit_mutable(&manager->events.destroy, NULL); | |
|
|
531 | assert(wl_list_empty(&manager->events.commit.listener_list)); | |
|
|
532 | assert(wl_list_empty(&manager->events.destroy.listener_list)); | |
|
|
533 | ||
|
|
534 | struct wlr_ext_workspace_group_handle_v1 *group, *tmp; | |
|
|
535 | wl_list_for_each_safe(group, tmp, &manager->groups, link) { | |
|
|
536 | wlr_ext_workspace_group_handle_v1_destroy(group); | |
|
|
537 | } | |
|
|
538 | ||
|
|
539 | struct wlr_ext_workspace_handle_v1 *workspace, *tmp2; | |
|
|
540 | wl_list_for_each_safe(workspace, tmp2, &manager->workspaces, link) { | |
|
|
541 | wlr_ext_workspace_handle_v1_destroy(workspace); | |
|
|
542 | } | |
|
|
543 | ||
|
|
544 | struct wlr_ext_workspace_manager_v1_resource *manager_res, *tmp3; | |
|
|
545 | wl_list_for_each_safe(manager_res, tmp3, &manager->resources, link) { | |
|
|
546 | destroy_manager_resource(manager_res); | |
|
|
547 | } | |
|
|
548 | ||
|
|
549 | if (manager->idle_source) { | |
|
|
550 | wl_event_source_remove(manager->idle_source); | |
|
|
551 | } | |
|
|
552 | ||
|
|
553 | wl_list_remove(&manager->display_destroy.link); | |
|
|
554 | wl_global_destroy(manager->global); | |
|
|
555 | free(manager); | |
|
|
556 | } | |
|
|
557 | ||
|
|
558 | struct wlr_ext_workspace_manager_v1 * | |
|
|
559 | wlr_ext_workspace_manager_v1_create(struct wl_display *display, | |
|
|
560 | uint32_t version) { | |
|
|
561 | assert(version <= EXT_WORKSPACE_V1_VERSION); | |
|
|
562 | ||
|
|
563 | struct wlr_ext_workspace_manager_v1 *manager = calloc(1, sizeof(*manager)); | |
|
|
564 | if (!manager) { | |
|
|
565 | return NULL; | |
|
|
566 | } | |
|
|
567 | ||
|
|
568 | manager->global = | |
|
|
569 | wl_global_create(display, &ext_workspace_manager_v1_interface, version, | |
|
|
570 | manager, manager_bind); | |
|
|
571 | if (!manager->global) { | |
|
|
572 | free(manager); | |
|
|
573 | return NULL; | |
|
|
574 | } | |
|
|
575 | ||
|
|
576 | manager->event_loop = wl_display_get_event_loop(display); | |
|
|
577 | ||
|
|
578 | manager->display_destroy.notify = manager_handle_display_destroy; | |
|
|
579 | wl_display_add_destroy_listener(display, &manager->display_destroy); | |
|
|
580 | ||
|
|
581 | wl_list_init(&manager->groups); | |
|
|
582 | wl_list_init(&manager->workspaces); | |
|
|
583 | wl_list_init(&manager->resources); | |
|
|
584 | wl_signal_init(&manager->events.commit); | |
|
|
585 | wl_signal_init(&manager->events.destroy); | |
|
|
586 | ||
|
|
587 | return manager; | |
|
|
588 | } | |
|
|
589 | ||
|
|
590 | struct wlr_ext_workspace_group_handle_v1 * | |
|
|
591 | wlr_ext_workspace_group_handle_v1_create( | |
|
|
592 | struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps) { | |
|
|
593 | struct wlr_ext_workspace_group_handle_v1 *group = calloc(1, sizeof(*group)); | |
|
|
594 | if (!group) { | |
|
|
595 | return NULL; | |
|
|
596 | } | |
|
|
597 | ||
|
|
598 | group->manager = manager; | |
|
|
599 | group->caps = caps; | |
|
|
600 | ||
|
|
601 | wl_list_init(&group->outputs); | |
|
|
602 | wl_list_init(&group->resources); | |
|
|
603 | wl_signal_init(&group->events.destroy); | |
|
|
604 | ||
|
|
605 | wl_list_insert(manager->groups.prev, &group->link); | |
|
|
606 | ||
|
|
607 | struct wlr_ext_workspace_manager_v1_resource *manager_res; | |
|
|
608 | wl_list_for_each(manager_res, &manager->resources, link) { | |
|
|
609 | struct wlr_ext_workspace_group_v1_resource *group_res = | |
|
|
610 | create_group_resource(group, manager_res); | |
|
|
611 | if (!group_res) { | |
|
|
612 | continue; | |
|
|
613 | } | |
|
|
614 | ext_workspace_manager_v1_send_workspace_group(manager_res->resource, | |
|
|
615 | group_res->resource); | |
|
|
616 | group_send_details(group_res); | |
|
|
617 | } | |
|
|
618 | ||
|
|
619 | manager_schedule_done(manager); | |
|
|
620 | ||
|
|
621 | return group; | |
|
|
622 | } | |
|
|
623 | ||
|
|
624 | static void | |
|
|
625 | workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace, | |
|
|
626 | struct wlr_ext_workspace_group_handle_v1 *group, | |
|
|
627 | bool enter) { | |
|
|
628 | ||
|
|
629 | struct wlr_ext_workspace_v1_resource *workspace_res; | |
|
|
630 | wl_list_for_each(workspace_res, &workspace->resources, link) { | |
|
|
631 | struct wlr_ext_workspace_group_v1_resource *group_res; | |
|
|
632 | wl_list_for_each(group_res, &group->resources, link) { | |
|
|
633 | if (group_res->manager != workspace_res->manager) { | |
|
|
634 | continue; | |
|
|
635 | } | |
|
|
636 | if (enter) { | |
|
|
637 | ext_workspace_group_handle_v1_send_workspace_enter( | |
|
|
638 | group_res->resource, workspace_res->resource); | |
|
|
639 | } else { | |
|
|
640 | ext_workspace_group_handle_v1_send_workspace_leave( | |
|
|
641 | group_res->resource, workspace_res->resource); | |
|
|
642 | } | |
|
|
643 | } | |
|
|
644 | } | |
|
|
645 | ||
|
|
646 | manager_schedule_done(workspace->manager); | |
|
|
647 | } | |
|
|
648 | ||
|
|
649 | static void | |
|
|
650 | destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) { | |
|
|
651 | wl_list_remove(&group_output->output_bind.link); | |
|
|
652 | wl_list_remove(&group_output->output_destroy.link); | |
|
|
653 | wl_list_remove(&group_output->link); | |
|
|
654 | free(group_output); | |
|
|
655 | } | |
|
|
656 | ||
|
|
657 | static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group, | |
|
|
658 | struct wlr_output *output, bool enter) { | |
|
|
659 | ||
|
|
660 | struct wlr_ext_workspace_group_v1_resource *group_res; | |
|
|
661 | wl_list_for_each(group_res, &group->resources, link) { | |
|
|
662 | struct wl_client *client = wl_resource_get_client(group_res->resource); | |
|
|
663 | ||
|
|
664 | struct wl_resource *output_resource; | |
|
|
665 | wl_resource_for_each(output_resource, &output->resources) { | |
|
|
666 | if (wl_resource_get_client(output_resource) != client) { | |
|
|
667 | continue; | |
|
|
668 | } | |
|
|
669 | if (enter) { | |
|
|
670 | ext_workspace_group_handle_v1_send_output_enter( | |
|
|
671 | group_res->resource, output_resource); | |
|
|
672 | } else { | |
|
|
673 | ext_workspace_group_handle_v1_send_output_leave( | |
|
|
674 | group_res->resource, output_resource); | |
|
|
675 | } | |
|
|
676 | } | |
|
|
677 | } | |
|
|
678 | ||
|
|
679 | manager_schedule_done(group->manager); | |
|
|
680 | } | |
|
|
681 | ||
|
|
682 | void wlr_ext_workspace_group_handle_v1_destroy( | |
|
|
683 | struct wlr_ext_workspace_group_handle_v1 *group) { | |
|
|
684 | if (!group) { | |
|
|
685 | return; | |
|
|
686 | } | |
|
|
687 | ||
|
|
688 | wl_signal_emit_mutable(&group->events.destroy, NULL); | |
|
|
689 | ||
|
|
690 | assert(wl_list_empty(&group->events.destroy.listener_list)); | |
|
|
691 | ||
|
|
692 | struct wlr_ext_workspace_handle_v1 *workspace; | |
|
|
693 | wl_list_for_each(workspace, &group->manager->workspaces, link) { | |
|
|
694 | if (workspace->group == group) { | |
|
|
695 | workspace_send_group(workspace, group, false); | |
|
|
696 | workspace->group = NULL; | |
|
|
697 | } | |
|
|
698 | } | |
|
|
699 | ||
|
|
700 | struct wlr_ext_workspace_group_v1_resource *group_res, *tmp; | |
|
|
701 | wl_list_for_each_safe(group_res, tmp, &group->resources, link) { | |
|
|
702 | ext_workspace_group_handle_v1_send_removed(group_res->resource); | |
|
|
703 | destroy_group_resource(group_res); | |
|
|
704 | } | |
|
|
705 | ||
|
|
706 | struct wlr_ext_workspace_manager_v1_resource *manager_res; | |
|
|
707 | wl_list_for_each(manager_res, &group->manager->resources, link) { | |
|
|
708 | clear_requests_by(manager_res, group, NULL); | |
|
|
709 | } | |
|
|
710 | ||
|
|
711 | struct wlr_ext_workspace_v1_group_output *group_output, *tmp3; | |
|
|
712 | wl_list_for_each_safe(group_output, tmp3, &group->outputs, link) { | |
|
|
713 | group_send_output(group, group_output->output, false); | |
|
|
714 | destroy_group_output(group_output); | |
|
|
715 | } | |
|
|
716 | ||
|
|
717 | manager_schedule_done(group->manager); | |
|
|
718 | ||
|
|
719 | wl_list_remove(&group->link); | |
|
|
720 | free(group); | |
|
|
721 | } | |
|
|
722 | ||
|
|
723 | static void handle_output_bind(struct wl_listener *listener, void *data) { | |
|
|
724 | struct wlr_ext_workspace_v1_group_output *group_output = | |
|
|
725 | wl_container_of(listener, group_output, output_bind); | |
|
|
726 | struct wlr_output_event_bind *event = data; | |
|
|
727 | struct wl_client *client = wl_resource_get_client(event->resource); | |
|
|
728 | ||
|
|
729 | struct wlr_ext_workspace_group_v1_resource *group_res; | |
|
|
730 | wl_list_for_each(group_res, &group_output->group->resources, link) { | |
|
|
731 | if (wl_resource_get_client(group_res->resource) == client) { | |
|
|
732 | ext_workspace_group_handle_v1_send_output_enter(group_res->resource, | |
|
|
733 | event->resource); | |
|
|
734 | } | |
|
|
735 | } | |
|
|
736 | ||
|
|
737 | manager_schedule_done(group_output->group->manager); | |
|
|
738 | } | |
|
|
739 | ||
|
|
740 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | |
|
|
741 | struct wlr_ext_workspace_v1_group_output *group_output = | |
|
|
742 | wl_container_of(listener, group_output, output_destroy); | |
|
|
743 | group_send_output(group_output->group, group_output->output, false); | |
|
|
744 | destroy_group_output(group_output); | |
|
|
745 | } | |
|
|
746 | ||
|
|
747 | static struct wlr_ext_workspace_v1_group_output * | |
|
|
748 | get_group_output(struct wlr_ext_workspace_group_handle_v1 *group, | |
|
|
749 | struct wlr_output *output) { | |
|
|
750 | struct wlr_ext_workspace_v1_group_output *group_output; | |
|
|
751 | wl_list_for_each(group_output, &group->outputs, link) { | |
|
|
752 | if (group_output->output == output) { | |
|
|
753 | return group_output; | |
|
|
754 | } | |
|
|
755 | } | |
|
|
756 | return NULL; | |
|
|
757 | } | |
|
|
758 | ||
|
|
759 | void wlr_ext_workspace_group_handle_v1_output_enter( | |
|
|
760 | struct wlr_ext_workspace_group_handle_v1 *group, | |
|
|
761 | struct wlr_output *output) { | |
|
|
762 | if (get_group_output(group, output)) { | |
|
|
763 | return; | |
|
|
764 | } | |
|
|
765 | struct wlr_ext_workspace_v1_group_output *group_output = | |
|
|
766 | calloc(1, sizeof(*group_output)); | |
|
|
767 | if (!group_output) { | |
|
|
768 | return; | |
|
|
769 | } | |
|
|
770 | group_output->output = output; | |
|
|
771 | group_output->group = group; | |
|
|
772 | wl_list_insert(&group->outputs, &group_output->link); | |
|
|
773 | ||
|
|
774 | group_output->output_bind.notify = handle_output_bind; | |
|
|
775 | wl_signal_add(&output->events.bind, &group_output->output_bind); | |
|
|
776 | group_output->output_destroy.notify = handle_output_destroy; | |
|
|
777 | wl_signal_add(&output->events.destroy, &group_output->output_destroy); | |
|
|
778 | ||
|
|
779 | group_send_output(group, output, true); | |
|
|
780 | } | |
|
|
781 | ||
|
|
782 | void wlr_ext_workspace_group_handle_v1_output_leave( | |
|
|
783 | struct wlr_ext_workspace_group_handle_v1 *group, | |
|
|
784 | struct wlr_output *output) { | |
|
|
785 | struct wlr_ext_workspace_v1_group_output *group_output = | |
|
|
786 | get_group_output(group, output); | |
|
|
787 | if (!group_output) { | |
|
|
788 | return; | |
|
|
789 | } | |
|
|
790 | ||
|
|
791 | group_send_output(group, output, false); | |
|
|
792 | destroy_group_output(group_output); | |
|
|
793 | } | |
|
|
794 | ||
|
|
795 | struct wlr_ext_workspace_handle_v1 * | |
|
|
796 | wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager, | |
|
|
797 | const char *id, uint32_t caps) { | |
|
|
798 | struct wlr_ext_workspace_handle_v1 *workspace = | |
|
|
799 | calloc(1, sizeof(*workspace)); | |
|
|
800 | if (!workspace) { | |
|
|
801 | return NULL; | |
|
|
802 | } | |
|
|
803 | ||
|
|
804 | workspace->manager = manager; | |
|
|
805 | workspace->caps = caps; | |
|
|
806 | ||
|
|
807 | if (id) { | |
|
|
808 | workspace->id = strdup(id); | |
|
|
809 | if (!workspace->id) { | |
|
|
810 | free(workspace); | |
|
|
811 | return NULL; | |
|
|
812 | } | |
|
|
813 | } | |
|
|
814 | ||
|
|
815 | wl_list_init(&workspace->resources); | |
|
|
816 | wl_array_init(&workspace->coordinates); | |
|
|
817 | wl_signal_init(&workspace->events.destroy); | |
|
|
818 | ||
|
|
819 | wl_list_insert(manager->workspaces.prev, &workspace->link); | |
|
|
820 | ||
|
|
821 | struct wlr_ext_workspace_manager_v1_resource *manager_res; | |
|
|
822 | wl_list_for_each(manager_res, &manager->resources, link) { | |
|
|
823 | struct wlr_ext_workspace_v1_resource *workspace_res = | |
|
|
824 | create_workspace_resource(workspace, manager_res); | |
|
|
825 | if (!workspace_res) { | |
|
|
826 | continue; | |
|
|
827 | } | |
|
|
828 | ext_workspace_manager_v1_send_workspace(manager_res->resource, | |
|
|
829 | workspace_res->resource); | |
|
|
830 | workspace_send_details(workspace_res); | |
|
|
831 | } | |
|
|
832 | ||
|
|
833 | manager_schedule_done(manager); | |
|
|
834 | ||
|
|
835 | return workspace; | |
|
|
836 | } | |
|
|
837 | ||
|
|
838 | void wlr_ext_workspace_handle_v1_destroy( | |
|
|
839 | struct wlr_ext_workspace_handle_v1 *workspace) { | |
|
|
840 | if (!workspace) { | |
|
|
841 | return; | |
|
|
842 | } | |
|
|
843 | ||
|
|
844 | wl_signal_emit_mutable(&workspace->events.destroy, NULL); | |
|
|
845 | ||
|
|
846 | assert(wl_list_empty(&workspace->events.destroy.listener_list)); | |
|
|
847 | ||
|
|
848 | if (workspace->group) { | |
|
|
849 | workspace_send_group(workspace, workspace->group, false); | |
|
|
850 | } | |
|
|
851 | ||
|
|
852 | struct wlr_ext_workspace_v1_resource *workspace_res, *tmp; | |
|
|
853 | wl_list_for_each_safe(workspace_res, tmp, &workspace->resources, link) { | |
|
|
854 | ext_workspace_handle_v1_send_removed(workspace_res->resource); | |
|
|
855 | destroy_workspace_resource(workspace_res); | |
|
|
856 | } | |
|
|
857 | ||
|
|
858 | struct wlr_ext_workspace_manager_v1_resource *manager_res; | |
|
|
859 | wl_list_for_each(manager_res, &workspace->manager->resources, link) { | |
|
|
860 | clear_requests_by(manager_res, NULL, workspace); | |
|
|
861 | } | |
|
|
862 | ||
|
|
863 | manager_schedule_done(workspace->manager); | |
|
|
864 | ||
|
|
865 | wl_list_remove(&workspace->link); | |
|
|
866 | wl_array_release(&workspace->coordinates); | |
|
|
867 | free(workspace->id); | |
|
|
868 | free(workspace->name); | |
|
|
869 | free(workspace); | |
|
|
870 | } | |
|
|
871 | ||
|
|
872 | void wlr_ext_workspace_handle_v1_set_group( | |
|
|
873 | struct wlr_ext_workspace_handle_v1 *workspace, | |
|
|
874 | struct wlr_ext_workspace_group_handle_v1 *group) { | |
|
|
875 | if (workspace->group == group) { | |
|
|
876 | return; | |
|
|
877 | } | |
|
|
878 | ||
|
|
879 | if (workspace->group) { | |
|
|
880 | workspace_send_group(workspace, workspace->group, false); | |
|
|
881 | } | |
|
|
882 | workspace->group = group; | |
|
|
883 | if (group) { | |
|
|
884 | workspace_send_group(workspace, group, true); | |
|
|
885 | } | |
|
|
886 | } | |
|
|
887 | ||
|
|
888 | void wlr_ext_workspace_handle_v1_set_name( | |
|
|
889 | struct wlr_ext_workspace_handle_v1 *workspace, const char *name) { | |
|
|
890 | assert(name); | |
|
|
891 | ||
|
|
892 | if (workspace->name && strcmp(workspace->name, name) == 0) { | |
|
|
893 | return; | |
|
|
894 | } | |
|
|
895 | ||
|
|
896 | free(workspace->name); | |
|
|
897 | workspace->name = strdup(name); | |
|
|
898 | if (workspace->name == NULL) { | |
|
|
899 | return; | |
|
|
900 | } | |
|
|
901 | ||
|
|
902 | struct wlr_ext_workspace_v1_resource *workspace_res; | |
|
|
903 | wl_list_for_each(workspace_res, &workspace->resources, link) { | |
|
|
904 | ext_workspace_handle_v1_send_name(workspace_res->resource, | |
|
|
905 | workspace->name); | |
|
|
906 | } | |
|
|
907 | ||
|
|
908 | manager_schedule_done(workspace->manager); | |
|
|
909 | } | |
|
|
910 | ||
|
|
911 | void wlr_ext_workspace_handle_v1_set_coordinates( | |
|
|
912 | struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords, | |
|
|
913 | size_t coords_len) { | |
|
|
914 | size_t size = coords_len * sizeof(coords[0]); | |
|
|
915 | if (size == workspace->coordinates.size && | |
|
|
916 | (size == 0 || memcmp(workspace->coordinates.data, coords, size) == 0)) { | |
|
|
917 | return; | |
|
|
918 | } | |
|
|
919 | ||
|
|
920 | wl_array_release(&workspace->coordinates); | |
|
|
921 | wl_array_init(&workspace->coordinates); | |
|
|
922 | struct wl_array arr = { | |
|
|
923 | .data = (void *)coords, | |
|
|
924 | .size = size, | |
|
|
925 | }; | |
|
|
926 | wl_array_copy(&workspace->coordinates, &arr); | |
|
|
927 | ||
|
|
928 | struct wlr_ext_workspace_v1_resource *workspace_res; | |
|
|
929 | wl_list_for_each(workspace_res, &workspace->resources, link) { | |
|
|
930 | ext_workspace_handle_v1_send_coordinates(workspace_res->resource, | |
|
|
931 | &workspace->coordinates); | |
|
|
932 | } | |
|
|
933 | ||
|
|
934 | manager_schedule_done(workspace->manager); | |
|
|
935 | } | |
|
|
936 | ||
|
|
937 | static void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace, | |
|
|
938 | enum ext_workspace_handle_v1_state state, | |
|
|
939 | bool enabled) { | |
|
|
940 | uint32_t old_state = workspace->state; | |
|
|
941 | if (enabled) { | |
|
|
942 | workspace->state |= state; | |
|
|
943 | } else { | |
|
|
944 | workspace->state &= ~state; | |
|
|
945 | } | |
|
|
946 | if (old_state == workspace->state) { | |
|
|
947 | return; | |
|
|
948 | } | |
|
|
949 | ||
|
|
950 | struct wlr_ext_workspace_v1_resource *workspace_res; | |
|
|
951 | wl_list_for_each(workspace_res, &workspace->resources, link) { | |
|
|
952 | ext_workspace_handle_v1_send_state(workspace_res->resource, | |
|
|
953 | workspace->state); | |
|
|
954 | } | |
|
|
955 | ||
|
|
956 | manager_schedule_done(workspace->manager); | |
|
|
957 | } | |
|
|
958 | ||
|
|
959 | void wlr_ext_workspace_handle_v1_set_active( | |
|
|
960 | struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) { | |
|
|
961 | workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE, | |
|
|
962 | enabled); | |
|
|
963 | } | |
|
|
964 | ||
|
|
965 | void wlr_ext_workspace_handle_v1_set_urgent( | |
|
|
966 | struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) { | |
|
|
967 | workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_URGENT, | |
|
|
968 | enabled); | |
|
|
969 | } | |
|
|
970 | ||
|
|
971 | void wlr_ext_workspace_handle_v1_set_hidden( | |
|
|
972 | struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) { | |
|
|
973 | workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_HIDDEN, | |
|
|
974 | enabled); | |
|
|
975 | } | |
| @@ -0,0 +1,150 | |||
|
|
1 | /* | |
|
|
2 | * This an unstable interface of wlroots. No guarantees are made regarding the | |
|
|
3 | * future consistency of this API. | |
|
|
4 | */ | |
|
|
5 | #ifndef WLR_USE_UNSTABLE | |
|
|
6 | #error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" | |
|
|
7 | #endif | |
|
|
8 | ||
|
|
9 | #ifndef WLR_TYPES_WLR_EXT_WORKSPACE_V1_H | |
|
|
10 | #define WLR_TYPES_WLR_EXT_WORKSPACE_V1_H | |
|
|
11 | ||
|
|
12 | #include <wayland-protocols/ext-workspace-v1-enum.h> | |
|
|
13 | #include <wayland-server-core.h> | |
|
|
14 | ||
|
|
15 | struct wlr_output; | |
|
|
16 | ||
|
|
17 | enum wlr_ext_workspace_v1_request_type { | |
|
|
18 | WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE, | |
|
|
19 | WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE, | |
|
|
20 | WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE, | |
|
|
21 | WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN, | |
|
|
22 | WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE, | |
|
|
23 | }; | |
|
|
24 | ||
|
|
25 | struct wlr_ext_workspace_v1_request { | |
|
|
26 | enum wlr_ext_workspace_v1_request_type type; | |
|
|
27 | struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests | |
|
|
28 | union { | |
|
|
29 | struct { | |
|
|
30 | char *name; | |
|
|
31 | struct wlr_ext_workspace_group_handle_v1 | |
|
|
32 | *group; // NULL if destroyed | |
|
|
33 | } create_workspace; | |
|
|
34 | struct { | |
|
|
35 | struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed | |
|
|
36 | } activate; | |
|
|
37 | struct { | |
|
|
38 | struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed | |
|
|
39 | } deactivate; | |
|
|
40 | struct { | |
|
|
41 | struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed | |
|
|
42 | struct wlr_ext_workspace_group_handle_v1 | |
|
|
43 | *group; // NULL if destroyed | |
|
|
44 | } assign; | |
|
|
45 | struct { | |
|
|
46 | struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed | |
|
|
47 | } remove; | |
|
|
48 | }; | |
|
|
49 | }; | |
|
|
50 | ||
|
|
51 | struct wlr_ext_workspace_v1_commit_event { | |
|
|
52 | struct wl_list *requests; // wlr_ext_workspace_v1_request.link | |
|
|
53 | }; | |
|
|
54 | ||
|
|
55 | struct wlr_ext_workspace_manager_v1 { | |
|
|
56 | struct wl_global *global; | |
|
|
57 | struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link | |
|
|
58 | struct wl_list workspaces; // wlr_ext_workspace_handle_v1.link | |
|
|
59 | ||
|
|
60 | struct { | |
|
|
61 | struct wl_signal commit; // wlr_ext_workspace_v1_commit_event | |
|
|
62 | struct wl_signal destroy; | |
|
|
63 | } events; | |
|
|
64 | ||
|
|
65 | void *data; | |
|
|
66 | ||
|
|
67 | struct { | |
|
|
68 | struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link | |
|
|
69 | struct wl_event_source *idle_source; | |
|
|
70 | struct wl_event_loop *event_loop; | |
|
|
71 | struct wl_listener display_destroy; | |
|
|
72 | }; | |
|
|
73 | }; | |
|
|
74 | ||
|
|
75 | struct wlr_ext_workspace_group_handle_v1 { | |
|
|
76 | struct wlr_ext_workspace_manager_v1 *manager; | |
|
|
77 | uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities | |
|
|
78 | struct { | |
|
|
79 | struct wl_signal destroy; | |
|
|
80 | } events; | |
|
|
81 | ||
|
|
82 | struct wl_list link; // wlr_ext_workspace_manager_v1.groups | |
|
|
83 | ||
|
|
84 | void *data; | |
|
|
85 | ||
|
|
86 | struct { | |
|
|
87 | struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link | |
|
|
88 | struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link | |
|
|
89 | }; | |
|
|
90 | }; | |
|
|
91 | ||
|
|
92 | struct wlr_ext_workspace_handle_v1 { | |
|
|
93 | struct wlr_ext_workspace_manager_v1 *manager; | |
|
|
94 | struct wlr_ext_workspace_group_handle_v1 *group; // May be NULL | |
|
|
95 | char *id; | |
|
|
96 | char *name; | |
|
|
97 | struct wl_array coordinates; | |
|
|
98 | uint32_t caps; // ext_workspace_handle_v1_workspace_capabilities | |
|
|
99 | uint32_t state; // ext_workspace_handle_v1_state | |
|
|
100 | ||
|
|
101 | struct { | |
|
|
102 | struct wl_signal destroy; | |
|
|
103 | } events; | |
|
|
104 | ||
|
|
105 | struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces | |
|
|
106 | ||
|
|
107 | void *data; | |
|
|
108 | ||
|
|
109 | struct { | |
|
|
110 | struct wl_list resources; // wlr_ext_workspace_v1_resource.link | |
|
|
111 | }; | |
|
|
112 | }; | |
|
|
113 | ||
|
|
114 | struct wlr_ext_workspace_manager_v1 * | |
|
|
115 | wlr_ext_workspace_manager_v1_create(struct wl_display *display, | |
|
|
116 | uint32_t version); | |
|
|
117 | ||
|
|
118 | struct wlr_ext_workspace_group_handle_v1 * | |
|
|
119 | wlr_ext_workspace_group_handle_v1_create( | |
|
|
120 | struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps); | |
|
|
121 | void wlr_ext_workspace_group_handle_v1_destroy( | |
|
|
122 | struct wlr_ext_workspace_group_handle_v1 *group); | |
|
|
123 | ||
|
|
124 | void wlr_ext_workspace_group_handle_v1_output_enter( | |
|
|
125 | struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output); | |
|
|
126 | void wlr_ext_workspace_group_handle_v1_output_leave( | |
|
|
127 | struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output); | |
|
|
128 | ||
|
|
129 | struct wlr_ext_workspace_handle_v1 * | |
|
|
130 | wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager, | |
|
|
131 | const char *id, uint32_t caps); | |
|
|
132 | void wlr_ext_workspace_handle_v1_destroy( | |
|
|
133 | struct wlr_ext_workspace_handle_v1 *workspace); | |
|
|
134 | ||
|
|
135 | void wlr_ext_workspace_handle_v1_set_group( | |
|
|
136 | struct wlr_ext_workspace_handle_v1 *workspace, | |
|
|
137 | struct wlr_ext_workspace_group_handle_v1 *group); | |
|
|
138 | void wlr_ext_workspace_handle_v1_set_name( | |
|
|
139 | struct wlr_ext_workspace_handle_v1 *workspace, const char *name); | |
|
|
140 | void wlr_ext_workspace_handle_v1_set_coordinates( | |
|
|
141 | struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords, | |
|
|
142 | size_t coords_len); | |
|
|
143 | void wlr_ext_workspace_handle_v1_set_active( | |
|
|
144 | struct wlr_ext_workspace_handle_v1 *workspace, bool enabled); | |
|
|
145 | void wlr_ext_workspace_handle_v1_set_urgent( | |
|
|
146 | struct wlr_ext_workspace_handle_v1 *workspace, bool enabled); | |
|
|
147 | void wlr_ext_workspace_handle_v1_set_hidden( | |
|
|
148 | struct wlr_ext_workspace_handle_v1 *workspace, bool enabled); | |
|
|
149 | ||
|
|
150 | #endif | |
General Comments 0
You need to be logged in to leave comments.
Login now
