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 |
|
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
