refactor(protocol)!: move protocol bindings to go-wayland-bindings
Remove protocol/, cmd/wlturbo-scanner, internal/scanner, the protocol migration doc and LICENSES/ (the LGPL text only covered the kdeserverdecoration XML, which moved with the bindings). wlturbo is now a pure client runtime: the root package and the wl/ shim. TestExternalConsumer, which compiled protocol/core tests in a separate module, is removed; the equivalent tests live in go-wayland-bindings. Registry bootstrap and BindNegotiated transport coverage is rewritten against the root package in registry_test.go. BREAKING CHANGE: github.com/bnema/wlturbo/protocol/<pkg> no longer exists. Import github.com/bnema/go-wayland-bindings/client/<pkg> instead. Renamed packages: core->wayland, datacontrol->extdatacontrol, drmsyncobj->linuxdrmsyncobj, extforeigntoplevel->extforeigntoplevellist, foreigntoplevel->wlrforeigntoplevelmanagement, idlenotify->extidlenotify, imagecapturesource->extimagecapturesource, imagecopycapture->extimagecopycapture, kdeserverdecoration->serverdecoration, layershell->wlrlayershell, outputmanagement->wlroutputmanagement, outputpower->wlroutputpowermanagement, presentation->presentationtime, screencopy->wlrscreencopy, shortcutsinhibit->keyboardshortcutsinhibit, workspace->extworkspace. All other package names are unchanged. The cmd/wlturbo-scanner generator is replaced by go-wayland-bindings' wlbgen.
- commit
- d9b2fda61758aa26bf90b608b0f79f9de6f26f06
- author
- brice · · 2026-10-01 05:48 UTC
- parent
- 089fa12
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
148 files · +135 -46447
D LICENSES/LGPL-2.1-or-later.txt +0 -176
| @@ -1,176 +0,0 @@ | |||
| 1 | - | GNU LESSER GENERAL PUBLIC LICENSE | |
| 2 | - | ||
| 3 | - | Version 2.1, February 1999 | |
| 4 | - | ||
| 5 | - | Copyright (C) 1991, 1999 Free Software Foundation, Inc. | |
| 6 | - | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 7 | - | ||
| 8 | - | Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. | |
| 9 | - | ||
| 10 | - | [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] | |
| 11 | - | ||
| 12 | - | Preamble | |
| 13 | - | ||
| 14 | - | The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. | |
| 15 | - | ||
| 16 | - | This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. | |
| 17 | - | ||
| 18 | - | When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. | |
| 19 | - | ||
| 20 | - | To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. | |
| 21 | - | ||
| 22 | - | For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. | |
| 23 | - | ||
| 24 | - | We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. | |
| 25 | - | ||
| 26 | - | To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. | |
| 27 | - | ||
| 28 | - | Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. | |
| 29 | - | ||
| 30 | - | Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. | |
| 31 | - | ||
| 32 | - | When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. | |
| 33 | - | ||
| 34 | - | We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. | |
| 35 | - | ||
| 36 | - | For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. | |
| 37 | - | ||
| 38 | - | In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. | |
| 39 | - | ||
| 40 | - | Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. | |
| 41 | - | ||
| 42 | - | The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. | |
| 43 | - | ||
| 44 | - | GNU LESSER GENERAL PUBLIC LICENSE | |
| 45 | - | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
| 46 | - | ||
| 47 | - | 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". | |
| 48 | - | ||
| 49 | - | A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. | |
| 50 | - | ||
| 51 | - | The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) | |
| 52 | - | ||
| 53 | - | "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. | |
| 54 | - | ||
| 55 | - | Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. | |
| 56 | - | ||
| 57 | - | 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. | |
| 58 | - | ||
| 59 | - | You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. | |
| 60 | - | ||
| 61 | - | 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: | |
| 62 | - | ||
| 63 | - | a) The modified work must itself be a software library. | |
| 64 | - | ||
| 65 | - | b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. | |
| 66 | - | ||
| 67 | - | c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. | |
| 68 | - | ||
| 69 | - | d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. | |
| 70 | - | ||
| 71 | - | (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) | |
| 72 | - | ||
| 73 | - | These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. | |
| 74 | - | ||
| 75 | - | Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. | |
| 76 | - | ||
| 77 | - | In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. | |
| 78 | - | ||
| 79 | - | 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. | |
| 80 | - | ||
| 81 | - | Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. | |
| 82 | - | ||
| 83 | - | This option is useful when you wish to copy part of the code of the Library into a program that is not a library. | |
| 84 | - | ||
| 85 | - | 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. | |
| 86 | - | ||
| 87 | - | If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. | |
| 88 | - | ||
| 89 | - | 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. | |
| 90 | - | ||
| 91 | - | However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. | |
| 92 | - | ||
| 93 | - | When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. | |
| 94 | - | ||
| 95 | - | If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) | |
| 96 | - | ||
| 97 | - | Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. | |
| 98 | - | ||
| 99 | - | 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. | |
| 100 | - | ||
| 101 | - | You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: | |
| 102 | - | ||
| 103 | - | a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) | |
| 104 | - | ||
| 105 | - | b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. | |
| 106 | - | ||
| 107 | - | c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. | |
| 108 | - | ||
| 109 | - | d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. | |
| 110 | - | ||
| 111 | - | e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. | |
| 112 | - | ||
| 113 | - | For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. | |
| 114 | - | ||
| 115 | - | It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. | |
| 116 | - | ||
| 117 | - | 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: | |
| 118 | - | ||
| 119 | - | a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. | |
| 120 | - | ||
| 121 | - | b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. | |
| 122 | - | ||
| 123 | - | 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. | |
| 124 | - | ||
| 125 | - | 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. | |
| 126 | - | ||
| 127 | - | 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. | |
| 128 | - | ||
| 129 | - | 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. | |
| 130 | - | ||
| 131 | - | If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. | |
| 132 | - | ||
| 133 | - | It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. | |
| 134 | - | ||
| 135 | - | This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. | |
| 136 | - | ||
| 137 | - | 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. | |
| 138 | - | ||
| 139 | - | 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. | |
| 140 | - | ||
| 141 | - | Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. | |
| 142 | - | ||
| 143 | - | 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. | |
| 144 | - | ||
| 145 | - | NO WARRANTY | |
| 146 | - | ||
| 147 | - | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |
| 148 | - | ||
| 149 | - | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
| 150 | - | ||
| 151 | - | END OF TERMS AND CONDITIONS | |
| 152 | - | ||
| 153 | - | How to Apply These Terms to Your New Libraries | |
| 154 | - | ||
| 155 | - | If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). | |
| 156 | - | ||
| 157 | - | To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. | |
| 158 | - | ||
| 159 | - | one line to give the library's name and an idea of what it does. | |
| 160 | - | Copyright (C) year name of author | |
| 161 | - | ||
| 162 | - | This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. | |
| 163 | - | ||
| 164 | - | This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | |
| 165 | - | ||
| 166 | - | You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. | |
| 167 | - | ||
| 168 | - | You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: | |
| 169 | - | ||
| 170 | - | Yoyodyne, Inc., hereby disclaims all copyright interest in | |
| 171 | - | the library `Frob' (a library for tweaking knobs) written | |
| 172 | - | by James Random Hacker. | |
| 173 | - | ||
| 174 | - | signature of Ty Coon, 1 April 1990 | |
| 175 | - | Ty Coon, President of Vice | |
| 176 | - | That's all there is to it! | |
M README.md +16 -36
| @@ -1,38 +1,31 @@ | |||
| 1 | 1 | # WLTurbo - Wayland Client Library for Go | |
| 2 | 2 | ||
| 3 | - | A performance-focused Wayland client library that provides the foundational protocol implementation for building Wayland applications and libraries. | |
| 3 | + | A performance-focused Wayland client runtime for Go, the foundation for protocol bindings and Wayland applications. | |
| 4 | 4 | ||
| 5 | 5 | ## Overview | |
| 6 | 6 | ||
| 7 | - | WLTurbo is a low-level Wayland client library with generated core and extension bindings. Applications and higher-level libraries use it to communicate with any compositor that advertises the required protocols. | |
| 7 | + | WLTurbo is a low-level Wayland client runtime: connection, wire framing, descriptor passing, object lifecycle and the bootstrap registry. Protocol bindings are provided separately (see [Protocol bindings](#protocol-bindings)). | |
| 8 | 8 | ||
| 9 | 9 | ## Architecture | |
| 10 | 10 | ||
| 11 | 11 | WLTurbo provides the foundational Wayland client infrastructure: | |
| 12 | 12 | ||
| 13 | - | - **Core Protocol Objects**: Display, Registry, Compositor, Surface, Seat, Region | |
| 13 | + | - **Bootstrap Objects**: Display and Registry | |
| 14 | 14 | - **Event Dispatching**: Efficient routing of Wayland events to handlers | |
| 15 | 15 | - **Connection Management**: Unix socket communication with the compositor | |
| 16 | 16 | - **Memory Management**: Shared memory support via file descriptor passing | |
| 17 | 17 | ||
| 18 | - | Bindings handle wire messages and object lifecycle. Applications own rendering, input interpretation, capability fallbacks and desktop policy. WLTurbo provides client bindings, not compositor-side server implementations. | |
| 18 | + | Applications own rendering, input interpretation, capability fallbacks and desktop policy. WLTurbo is client-side only, not a compositor-side server implementation. | |
| 19 | 19 | ||
| 20 | - | ## Generated protocols | |
| 20 | + | ## Protocol bindings | |
| 21 | 21 | ||
| 22 | - | Packages under `protocol/` cover: | |
| 22 | + | Generated protocol bindings are not part of this module. They live in [github.com/bnema/go-wayland-bindings](https://github.com/bnema/go-wayland-bindings), one package per protocol under `client/<pkg>`, for example `client/wayland`, `client/xdgshell` and `client/wlrlayershell`: | |
| 23 | 23 | ||
| 24 | - | | Area | Packages | | |
| 25 | - | |---|---| | |
| 26 | - | | Core and windows | `core`, `xdgshell`, `xdgdecoration`, `xdgactivation` | | |
| 27 | - | | Buffers and scaling | `linuxdmabuf`, `drmsyncobj`, `viewporter`, `fractionalscale` | | |
| 28 | - | | Presentation and color | `presentation`, `tearingcontrol`, `fifo`, `committiming`, `contenttype`, `alphamodifier`, `colormanagement`, `colorrepresentation`, `drmlease` | | |
| 29 | - | | Input | `cursorshape`, `tablet`, `textinput`, `relativepointer`, `pointerconstraints`, `pointerwarp`, `shortcutsinhibit`, `virtualkeyboard`, `inputmethod` | | |
| 30 | - | | Clipboard | Core data-device, `primaryselection`, `datacontrol` (ext-data-control) | | |
| 31 | - | | Desktop and outputs | `layershell`, `xdgoutput`, `outputmanagement`, `outputpower`, `workspace`, `foreigntoplevel` (wlr), `extforeigntoplevel`, `extsessionlock`, `kdeserverdecoration` | | |
| 32 | - | | Idle | `idleinhibit`, `idlenotify` | | |
| 33 | - | | Capture | `screencopy` (wlr), `imagecapturesource`, `imagecopycapture` | | |
| 24 | + | ```go | |
| 25 | + | import "github.com/bnema/go-wayland-bindings/client/xdgshell" | |
| 26 | + | ``` | |
| 34 | 27 | ||
| 35 | - | Each package contains the upstream XML, generated Go bindings and a generation command. [Protocol sources](protocol/SOURCE.md) records pinned upstream revisions and checksums. A binding's presence does not imply that the compositor implements it. | |
| 28 | + | Those packages are built on this runtime. A binding's presence does not imply that the compositor implements it. | |
| 36 | 29 | ||
| 37 | 30 | After `display.Roundtrip()` discovers globals, call `display.Registry().BindNegotiated(interfaceName, supportedVersion, proxy)` to bind at the lesser of the advertised and supported versions. It returns the negotiated version; use `errors.Is(err, wlturbo.ErrGlobalNotFound)` to handle absent optional globals. | |
| 38 | 31 | ||
| @@ -41,8 +34,8 @@ After `display.Roundtrip()` discovers globals, call `display.Registry().BindNego | |||
| 41 | 34 | - **Stream framing**: messages split across or coalesced within socket reads are framed exactly; event bodies are not copied. | |
| 42 | 35 | - **Descriptor ownership**: received FDs belong to the event that declares them and are closed if a handler does not take them. | |
| 43 | 36 | - **Object lifecycle**: destroyed objects stay as zombies until `delete_id`, so events already in flight are dropped instead of failing the connection. | |
| 44 | - | - **Version checks**: generated requests newer than the bound object version return `ErrVersionTooLow` before anything is sent. | |
| 45 | - | - **Allocation-free numeric paths**: numeric generated requests without object creation or descriptors, and typed numeric events, do not allocate after warm-up; representative cases have allocation regression tests. Object creation, received strings and descriptors have separate allocation costs. | |
| 37 | + | - **Version checks**: requests newer than the bound object version return `ErrVersionTooLow` before anything is sent. | |
| 38 | + | - **Allocation-free numeric paths**: numeric requests sent with `Context.RequestArgs` without object creation or descriptors, and typed numeric events, do not allocate after warm-up. Object creation, received strings and descriptors have separate allocation costs. | |
| 46 | 39 | ||
| 47 | 40 | ## Quick Start | |
| 48 | 41 | ||
| @@ -76,22 +69,13 @@ For higher-level device control, [libwldevices-go](https://github.com/bnema/libw | |||
| 76 | 69 | ## Development checks | |
| 77 | 70 | ||
| 78 | 71 | ```sh | |
| 79 | - | GOWORK=off go generate ./... | |
| 80 | 72 | GOWORK=off go test ./... | |
| 81 | 73 | GOWORK=off go test -race ./... | |
| 82 | 74 | GOWORK=off go vet ./... | |
| 83 | - | GOWORK=off go test ./protocol -run '^$' -bench . -benchmem | |
| 84 | - | ``` | |
| 85 | - | ||
| 86 | - | Tests verify that checked-in bindings reproduce from the vendored XML. Socketpair tests exercise wire messages, versions, object lifecycle and file descriptors without a compositor. | |
| 87 | - | ||
| 88 | - | For isolated integration tests, build [NeferWL](https://github.com/bnema/neferwl) with its headless backend and pass its executable path: | |
| 89 | - | ||
| 90 | - | ```sh | |
| 91 | - | env GOWORK=off WLTURBO_HEADLESS=/path/to/neferwl go test ./protocol -run Headless -v -count=1 -timeout=90s | |
| 75 | + | GOWORK=off go test -run '^$' -bench . -benchmem | |
| 92 | 76 | ``` | |
| 93 | 77 | ||
| 94 | - | The tests start a separate compositor with temporary runtime/config directories and no terminal or Xwayland. They do not use the running desktop session. Headless tests do not validate physical display timing, DRM leasing or hardware HDR output. | |
| 78 | + | Socketpair tests exercise wire messages, versions, object lifecycle and file descriptors without a compositor. | |
| 95 | 79 | ||
| 96 | 80 | ## Requirements | |
| 97 | 81 | ||
| @@ -101,16 +85,12 @@ The tests start a separate compositor with temporary runtime/config directories | |||
| 101 | 85 | ||
| 102 | 86 | ## License | |
| 103 | 87 | ||
| 104 | - | The transport and scanner are MIT-licensed; see [LICENSE](LICENSE). | |
| 105 | - | Vendored protocol XML and generated bindings retain upstream notices and terms. | |
| 106 | - | In particular, `kdeserverdecoration` is LGPL-2.1-or-later. See | |
| 107 | - | [protocol sources](protocol/SOURCE.md), the generated file headers and the | |
| 108 | - | [included LGPL text](LICENSES/LGPL-2.1-or-later.txt). | |
| 88 | + | MIT; see [LICENSE](LICENSE). | |
| 109 | 89 | ||
| 110 | 90 | ## Contributing | |
| 111 | 91 | ||
| 112 | 92 | Contributions welcome! Areas of focus: | |
| 113 | 93 | - Performance improvements | |
| 114 | - | - Additional protocol object support | |
| 94 | + | - Transport correctness and hardening | |
| 115 | 95 | - Documentation and examples | |
| 116 | 96 | - Benchmark suite⏎̸ | |
M client.go +2 -2
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | // Package wlturbo is a Wayland client transport for Go: connection, framing, | |
| 2 | - | // descriptor passing, object lifecycle and the bootstrap registry. Protocol | |
| 3 | - | // bindings are generated into the protocol/ packages. | |
| 2 | + | // descriptor passing, object lifecycle and the bootstrap registry. Generated | |
| 3 | + | // protocol bindings live in github.com/bnema/go-wayland-bindings (client/). | |
| 4 | 4 | package wlturbo | |
| 5 | 5 | ||
| 6 | 6 | import ( | |
D cmd/wlturbo-scanner/main.go +0 -132
| @@ -1,132 +0,0 @@ | |||
| 1 | - | // Command wlturbo-scanner generates Go bindings from Wayland protocol XML files. | |
| 2 | - | // | |
| 3 | - | // Usage: | |
| 4 | - | // | |
| 5 | - | // wlturbo-scanner [flags] protocol.xml | |
| 6 | - | // | |
| 7 | - | // Flags: | |
| 8 | - | // | |
| 9 | - | // -o, --output Output file path (default: <protocol>_generated.go) | |
| 10 | - | // -p, --package Go package name (default: derived from protocol name) | |
| 11 | - | // -h, --help Show help | |
| 12 | - | // | |
| 13 | - | // Examples: | |
| 14 | - | // | |
| 15 | - | // # Generate bindings for virtual pointer protocol | |
| 16 | - | // wlturbo-scanner -o virtual_pointer.go ../wlr-protocols/unstable/wlr-virtual-pointer-unstable-v1.xml | |
| 17 | - | // | |
| 18 | - | // # Generate with custom package name | |
| 19 | - | // wlturbo-scanner -p vpointer -o vpointer.go protocol.xml | |
| 20 | - | package main | |
| 21 | - | ||
| 22 | - | import ( | |
| 23 | - | "flag" | |
| 24 | - | "fmt" | |
| 25 | - | "log" | |
| 26 | - | "os" | |
| 27 | - | "path/filepath" | |
| 28 | - | "strings" | |
| 29 | - | ||
| 30 | - | "github.com/bnema/wlturbo/internal/scanner" | |
| 31 | - | ) | |
| 32 | - | ||
| 33 | - | func main() { | |
| 34 | - | var ( | |
| 35 | - | outputPath string | |
| 36 | - | packageName string | |
| 37 | - | showHelp bool | |
| 38 | - | crossImports crossFlags | |
| 39 | - | ) | |
| 40 | - | ||
| 41 | - | flag.StringVar(&outputPath, "o", "", "Output file path") | |
| 42 | - | flag.StringVar(&outputPath, "output", "", "Output file path") | |
| 43 | - | flag.StringVar(&packageName, "p", "", "Go package name") | |
| 44 | - | flag.StringVar(&packageName, "package", "", "Go package name") | |
| 45 | - | flag.Var(&crossImports, "import", "Interface=Go import path (repeatable)") | |
| 46 | - | flag.BoolVar(&showHelp, "h", false, "Show help") | |
| 47 | - | flag.BoolVar(&showHelp, "help", false, "Show help") | |
| 48 | - | ||
| 49 | - | flag.Usage = func() { | |
| 50 | - | fmt.Fprintf(os.Stderr, "Usage: %s [flags] protocol.xml\n\n", os.Args[0]) | |
| 51 | - | fmt.Fprintf(os.Stderr, "Generates Go bindings from Wayland protocol XML files.\n\n") | |
| 52 | - | fmt.Fprintf(os.Stderr, "Flags:\n") | |
| 53 | - | flag.PrintDefaults() | |
| 54 | - | fmt.Fprintf(os.Stderr, "\nExamples:\n") | |
| 55 | - | fmt.Fprintf(os.Stderr, " # Generate bindings for virtual pointer protocol\n") | |
| 56 | - | fmt.Fprintf(os.Stderr, " %s -o virtual_pointer.go wlr-virtual-pointer-unstable-v1.xml\n\n", os.Args[0]) | |
| 57 | - | fmt.Fprintf(os.Stderr, " # Generate with custom package name\n") | |
| 58 | - | fmt.Fprintf(os.Stderr, " %s -p vpointer -o vpointer.go protocol.xml\n", os.Args[0]) | |
| 59 | - | } | |
| 60 | - | ||
| 61 | - | flag.Parse() | |
| 62 | - | ||
| 63 | - | if showHelp || flag.NArg() == 0 { | |
| 64 | - | flag.Usage() | |
| 65 | - | if showHelp { | |
| 66 | - | os.Exit(0) | |
| 67 | - | } | |
| 68 | - | os.Exit(1) | |
| 69 | - | } | |
| 70 | - | ||
| 71 | - | xmlPath := flag.Arg(0) | |
| 72 | - | ||
| 73 | - | // Derive output path if not specified | |
| 74 | - | if outputPath == "" { | |
| 75 | - | base := filepath.Base(xmlPath) | |
| 76 | - | base = strings.TrimSuffix(base, filepath.Ext(base)) | |
| 77 | - | outputPath = base + "_generated.go" | |
| 78 | - | } | |
| 79 | - | ||
| 80 | - | // Derive package name if not specified | |
| 81 | - | if packageName == "" { | |
| 82 | - | base := filepath.Base(xmlPath) | |
| 83 | - | base = strings.TrimSuffix(base, filepath.Ext(base)) | |
| 84 | - | ||
| 85 | - | // Clean up common prefixes/suffixes | |
| 86 | - | base = strings.TrimPrefix(base, "wlr-") | |
| 87 | - | base = strings.TrimPrefix(base, "zwlr-") | |
| 88 | - | base = strings.TrimSuffix(base, "-unstable-v1") | |
| 89 | - | base = strings.TrimSuffix(base, "-unstable-v2") | |
| 90 | - | base = strings.TrimSuffix(base, "-stable-v1") | |
| 91 | - | ||
| 92 | - | // Convert to valid Go package name | |
| 93 | - | packageName = strings.ReplaceAll(base, "-", "_") | |
| 94 | - | } | |
| 95 | - | ||
| 96 | - | // Create scanner | |
| 97 | - | s := scanner.NewScanner() | |
| 98 | - | s.CrossPackage = crossImports | |
| 99 | - | ||
| 100 | - | // Parse XML | |
| 101 | - | if err := s.ParseXML(xmlPath); err != nil { | |
| 102 | - | log.Fatalf("Failed to parse XML: %v", err) | |
| 103 | - | } | |
| 104 | - | ||
| 105 | - | // Generate code | |
| 106 | - | code, err := s.Generate(packageName) | |
| 107 | - | if err != nil { | |
| 108 | - | log.Fatalf("Failed to generate code: %v", err) | |
| 109 | - | } | |
| 110 | - | ||
| 111 | - | // Write output with secure permissions | |
| 112 | - | if err := os.WriteFile(outputPath, code, 0600); err != nil { | |
| 113 | - | log.Fatalf("Failed to write output: %v", err) | |
| 114 | - | } | |
| 115 | - | ||
| 116 | - | fmt.Printf("Generated %s (package %s)\n", outputPath, packageName) | |
| 117 | - | } | |
| 118 | - | ||
| 119 | - | type crossFlags map[string]string | |
| 120 | - | ||
| 121 | - | func (f *crossFlags) String() string { return fmt.Sprint(map[string]string(*f)) } | |
| 122 | - | func (f *crossFlags) Set(v string) error { | |
| 123 | - | parts := strings.SplitN(v, "=", 2) | |
| 124 | - | if len(parts) != 2 || parts[0] == "" || parts[1] == "" { | |
| 125 | - | return fmt.Errorf("-import must be interface=GoImportPath") | |
| 126 | - | } | |
| 127 | - | if *f == nil { | |
| 128 | - | *f = make(map[string]string) | |
| 129 | - | } | |
| 130 | - | (*f)[parts[0]] = parts[1] | |
| 131 | - | return nil | |
| 132 | - | } | |
D consumer_test.go +0 -63
| @@ -1,63 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package wlturbo | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "os" | |
| 7 | - | "os/exec" | |
| 8 | - | "path/filepath" | |
| 9 | - | "testing" | |
| 10 | - | ) | |
| 11 | - | ||
| 12 | - | // Run the public socketpair integration against a separate module, with no | |
| 13 | - | // imports from internal/ and no worktree replacement outside its temp go.mod. | |
| 14 | - | func TestExternalConsumer(t *testing.T) { | |
| 15 | - | goBin, err := exec.LookPath("go") | |
| 16 | - | if err != nil { | |
| 17 | - | t.Skip("go executable unavailable: external module integration requires go") | |
| 18 | - | } | |
| 19 | - | root, err := os.Getwd() | |
| 20 | - | if err != nil { | |
| 21 | - | t.Fatal(err) | |
| 22 | - | } | |
| 23 | - | temp := t.TempDir() | |
| 24 | - | mod := "module example.com/wlturbo-consumer\n\ngo 1.27\n\nrequire github.com/bnema/wlturbo v0.0.0\nreplace github.com/bnema/wlturbo => " + root + "\n" | |
| 25 | - | if err := os.WriteFile(filepath.Join(temp, "go.mod"), []byte(mod), 0600); err != nil { | |
| 26 | - | t.Fatal(err) | |
| 27 | - | } | |
| 28 | - | source, err := os.ReadFile(filepath.Join(root, "protocol/core/core_test.go")) | |
| 29 | - | if err != nil { | |
| 30 | - | t.Fatal(err) | |
| 31 | - | } | |
| 32 | - | // The external module has no access to the package's test helpers except | |
| 33 | - | // the ones copied into this temporary module. Compile and exercise only | |
| 34 | - | // the public integration scenarios, including typed key, frame and release. | |
| 35 | - | if err := os.WriteFile(filepath.Join(temp, "consumer_test.go"), source, 0600); err != nil { | |
| 36 | - | t.Fatal(err) | |
| 37 | - | } | |
| 38 | - | // Keep the extension fake server in a separate package: both fixtures | |
| 39 | - | // independently own their socketpair helpers. | |
| 40 | - | extension, err := os.ReadFile(filepath.Join(root, "protocol/extensions_test.go")) | |
| 41 | - | if err != nil { | |
| 42 | - | t.Fatal(err) | |
| 43 | - | } | |
| 44 | - | if err := os.Mkdir(filepath.Join(temp, "extensions"), 0700); err != nil { | |
| 45 | - | t.Fatal(err) | |
| 46 | - | } | |
| 47 | - | if err := os.WriteFile(filepath.Join(temp, "extensions", "extensions_test.go"), extension, 0600); err != nil { | |
| 48 | - | t.Fatal(err) | |
| 49 | - | } | |
| 50 | - | negotiation, err := os.ReadFile(filepath.Join(root, "protocol/negotiation_test.go")) | |
| 51 | - | if err != nil { | |
| 52 | - | t.Fatal(err) | |
| 53 | - | } | |
| 54 | - | if err := os.WriteFile(filepath.Join(temp, "extensions", "negotiation_test.go"), negotiation, 0600); err != nil { | |
| 55 | - | t.Fatal(err) | |
| 56 | - | } | |
| 57 | - | cmd := exec.Command(goBin, "test", "-run", "TestGeneratedCoreOverSocketpair|TestBufferReleaseAndOfferChild|TestExtensionsOverSocketpair|TestAnnouncedVersionNegotiation", "./...") | |
| 58 | - | cmd.Dir = temp | |
| 59 | - | cmd.Env = append(os.Environ(), "GOWORK=off", "GOFLAGS=-mod=mod") | |
| 60 | - | if output, err := cmd.CombinedOutput(); err != nil { | |
| 61 | - | t.Fatalf("external consumer: %v\n%s", err, output) | |
| 62 | - | } | |
| 63 | - | } | |
D docs/protocol-migration.md +0 -40
| @@ -1,40 +0,0 @@ | |||
| 1 | - | # Canonical core / migration (v0.x) | |
| 2 | - | ||
| 3 | - | `protocol/core` replaces root-package and `wl` shim core object types. Bootstrap | |
| 4 | - | `Display`, `Registry`, `Context`, and `BaseProxy` remain in the root/`wl` | |
| 5 | - | transport. Bind globals using `core.NewCompositor(display.Context())`, | |
| 6 | - | `core.NewSeat(display.Context())`, etc. and `display.Registry().Bind(name, | |
| 7 | - | core.CompositorInterface, version, compositor)`. Requests create typed registered | |
| 8 | - | children (`seat.GetKeyboard()`, `surface.Frame()`, `shm.CreatePool()`) and | |
| 9 | - | server-side `new_id` events register concrete objects before invoking handlers. | |
| 10 | - | Do not overwrite registered objects with a second wrapper. | |
| 11 | - | ||
| 12 | - | Breaking changes: `wlturbo`/`wl` `Seat`, `Surface`, `Pointer`, `Keyboard`, | |
| 13 | - | `Touch`, `Output`, `Region`, `Compositor`, their constructors, and seat | |
| 14 | - | capability aliases have moved to `protocol/core`. Generated methods accept | |
| 15 | - | concrete core objects and return concrete children, not `wl.Object`. Legacy | |
| 16 | - | raw `Event.Fd()` is not for generated events; generated FD handlers receive | |
| 17 | - | `*wlturbo.OwnedFD` with `Take() (int,error)` or `Close()`; second and later | |
| 18 | - | handlers receive nil FD. On a successful full send a generated FD request | |
| 19 | - | closes the local descriptor; on error the caller keeps it. `Registry.BindID` | |
| 20 | - | remains for legacy callers but cannot register typed event dispatch: prefer | |
| 21 | - | `Bind` and generated constructors. Unrecognized custom-proxy event opcodes | |
| 22 | - | now fail unless declared via `Display.RegisterEventSignature`. | |
| 23 | - | ||
| 24 | - | The scanner accepts `-import wl_surface=github.com/bnema/wlturbo/protocol/core` | |
| 25 | - | (repeat for each external type); local XML definitions take precedence, then | |
| 26 | - | explicit external mapping, then only bootstrap display/registry. Generate with | |
| 27 | - | `GOWORK=off go generate ./...`; metadata and XML license are in | |
| 28 | - | `protocol/SOURCE.md`. Extension packages under `protocol/` use the same scanner | |
| 29 | - | and public core mappings; the generator carries no compositor policy. | |
| 30 | - | ||
| 31 | - | Generated requests use `Context.RequestArgs` with typed `Arg` values to avoid | |
| 32 | - | boxing numeric arguments. Custom proxies may use the same API; `Context.Request` | |
| 33 | - | and the raw send methods remain available. Both request APIs share version, | |
| 34 | - | child-object, destructor and descriptor lifecycle handling. Strings and arrays | |
| 35 | - | passed as arguments are borrowed until the synchronous request returns. | |
| 36 | - | ||
| 37 | - | For client code in compositor tests, replace handwritten protocol proxies with | |
| 38 | - | these generated constructors and typed handlers. Keep compositor-side server | |
| 39 | - | implementations in the compositor repository. Negotiate optional globals and | |
| 40 | - | handle their absence rather than testing the compositor's name. | |
D internal/scanner/license_test.go +0 -53
| @@ -1,53 +0,0 @@ | |||
| 1 | - | package scanner | |
| 2 | - | ||
| 3 | - | import ( | |
| 4 | - | "crypto/sha256" | |
| 5 | - | "fmt" | |
| 6 | - | "os" | |
| 7 | - | "strings" | |
| 8 | - | "testing" | |
| 9 | - | ) | |
| 10 | - | ||
| 11 | - | func TestIncludedLGPLLicense(t *testing.T) { | |
| 12 | - | content, err := os.ReadFile("../../LICENSES/LGPL-2.1-or-later.txt") | |
| 13 | - | if err != nil { | |
| 14 | - | t.Fatal(err) | |
| 15 | - | } | |
| 16 | - | const expected = "5749785c8bdefafcb5d798270ed0a967036fe2ca63dcedade1627565dfef81d2" | |
| 17 | - | if got := fmt.Sprintf("%x", sha256.Sum256(content)); got != expected { | |
| 18 | - | t.Fatalf("LGPL text checksum %s, want %s", got, expected) | |
| 19 | - | } | |
| 20 | - | } | |
| 21 | - | ||
| 22 | - | func TestGeneratedSourceRetainsProtocolLicense(t *testing.T) { | |
| 23 | - | for _, source := range []string{ | |
| 24 | - | "../../protocol/kdeserverdecoration/server-decoration.xml", | |
| 25 | - | "../../protocol/layershell/wlr-layer-shell-unstable-v1.xml", | |
| 26 | - | "../../protocol/wayland.xml", | |
| 27 | - | } { | |
| 28 | - | t.Run(source, func(t *testing.T) { | |
| 29 | - | s := NewScanner() | |
| 30 | - | if err := s.ParseXML(source); err != nil { | |
| 31 | - | t.Fatal(err) | |
| 32 | - | } | |
| 33 | - | s.CrossPackage = map[string]string{ | |
| 34 | - | "wl_surface": "github.com/bnema/wlturbo/protocol/core", | |
| 35 | - | "wl_output": "github.com/bnema/wlturbo/protocol/core", | |
| 36 | - | "xdg_popup": "github.com/bnema/wlturbo/protocol/xdgshell", | |
| 37 | - | } | |
| 38 | - | generated, err := s.Generate("core") | |
| 39 | - | if err != nil { | |
| 40 | - | t.Fatal(err) | |
| 41 | - | } | |
| 42 | - | header, _, ok := strings.Cut(string(generated), "\npackage core") | |
| 43 | - | if !ok { | |
| 44 | - | t.Fatal("package declaration missing") | |
| 45 | - | } | |
| 46 | - | for _, line := range strings.Split(strings.TrimSpace(s.protocol.Copyright), "\n") { | |
| 47 | - | if text := strings.TrimSpace(line); text != "" && !strings.Contains(header, text) { | |
| 48 | - | t.Errorf("upstream license line missing from header: %q", text) | |
| 49 | - | } | |
| 50 | - | } | |
| 51 | - | }) | |
| 52 | - | } | |
| 53 | - | } | |
D internal/scanner/protocols_test.go +0 -113
| @@ -1,113 +0,0 @@ | |||
| 1 | - | package scanner | |
| 2 | - | ||
| 3 | - | import ( | |
| 4 | - | "bytes" | |
| 5 | - | "os" | |
| 6 | - | "path/filepath" | |
| 7 | - | "strings" | |
| 8 | - | "testing" | |
| 9 | - | ) | |
| 10 | - | ||
| 11 | - | // Check every checked-in binding against its generation command, including | |
| 12 | - | // external type mappings. Regeneration must not depend on the host's XML files. | |
| 13 | - | func TestVendoredProtocolsReproduce(t *testing.T) { | |
| 14 | - | root := filepath.Join("..", "..", "protocol") | |
| 15 | - | referenced := make(map[string]bool) | |
| 16 | - | err := filepath.WalkDir(root, func(path string, entry os.DirEntry, err error) error { | |
| 17 | - | if err != nil { | |
| 18 | - | return err | |
| 19 | - | } | |
| 20 | - | if entry.IsDir() || entry.Name() != "generate.go" { | |
| 21 | - | return nil | |
| 22 | - | } | |
| 23 | - | content, err := os.ReadFile(path) | |
| 24 | - | if err != nil { | |
| 25 | - | return err | |
| 26 | - | } | |
| 27 | - | for _, line := range strings.Split(string(content), "\n") { | |
| 28 | - | if !strings.HasPrefix(line, "//go:generate go run ") { | |
| 29 | - | continue | |
| 30 | - | } | |
| 31 | - | fields := strings.Fields(line) | |
| 32 | - | if len(fields) < 5 || !strings.HasSuffix(fields[3], "/cmd/wlturbo-scanner") { | |
| 33 | - | t.Fatalf("%s: expected direct go run of cmd/wlturbo-scanner", path) | |
| 34 | - | } | |
| 35 | - | args := fields[4:] | |
| 36 | - | var pkg, output, input string | |
| 37 | - | imports := make(map[string]string) | |
| 38 | - | for i := 0; i < len(args); i++ { | |
| 39 | - | switch args[i] { | |
| 40 | - | case "-p", "-o", "-import": | |
| 41 | - | if i+1 == len(args) { | |
| 42 | - | t.Fatalf("%s: missing value for %s", path, args[i]) | |
| 43 | - | } | |
| 44 | - | flag, value := args[i], args[i+1] | |
| 45 | - | i++ | |
| 46 | - | switch flag { | |
| 47 | - | case "-p": | |
| 48 | - | pkg = value | |
| 49 | - | case "-o": | |
| 50 | - | output = value | |
| 51 | - | case "-import": | |
| 52 | - | iface, target, ok := strings.Cut(value, "=") | |
| 53 | - | if !ok { | |
| 54 | - | t.Fatalf("%s: invalid import %q", path, value) | |
| 55 | - | } | |
| 56 | - | imports[iface] = target | |
| 57 | - | } | |
| 58 | - | default: | |
| 59 | - | if strings.HasPrefix(args[i], "-") || input != "" { | |
| 60 | - | t.Fatalf("%s: unexpected generation argument %q", path, args[i]) | |
| 61 | - | } | |
| 62 | - | input = args[i] | |
| 63 | - | } | |
| 64 | - | } | |
| 65 | - | if pkg == "" || output == "" || input == "" { | |
| 66 | - | t.Fatalf("%s: incomplete generation command", path) | |
| 67 | - | } | |
| 68 | - | dir := filepath.Dir(path) | |
| 69 | - | xmlPath := filepath.Clean(filepath.Join(dir, input)) | |
| 70 | - | if referenced[xmlPath] { | |
| 71 | - | t.Fatalf("%s generated more than once", xmlPath) | |
| 72 | - | } | |
| 73 | - | referenced[xmlPath] = true | |
| 74 | - | t.Run(pkg, func(t *testing.T) { | |
| 75 | - | s := NewScanner() | |
| 76 | - | s.CrossPackage = imports | |
| 77 | - | if err := s.ParseXML(xmlPath); err != nil { | |
| 78 | - | t.Fatal(err) | |
| 79 | - | } | |
| 80 | - | generated, err := s.Generate(pkg) | |
| 81 | - | if err != nil { | |
| 82 | - | t.Fatal(err) | |
| 83 | - | } | |
| 84 | - | checkedIn, err := os.ReadFile(filepath.Join(dir, output)) | |
| 85 | - | if err != nil { | |
| 86 | - | t.Fatal(err) | |
| 87 | - | } | |
| 88 | - | if !bytes.Equal(generated, checkedIn) { | |
| 89 | - | t.Fatal("bindings are stale; run GOWORK=off go generate ./...") | |
| 90 | - | } | |
| 91 | - | }) | |
| 92 | - | } | |
| 93 | - | return nil | |
| 94 | - | }) | |
| 95 | - | if err != nil { | |
| 96 | - | t.Fatal(err) | |
| 97 | - | } | |
| 98 | - | if len(referenced) == 0 { | |
| 99 | - | t.Fatal("no vendored protocols found") | |
| 100 | - | } | |
| 101 | - | err = filepath.WalkDir(root, func(path string, entry os.DirEntry, err error) error { | |
| 102 | - | if err != nil { | |
| 103 | - | return err | |
| 104 | - | } | |
| 105 | - | if !entry.IsDir() && filepath.Ext(path) == ".xml" && !referenced[path] { | |
| 106 | - | t.Errorf("%s has no generation command", path) | |
| 107 | - | } | |
| 108 | - | return nil | |
| 109 | - | }) | |
| 110 | - | if err != nil { | |
| 111 | - | t.Fatal(err) | |
| 112 | - | } | |
| 113 | - | } | |
D internal/scanner/requestargs_test.go +0 -243
| @@ -1,243 +0,0 @@ | |||
| 1 | - | package scanner | |
| 2 | - | ||
| 3 | - | import ( | |
| 4 | - | "os" | |
| 5 | - | "os/exec" | |
| 6 | - | "path/filepath" | |
| 7 | - | "strings" | |
| 8 | - | "testing" | |
| 9 | - | ) | |
| 10 | - | ||
| 11 | - | const requestArgsXML = `<protocol name="argsfix"> | |
| 12 | - | <interface name="args_obj" version="1"> | |
| 13 | - | <request name="mixed"> | |
| 14 | - | <arg name="serial" type="uint"/><arg name="dx" type="int"/><arg name="fx" type="fixed"/> | |
| 15 | - | <arg name="name" type="string"/><arg name="blob" type="array"/> | |
| 16 | - | <arg name="peer" type="object" interface="args_obj" allow-null="true"/> | |
| 17 | - | </request> | |
| 18 | - | <request name="make"><arg name="id" type="new_id" interface="args_obj"/><arg name="n" type="uint"/></request> | |
| 19 | - | <request name="give"><arg name="tag" type="string"/><arg name="fd" type="fd"/><arg name="size" type="uint"/></request> | |
| 20 | - | <request name="destroy" type="destructor"/> | |
| 21 | - | </interface></protocol>` | |
| 22 | - | ||
| 23 | - | func generateArgsFixture(t *testing.T) string { | |
| 24 | - | t.Helper() | |
| 25 | - | path := filepath.Join(t.TempDir(), "argsfix.xml") | |
| 26 | - | if err := os.WriteFile(path, []byte(requestArgsXML), 0600); err != nil { | |
| 27 | - | t.Fatal(err) | |
| 28 | - | } | |
| 29 | - | s := NewScanner() | |
| 30 | - | if err := s.ParseXML(path); err != nil { | |
| 31 | - | t.Fatal(err) | |
| 32 | - | } | |
| 33 | - | b, err := s.Generate("argsfix") | |
| 34 | - | if err != nil { | |
| 35 | - | t.Fatal(err) | |
| 36 | - | } | |
| 37 | - | return string(b) | |
| 38 | - | } | |
| 39 | - | ||
| 40 | - | // Generated requests must use typed arguments only: no interface{} boxing | |
| 41 | - | // path and no uintptr placeholder for descriptors. | |
| 42 | - | func TestGeneratedRequestsUseTypedArgs(t *testing.T) { | |
| 43 | - | text := generateArgsFixture(t) | |
| 44 | - | for _, want := range []string{ | |
| 45 | - | "RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: \"args_obj.mixed\"}, wl.ArgUint(serial), wl.ArgInt(dx), wl.ArgFixed(fx), wl.ArgString(name), wl.ArgArray(blob), wl.ArgObject(arg5))", | |
| 46 | - | "Child: child}, wl.ArgObject(child), wl.ArgUint(n))", | |
| 47 | - | "FDs: []int{fd}}, wl.ArgString(tag), wl.ArgFD(), wl.ArgUint(size))", | |
| 48 | - | "Destructor: true})", | |
| 49 | - | } { | |
| 50 | - | if !strings.Contains(text, want) { | |
| 51 | - | t.Errorf("generated code missing %q\n%s", want, text) | |
| 52 | - | } | |
| 53 | - | } | |
| 54 | - | for _, bad := range []string{".Request(wl.Request", "uintptr("} { | |
| 55 | - | if strings.Contains(text, bad) { | |
| 56 | - | t.Errorf("generated code still contains %q", bad) | |
| 57 | - | } | |
| 58 | - | } | |
| 59 | - | } | |
| 60 | - | ||
| 61 | - | // The generated requests compile against the transport, put the exact wire | |
| 62 | - | // bytes on the socket, and do not allocate for realistic numeric values. | |
| 63 | - | func TestGeneratedRequestsWireAndAllocations(t *testing.T) { | |
| 64 | - | goBin, err := exec.LookPath("go") | |
| 65 | - | if err != nil { | |
| 66 | - | t.Skip("go unavailable") | |
| 67 | - | } | |
| 68 | - | root, err := filepath.Abs("../..") | |
| 69 | - | if err != nil { | |
| 70 | - | t.Fatal(err) | |
| 71 | - | } | |
| 72 | - | dir := t.TempDir() | |
| 73 | - | write := func(name, content string) { | |
| 74 | - | if err := os.WriteFile(filepath.Join(dir, name), []byte(content), 0600); err != nil { | |
| 75 | - | t.Fatal(err) | |
| 76 | - | } | |
| 77 | - | } | |
| 78 | - | write("args.go", generateArgsFixture(t)) | |
| 79 | - | write("go.mod", "module example.com/argsfix\n\ngo 1.27\n\nrequire github.com/bnema/wlturbo v0.0.0\nreplace github.com/bnema/wlturbo => "+root+"\n") | |
| 80 | - | write("args_test.go", `package argsfix | |
| 81 | - | ||
| 82 | - | import ( | |
| 83 | - | "bytes" | |
| 84 | - | "net" | |
| 85 | - | "os" | |
| 86 | - | "testing" | |
| 87 | - | "time" | |
| 88 | - | ||
| 89 | - | "github.com/bnema/wlturbo" | |
| 90 | - | "golang.org/x/sys/unix" | |
| 91 | - | ) | |
| 92 | - | ||
| 93 | - | type sink struct{ last []byte } | |
| 94 | - | ||
| 95 | - | func (c *sink) Read([]byte) (int, error) { return 0, net.ErrClosed } | |
| 96 | - | func (c *sink) Write(p []byte) (int, error) { | |
| 97 | - | c.last = append(c.last[:0], p...) | |
| 98 | - | return len(p), nil | |
| 99 | - | } | |
| 100 | - | func (c *sink) Close() error { return nil } | |
| 101 | - | func (c *sink) LocalAddr() net.Addr { return a{} } | |
| 102 | - | func (c *sink) RemoteAddr() net.Addr { return a{} } | |
| 103 | - | func (c *sink) SetDeadline(time.Time) error { return nil } | |
| 104 | - | func (c *sink) SetReadDeadline(time.Time) error { return nil } | |
| 105 | - | func (c *sink) SetWriteDeadline(time.Time) error { return nil } | |
| 106 | - | ||
| 107 | - | type a struct{} | |
| 108 | - | ||
| 109 | - | func (a) Network() string { return "t" } | |
| 110 | - | func (a) String() string { return "t" } | |
| 111 | - | ||
| 112 | - | func setup(t testing.TB) (*wlturbo.Display, *sink, *ArgsObj) { | |
| 113 | - | c := &sink{} | |
| 114 | - | d, err := wlturbo.ConnectFromConn(c) | |
| 115 | - | if err != nil { | |
| 116 | - | t.Fatal(err) | |
| 117 | - | } | |
| 118 | - | o := NewArgsObj(d.Context()) | |
| 119 | - | o.SetID(d.AllocateID()) | |
| 120 | - | d.Context().Register(o) | |
| 121 | - | return d, c, o | |
| 122 | - | } | |
| 123 | - | ||
| 124 | - | func TestMixedWire(t *testing.T) { | |
| 125 | - | _, c, o := setup(t) | |
| 126 | - | peer := NewArgsObj(o.Context()) | |
| 127 | - | peer.SetID(0x1234) | |
| 128 | - | if err := o.Mixed(1000, -2, wlturbo.Fixed(512), "ab", []byte{9, 8, 7}, peer); err != nil { | |
| 129 | - | t.Fatal(err) | |
| 130 | - | } | |
| 131 | - | want := []byte{ | |
| 132 | - | byte(o.ID()), 0, 0, 0, 0, 0, 40, 0, | |
| 133 | - | 0xe8, 3, 0, 0, | |
| 134 | - | 0xfe, 0xff, 0xff, 0xff, | |
| 135 | - | 0, 2, 0, 0, | |
| 136 | - | 3, 0, 0, 0, 'a', 'b', 0, 0, | |
| 137 | - | 3, 0, 0, 0, 9, 8, 7, 0, | |
| 138 | - | 0x34, 0x12, 0, 0, | |
| 139 | - | } | |
| 140 | - | if !bytes.Equal(c.last, want) { | |
| 141 | - | t.Fatalf("got %x want %x", c.last, want) | |
| 142 | - | } | |
| 143 | - | if err := o.Mixed(1, 2, 3, "", nil, nil); err != nil { | |
| 144 | - | t.Fatal(err) | |
| 145 | - | } | |
| 146 | - | if got := c.last[len(c.last)-4:]; !bytes.Equal(got, []byte{0, 0, 0, 0}) { | |
| 147 | - | t.Fatalf("nil object = %x", got) | |
| 148 | - | } | |
| 149 | - | } | |
| 150 | - | ||
| 151 | - | func TestMixedAllocFree(t *testing.T) { | |
| 152 | - | _, _, o := setup(t) | |
| 153 | - | blob := []byte("blob") | |
| 154 | - | n := testing.AllocsPerRun(200, func() { | |
| 155 | - | if err := o.Mixed(123456, -70000, wlturbo.Fixed(1<<20), "hello", blob, nil); err != nil { | |
| 156 | - | t.Fatal(err) | |
| 157 | - | } | |
| 158 | - | }) | |
| 159 | - | if n != 0 { | |
| 160 | - | t.Fatalf("Mixed: %v allocs/op, want 0", n) | |
| 161 | - | } | |
| 162 | - | } | |
| 163 | - | ||
| 164 | - | func TestChildAndDestructor(t *testing.T) { | |
| 165 | - | d, c, o := setup(t) | |
| 166 | - | kid, err := o.Make(77777) | |
| 167 | - | if err != nil { | |
| 168 | - | t.Fatal(err) | |
| 169 | - | } | |
| 170 | - | if kid.ID() == 0 || c.last[8] != byte(kid.ID()) { | |
| 171 | - | t.Fatalf("child id %d not on the wire: %x", kid.ID(), c.last) | |
| 172 | - | } | |
| 173 | - | if err := o.Destroy(); err != nil { | |
| 174 | - | t.Fatal(err) | |
| 175 | - | } | |
| 176 | - | n := len(c.last) | |
| 177 | - | c.last = c.last[:0] | |
| 178 | - | if err := o.Destroy(); err == nil { | |
| 179 | - | t.Fatal("second destructor succeeded") | |
| 180 | - | } | |
| 181 | - | if len(c.last) != 0 || n == 0 { | |
| 182 | - | t.Fatal("wrote after destructor") | |
| 183 | - | } | |
| 184 | - | _ = d | |
| 185 | - | } | |
| 186 | - | ||
| 187 | - | func TestFDRequest(t *testing.T) { | |
| 188 | - | sp, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0) | |
| 189 | - | if err != nil { | |
| 190 | - | t.Fatal(err) | |
| 191 | - | } | |
| 192 | - | fa, fb := os.NewFile(uintptr(sp[0]), "a"), os.NewFile(uintptr(sp[1]), "b") | |
| 193 | - | ca, err := net.FileConn(fa) | |
| 194 | - | fa.Close() | |
| 195 | - | if err != nil { | |
| 196 | - | fb.Close() | |
| 197 | - | t.Fatal(err) | |
| 198 | - | } | |
| 199 | - | defer ca.Close() | |
| 200 | - | cb, err := net.FileConn(fb) | |
| 201 | - | fb.Close() | |
| 202 | - | if err != nil { | |
| 203 | - | t.Fatal(err) | |
| 204 | - | } | |
| 205 | - | defer cb.Close() | |
| 206 | - | d, err := wlturbo.ConnectFromConn(ca) | |
| 207 | - | if err != nil { | |
| 208 | - | t.Fatal(err) | |
| 209 | - | } | |
| 210 | - | defer d.Close() | |
| 211 | - | o := NewArgsObj(d.Context()) | |
| 212 | - | o.SetID(d.AllocateID()) | |
| 213 | - | d.Context().Register(o) | |
| 214 | - | fd, err := unix.Open(os.DevNull, unix.O_RDONLY|unix.O_CLOEXEC, 0) | |
| 215 | - | if err != nil { | |
| 216 | - | t.Fatal(err) | |
| 217 | - | } | |
| 218 | - | if err := o.Give("t", fd, 5); err != nil { | |
| 219 | - | t.Fatal(err) | |
| 220 | - | } | |
| 221 | - | if _, err := unix.FcntlInt(uintptr(fd), unix.F_GETFD, 0); err == nil { | |
| 222 | - | t.Fatal("fd not closed after send") | |
| 223 | - | } | |
| 224 | - | // The connection first sends wl_display.get_registry (12 bytes). | |
| 225 | - | buf := make([]byte, 12+8+8+4) | |
| 226 | - | oob := make([]byte, unix.CmsgSpace(4)) | |
| 227 | - | n, oobn, _, _, err := cb.(*net.UnixConn).ReadMsgUnix(buf, oob) | |
| 228 | - | if err != nil || n != len(buf) || oobn == 0 { | |
| 229 | - | t.Fatalf("n=%d oobn=%d err=%v", n, oobn, err) | |
| 230 | - | } | |
| 231 | - | // The descriptor has no body word: string(8) + uint(4) only. | |
| 232 | - | if buf[12+4] != 2 || buf[12+8+8] != 5 || buf[12+6] != 20 { | |
| 233 | - | t.Fatalf("message = %x", buf[12:]) | |
| 234 | - | } | |
| 235 | - | } | |
| 236 | - | `) | |
| 237 | - | cmd := exec.Command(goBin, "test", "./...") | |
| 238 | - | cmd.Dir = dir | |
| 239 | - | cmd.Env = append(os.Environ(), "GOWORK=off", "GOFLAGS=-mod=mod") | |
| 240 | - | if out, err := cmd.CombinedOutput(); err != nil { | |
| 241 | - | t.Fatalf("generated request test: %v\n%s", err, out) | |
| 242 | - | } | |
| 243 | - | } | |
D internal/scanner/scanner.go +0 -748
| @@ -1,748 +0,0 @@ | |||
| 1 | - | // Package scanner generates WLTurbo-backed Go bindings from Wayland protocol | |
| 2 | - | // XML files. | |
| 3 | - | // | |
| 4 | - | // The generated code owns protocol semantics only: it embeds wl.BaseProxy, | |
| 5 | - | // allocates and registers child objects through the wl.Context, sends requests | |
| 6 | - | // through that context, and dispatches typed events to registered handlers. | |
| 7 | - | // Message framing, descriptor passing and connection lifetime stay in the | |
| 8 | - | // transport, so a generated binding never opens a socket or writes a header. | |
| 9 | - | package scanner | |
| 10 | - | ||
| 11 | - | import ( | |
| 12 | - | "bytes" | |
| 13 | - | "encoding/xml" | |
| 14 | - | "fmt" | |
| 15 | - | "go/format" | |
| 16 | - | "io" | |
| 17 | - | "os" | |
| 18 | - | "path/filepath" | |
| 19 | - | "sort" | |
| 20 | - | "strings" | |
| 21 | - | "text/template" | |
| 22 | - | ) | |
| 23 | - | ||
| 24 | - | // TransportImport is the import path generated bindings use for the Wayland | |
| 25 | - | // transport. | |
| 26 | - | const TransportImport = "github.com/bnema/wlturbo/wl" | |
| 27 | - | ||
| 28 | - | // Protocol represents a Wayland protocol specification | |
| 29 | - | type Protocol struct { | |
| 30 | - | XMLName xml.Name `xml:"protocol"` | |
| 31 | - | Name string `xml:"name,attr"` | |
| 32 | - | Copyright string `xml:"copyright"` | |
| 33 | - | Description *Description `xml:"description"` | |
| 34 | - | Interfaces []Interface `xml:"interface"` | |
| 35 | - | } | |
| 36 | - | ||
| 37 | - | // Interface represents a Wayland interface in the protocol | |
| 38 | - | type Interface struct { | |
| 39 | - | Name string `xml:"name,attr"` | |
| 40 | - | Version int `xml:"version,attr"` | |
| 41 | - | Description *Description `xml:"description"` | |
| 42 | - | Requests []Request `xml:"request"` | |
| 43 | - | Events []Event `xml:"event"` | |
| 44 | - | Enums []Enum `xml:"enum"` | |
| 45 | - | } | |
| 46 | - | ||
| 47 | - | // Request represents a client-to-server message | |
| 48 | - | type Request struct { | |
| 49 | - | Name string `xml:"name,attr"` | |
| 50 | - | Type string `xml:"type,attr"` // "destructor" or empty | |
| 51 | - | Since int `xml:"since,attr"` | |
| 52 | - | Description *Description `xml:"description"` | |
| 53 | - | Args []Arg `xml:"arg"` | |
| 54 | - | } | |
| 55 | - | ||
| 56 | - | // Event represents a server-to-client message | |
| 57 | - | type Event struct { | |
| 58 | - | Type string `xml:"type,attr"` | |
| 59 | - | Name string `xml:"name,attr"` | |
| 60 | - | Since int `xml:"since,attr"` | |
| 61 | - | Description *Description `xml:"description"` | |
| 62 | - | Args []Arg `xml:"arg"` | |
| 63 | - | } | |
| 64 | - | ||
| 65 | - | // Arg represents a message argument | |
| 66 | - | type Arg struct { | |
| 67 | - | Name string `xml:"name,attr"` | |
| 68 | - | Type string `xml:"type,attr"` | |
| 69 | - | Summary string `xml:"summary,attr"` | |
| 70 | - | Interface string `xml:"interface,attr"` | |
| 71 | - | AllowNull bool `xml:"allow-null,attr"` | |
| 72 | - | Enum string `xml:"enum,attr"` | |
| 73 | - | } | |
| 74 | - | ||
| 75 | - | // Enum represents an enumeration type | |
| 76 | - | type Enum struct { | |
| 77 | - | Name string `xml:"name,attr"` | |
| 78 | - | Since int `xml:"since,attr"` | |
| 79 | - | Bitfield bool `xml:"bitfield,attr"` | |
| 80 | - | Description *Description `xml:"description"` | |
| 81 | - | Entries []Entry `xml:"entry"` | |
| 82 | - | } | |
| 83 | - | ||
| 84 | - | // Entry represents an enum value | |
| 85 | - | type Entry struct { | |
| 86 | - | Name string `xml:"name,attr"` | |
| 87 | - | Value string `xml:"value,attr"` | |
| 88 | - | Summary string `xml:"summary,attr"` | |
| 89 | - | Since int `xml:"since,attr"` | |
| 90 | - | } | |
| 91 | - | ||
| 92 | - | // Description represents documentation | |
| 93 | - | type Description struct { | |
| 94 | - | Summary string `xml:"summary,attr"` | |
| 95 | - | Text string `xml:",chardata"` | |
| 96 | - | } | |
| 97 | - | ||
| 98 | - | // Scanner generates Go bindings from Wayland protocol XML | |
| 99 | - | type Scanner struct { | |
| 100 | - | protocol *Protocol | |
| 101 | - | source string | |
| 102 | - | // CrossPackage maps interface names to Go package import paths. Local wins. | |
| 103 | - | CrossPackage map[string]string | |
| 104 | - | } | |
| 105 | - | ||
| 106 | - | // NewScanner creates a new protocol scanner | |
| 107 | - | func NewScanner() *Scanner { | |
| 108 | - | return &Scanner{} | |
| 109 | - | } | |
| 110 | - | ||
| 111 | - | // ParseXML parses a Wayland protocol XML file | |
| 112 | - | func (s *Scanner) ParseXML(path string) error { | |
| 113 | - | file, err := os.Open(path) | |
| 114 | - | if err != nil { | |
| 115 | - | return fmt.Errorf("failed to open XML file: %w", err) | |
| 116 | - | } | |
| 117 | - | defer func() { _ = file.Close() }() | |
| 118 | - | ||
| 119 | - | data, err := io.ReadAll(file) | |
| 120 | - | if err != nil { | |
| 121 | - | return fmt.Errorf("failed to read XML file: %w", err) | |
| 122 | - | } | |
| 123 | - | ||
| 124 | - | var protocol Protocol | |
| 125 | - | if err := xml.Unmarshal(data, &protocol); err != nil { | |
| 126 | - | return fmt.Errorf("failed to parse XML: %w", err) | |
| 127 | - | } | |
| 128 | - | ||
| 129 | - | s.protocol = &protocol | |
| 130 | - | // Only the base name is recorded: generated output must not depend on the | |
| 131 | - | // path the XML happened to be read from. | |
| 132 | - | s.source = filepath.Base(path) | |
| 133 | - | return nil | |
| 134 | - | } | |
| 135 | - | ||
| 136 | - | // Generate creates Go source code for the parsed protocol | |
| 137 | - | func (s *Scanner) Generate(packageName string) ([]byte, error) { | |
| 138 | - | if s.protocol == nil { | |
| 139 | - | return nil, fmt.Errorf("no protocol parsed") | |
| 140 | - | } | |
| 141 | - | ||
| 142 | - | data, err := s.prepareTemplateData(packageName) | |
| 143 | - | if err != nil { | |
| 144 | - | return nil, err | |
| 145 | - | } | |
| 146 | - | ||
| 147 | - | var buf bytes.Buffer | |
| 148 | - | tmpl := template.Must(template.New("protocol").Parse(protocolTemplate)) | |
| 149 | - | if err := tmpl.Execute(&buf, data); err != nil { | |
| 150 | - | return nil, fmt.Errorf("failed to execute template: %w", err) | |
| 151 | - | } | |
| 152 | - | ||
| 153 | - | formatted, err := format.Source(buf.Bytes()) | |
| 154 | - | if err != nil { | |
| 155 | - | return buf.Bytes(), fmt.Errorf("failed to format generated code: %w", err) | |
| 156 | - | } | |
| 157 | - | return formatted, nil | |
| 158 | - | } | |
| 159 | - | ||
| 160 | - | // templateData holds data for template generation | |
| 161 | - | type templateData struct { | |
| 162 | - | Package string | |
| 163 | - | Protocol string | |
| 164 | - | Source string | |
| 165 | - | Copyright string | |
| 166 | - | ImportBlock string | |
| 167 | - | Constants []constantData | |
| 168 | - | Interfaces []interfaceData | |
| 169 | - | } | |
| 170 | - | ||
| 171 | - | type interfaceData struct { | |
| 172 | - | Name string | |
| 173 | - | GoName string | |
| 174 | - | Version int | |
| 175 | - | HasEvents bool | |
| 176 | - | SignatureCases []signatureCase | |
| 177 | - | Requests []requestData | |
| 178 | - | Events []eventData | |
| 179 | - | } | |
| 180 | - | ||
| 181 | - | type signatureCase struct { | |
| 182 | - | Opcode int | |
| 183 | - | Signature string | |
| 184 | - | } | |
| 185 | - | type requestData struct { | |
| 186 | - | Name string | |
| 187 | - | GoName string | |
| 188 | - | Doc string | |
| 189 | - | Opcode int | |
| 190 | - | Destructor bool | |
| 191 | - | Since int | |
| 192 | - | Params string | |
| 193 | - | Results string | |
| 194 | - | ArgPreparations []string | |
| 195 | - | CreatesChild bool | |
| 196 | - | ChildVar string | |
| 197 | - | ChildType string | |
| 198 | - | ChildFactory string | |
| 199 | - | ErrorReturn string | |
| 200 | - | HasFDs bool | |
| 201 | - | FDList string | |
| 202 | - | ArgList string | |
| 203 | - | } | |
| 204 | - | ||
| 205 | - | // argSlot is one positional argument of a request, in declaration order. A | |
| 206 | - | // new_id slot is filled in once the child object has been created. | |
| 207 | - | type argSlot struct { | |
| 208 | - | newID bool | |
| 209 | - | expr string | |
| 210 | - | } | |
| 211 | - | ||
| 212 | - | type eventData struct { | |
| 213 | - | HasFD bool | |
| 214 | - | ServerDestroy bool | |
| 215 | - | FDNames []string | |
| 216 | - | Name string | |
| 217 | - | GoName string | |
| 218 | - | Opcode int | |
| 219 | - | HandlerField string | |
| 220 | - | HandlerAccessor string | |
| 221 | - | HandlerParams string | |
| 222 | - | HandlerArgs string | |
| 223 | - | DecodeLines []string | |
| 224 | - | } | |
| 225 | - | ||
| 226 | - | type constantData struct { | |
| 227 | - | Name string | |
| 228 | - | Value string | |
| 229 | - | Type string | |
| 230 | - | Enum string | |
| 231 | - | Entry string | |
| 232 | - | } | |
| 233 | - | ||
| 234 | - | // Only display and registry have handwritten bootstrap bindings. | |
| 235 | - | var bootstrapTypes = map[string]bool{ | |
| 236 | - | "Display": true, | |
| 237 | - | "Registry": true, | |
| 238 | - | } | |
| 239 | - | ||
| 240 | - | // goKeywords are avoided as parameter names because generated identifiers | |
| 241 | - | // must not collide with the language. | |
| 242 | - | var goKeywords = map[string]bool{ | |
| 243 | - | "break": true, "case": true, "chan": true, "const": true, "continue": true, | |
| 244 | - | "default": true, "defer": true, "else": true, "fallthrough": true, "for": true, | |
| 245 | - | "func": true, "go": true, "goto": true, "if": true, "import": true, | |
| 246 | - | "interface": true, "map": true, "package": true, "range": true, "return": true, | |
| 247 | - | "select": true, "struct": true, "switch": true, "type": true, "var": true, | |
| 248 | - | } | |
| 249 | - | ||
| 250 | - | func (s *Scanner) prepareTemplateData(packageName string) (templateData, error) { | |
| 251 | - | data := templateData{ | |
| 252 | - | Package: packageName, | |
| 253 | - | Protocol: s.protocol.Name, | |
| 254 | - | Source: s.source, | |
| 255 | - | } | |
| 256 | - | if notice := strings.TrimSpace(s.protocol.Copyright); notice != "" { | |
| 257 | - | var comment strings.Builder | |
| 258 | - | for _, line := range strings.Split(notice, "\n") { | |
| 259 | - | comment.WriteString("// ") | |
| 260 | - | comment.WriteString(strings.TrimSpace(line)) | |
| 261 | - | comment.WriteByte('\n') | |
| 262 | - | } | |
| 263 | - | data.Copyright = comment.String() | |
| 264 | - | } | |
| 265 | - | ||
| 266 | - | imports := []string{TransportImport} | |
| 267 | - | usedCross := make(map[string]bool) | |
| 268 | - | for _, candidate := range s.protocol.Interfaces { | |
| 269 | - | for _, req := range candidate.Requests { | |
| 270 | - | for _, arg := range req.Args { | |
| 271 | - | if arg.Type == "object" || arg.Type == "new_id" { | |
| 272 | - | usedCross[arg.Interface] = true | |
| 273 | - | } | |
| 274 | - | } | |
| 275 | - | } | |
| 276 | - | for _, ev := range candidate.Events { | |
| 277 | - | for _, arg := range ev.Args { | |
| 278 | - | // Event object references are decoded as IDs, not imported proxies. | |
| 279 | - | if arg.Type == "new_id" { | |
| 280 | - | usedCross[arg.Interface] = true | |
| 281 | - | } | |
| 282 | - | } | |
| 283 | - | } | |
| 284 | - | } | |
| 285 | - | for iface, path := range s.CrossPackage { | |
| 286 | - | local := false | |
| 287 | - | for _, candidate := range s.protocol.Interfaces { | |
| 288 | - | if candidate.Name == iface { | |
| 289 | - | local = true | |
| 290 | - | break | |
| 291 | - | } | |
| 292 | - | } | |
| 293 | - | if local || !usedCross[iface] || bootstrapTypes[s.toGoName(iface)] { | |
| 294 | - | continue | |
| 295 | - | } | |
| 296 | - | alias := "cross_" + strings.ReplaceAll(iface, "-", "_") | |
| 297 | - | imports = append(imports, alias+" "+path) | |
| 298 | - | } | |
| 299 | - | sort.Strings(imports) | |
| 300 | - | stdImports := []string{} | |
| 301 | - | needsSync := false | |
| 302 | - | ||
| 303 | - | // Enum constants are package-level declarations, so two interfaces that | |
| 304 | - | // declare the same enum entry (for example xdg_surface.error.invalid_size | |
| 305 | - | // and xdg_toplevel.error.invalid_size) would collide. Entries whose name | |
| 306 | - | // occurs in more than one interface are qualified with their interface | |
| 307 | - | // name below; unique names keep their historical, unprefixed form. | |
| 308 | - | enumEntryCounts := map[string]int{} | |
| 309 | - | for _, iface := range s.protocol.Interfaces { | |
| 310 | - | for _, enum := range iface.Enums { | |
| 311 | - | for _, entry := range enum.Entries { | |
| 312 | - | enumEntryCounts[constantName(enum.Name, entry.Name)]++ | |
| 313 | - | } | |
| 314 | - | } | |
| 315 | - | } | |
| 316 | - | ||
| 317 | - | for _, iface := range s.protocol.Interfaces { | |
| 318 | - | if packageName == "core" && (iface.Name == "wl_display" || iface.Name == "wl_registry") { | |
| 319 | - | continue | |
| 320 | - | } | |
| 321 | - | ifaceData, err := s.processInterface(iface) | |
| 322 | - | if err != nil { | |
| 323 | - | return data, err | |
| 324 | - | } | |
| 325 | - | data.Interfaces = append(data.Interfaces, ifaceData) | |
| 326 | - | if len(iface.Events) > 0 { | |
| 327 | - | needsSync = true | |
| 328 | - | } | |
| 329 | - | ||
| 330 | - | for _, enum := range iface.Enums { | |
| 331 | - | for _, entry := range enum.Entries { | |
| 332 | - | name := constantName(enum.Name, entry.Name) | |
| 333 | - | if enumEntryCounts[name] > 1 { | |
| 334 | - | name = qualifiedConstantName(iface.Name, enum.Name, entry.Name) | |
| 335 | - | } | |
| 336 | - | // Enum values are emitted untyped: the same enum travels as a uint | |
| 337 | - | // in one protocol and as an int in another, and an untyped constant | |
| 338 | - | // assigns to either without casts at the call site. | |
| 339 | - | data.Constants = append(data.Constants, constantData{ | |
| 340 | - | Name: name, | |
| 341 | - | Value: entry.Value, | |
| 342 | - | Enum: enum.Name, | |
| 343 | - | Entry: entry.Name, | |
| 344 | - | }) | |
| 345 | - | } | |
| 346 | - | } | |
| 347 | - | } | |
| 348 | - | ||
| 349 | - | // Handlers are registered and dispatched from different goroutines, so an | |
| 350 | - | // interface with events needs a mutex. | |
| 351 | - | if needsSync { | |
| 352 | - | stdImports = append(stdImports, "sync") | |
| 353 | - | } | |
| 354 | - | ||
| 355 | - | var block strings.Builder | |
| 356 | - | block.WriteString("import (\n") | |
| 357 | - | for _, imp := range stdImports { | |
| 358 | - | fmt.Fprintf(&block, "\t%q\n", imp) | |
| 359 | - | } | |
| 360 | - | if len(stdImports) > 0 && len(imports) > 0 { | |
| 361 | - | block.WriteString("\n") | |
| 362 | - | } | |
| 363 | - | for _, imp := range imports { | |
| 364 | - | if strings.Contains(imp, " ") { | |
| 365 | - | parts := strings.SplitN(imp, " ", 2) | |
| 366 | - | fmt.Fprintf(&block, "\t%s %q\n", parts[0], parts[1]) | |
| 367 | - | } else { | |
| 368 | - | fmt.Fprintf(&block, "\t%q\n", imp) | |
| 369 | - | } | |
| 370 | - | } | |
| 371 | - | block.WriteString(")") | |
| 372 | - | data.ImportBlock = block.String() | |
| 373 | - | ||
| 374 | - | return data, nil | |
| 375 | - | } | |
| 376 | - | ||
| 377 | - | func (s *Scanner) processInterface(iface Interface) (interfaceData, error) { | |
| 378 | - | data := interfaceData{ | |
| 379 | - | Name: iface.Name, | |
| 380 | - | GoName: s.toGoName(iface.Name), | |
| 381 | - | Version: iface.Version, | |
| 382 | - | HasEvents: len(iface.Events) > 0, | |
| 383 | - | } | |
| 384 | - | ||
| 385 | - | for i, req := range iface.Requests { | |
| 386 | - | request, err := s.processRequest(iface, req, i) | |
| 387 | - | if err != nil { | |
| 388 | - | return data, err | |
| 389 | - | } | |
| 390 | - | data.Requests = append(data.Requests, request) | |
| 391 | - | } | |
| 392 | - | ||
| 393 | - | for i, event := range iface.Events { | |
| 394 | - | var sig strings.Builder | |
| 395 | - | for _, arg := range event.Args { | |
| 396 | - | sig.WriteString(arg.Type) | |
| 397 | - | sig.WriteByte(',') | |
| 398 | - | } | |
| 399 | - | data.SignatureCases = append(data.SignatureCases, signatureCase{i, sig.String()}) | |
| 400 | - | eventData, err := s.processEvent(event, i) | |
| 401 | - | if iface.Name == "wl_callback" && event.Name == "done" { | |
| 402 | - | eventData.ServerDestroy = true | |
| 403 | - | } | |
| 404 | - | if err != nil { | |
| 405 | - | return data, err | |
| 406 | - | } | |
| 407 | - | data.Events = append(data.Events, eventData) | |
| 408 | - | } | |
| 409 | - | ||
| 410 | - | return data, nil | |
| 411 | - | } | |
| 412 | - | ||
| 413 | - | func (s *Scanner) processRequest(iface Interface, req Request, opcode int) (requestData, error) { | |
| 414 | - | data := requestData{ | |
| 415 | - | Name: req.Name, | |
| 416 | - | GoName: s.toGoName(req.Name), | |
| 417 | - | Doc: s.formatDescription(req.Description), | |
| 418 | - | Opcode: opcode, | |
| 419 | - | Destructor: req.Type == "destructor", | |
| 420 | - | Since: req.Since, | |
| 421 | - | ChildVar: "child", | |
| 422 | - | } | |
| 423 | - | ||
| 424 | - | var ( | |
| 425 | - | params []string | |
| 426 | - | argSlots []argSlot | |
| 427 | - | argExprs []string | |
| 428 | - | fdExprs []string | |
| 429 | - | newIDArg *Arg | |
| 430 | - | ) | |
| 431 | - | ||
| 432 | - | for i, arg := range req.Args { | |
| 433 | - | if arg.Type == "new_id" { | |
| 434 | - | if newIDArg != nil { | |
| 435 | - | return data, fmt.Errorf("%s.%s: more than one new_id argument is not supported", iface.Name, req.Name) | |
| 436 | - | } | |
| 437 | - | newIDArg = &arg | |
| 438 | - | // The child object is created later, but it keeps its declared | |
| 439 | - | // position: the wire order is the argument order. | |
| 440 | - | argSlots = append(argSlots, argSlot{newID: true}) | |
| 441 | - | continue | |
| 442 | - | } | |
| 443 | - | ||
| 444 | - | name := s.paramName(arg.Name, i) | |
| 445 | - | goType, err := s.goTypeForArg(arg) | |
| 446 | - | if err != nil { | |
| 447 | - | return data, fmt.Errorf("%s.%s: %w", iface.Name, req.Name, err) | |
| 448 | - | } | |
| 449 | - | ||
| 450 | - | expr := name | |
| 451 | - | switch arg.Type { | |
| 452 | - | case "object": | |
| 453 | - | // Objects are pointer types, and travel as wl.Object so a nil | |
| 454 | - | // pointer is never sent as a non-nil interface holding a typed nil. | |
| 455 | - | params = append(params, name+" *"+goType) | |
| 456 | - | holder := fmt.Sprintf("arg%d", i) | |
| 457 | - | data.ArgPreparations = append(data.ArgPreparations, | |
| 458 | - | fmt.Sprintf("var %s wl.Object", holder), | |
| 459 | - | fmt.Sprintf("if %s != nil {", name), | |
| 460 | - | fmt.Sprintf("\t%s = %s", holder, name), | |
| 461 | - | "}") | |
| 462 | - | expr = "wl.ArgObject(" + holder + ")" | |
| 463 | - | ||
| 464 | - | case "fd": | |
| 465 | - | // Descriptors travel out of band: the body carries no value for | |
| 466 | - | // them, and the descriptor list is attached to the request. | |
| 467 | - | params = append(params, name+" int") | |
| 468 | - | fdExprs = append(fdExprs, name) | |
| 469 | - | expr = "wl.ArgFD()" | |
| 470 | - | ||
| 471 | - | default: | |
| 472 | - | params = append(params, name+" "+goType) | |
| 473 | - | switch arg.Type { | |
| 474 | - | case "int": | |
| 475 | - | expr = "wl.ArgInt(" + name + ")" | |
| 476 | - | case "uint": | |
| 477 | - | expr = "wl.ArgUint(" + name + ")" | |
| 478 | - | case "fixed": | |
| 479 | - | expr = "wl.ArgFixed(" + name + ")" | |
| 480 | - | case "string": | |
| 481 | - | expr = "wl.ArgString(" + name + ")" | |
| 482 | - | case "array": | |
| 483 | - | expr = "wl.ArgArray(" + name + ")" | |
| 484 | - | } | |
| 485 | - | } | |
| 486 | - | ||
| 487 | - | argSlots = append(argSlots, argSlot{expr: expr}) | |
| 488 | - | } | |
| 489 | - | ||
| 490 | - | if newIDArg != nil { | |
| 491 | - | childType, err := s.goTypeForArg(*newIDArg) | |
| 492 | - | if err != nil { | |
| 493 | - | return data, fmt.Errorf("%s.%s: %w", iface.Name, req.Name, err) | |
| 494 | - | } | |
| 495 | - | data.CreatesChild = true | |
| 496 | - | data.ChildType = childType | |
| 497 | - | if strings.Contains(childType, ".") { | |
| 498 | - | data.ChildFactory = childType[:strings.LastIndex(childType, ".")+1] + "New" + s.toGoName(newIDArg.Interface) | |
| 499 | - | } | |
| 500 | - | } | |
| 501 | - | ||
| 502 | - | for _, slot := range argSlots { | |
| 503 | - | if slot.newID { | |
| 504 | - | argExprs = append(argExprs, "wl.ArgObject("+data.ChildVar+")") | |
| 505 | - | continue | |
| 506 | - | } | |
| 507 | - | argExprs = append(argExprs, slot.expr) | |
| 508 | - | } | |
| 509 | - | ||
| 510 | - | data.Params = strings.Join(params, ", ") | |
| 511 | - | args := "" | |
| 512 | - | if len(argExprs) > 0 { | |
| 513 | - | args = ", " + strings.Join(argExprs, ", ") | |
| 514 | - | } | |
| 515 | - | // Context.RequestArgs owns the lifecycle: destructors claim the proxy | |
| 516 | - | // atomically, children are registered before the send and descriptors are | |
| 517 | - | // closed only after a successful send. | |
| 518 | - | data.ArgList = args | |
| 519 | - | data.FDList = strings.Join(fdExprs, ", ") | |
| 520 | - | data.HasFDs = len(fdExprs) > 0 | |
| 521 | - | if data.CreatesChild { | |
| 522 | - | data.Results = "(*" + data.ChildType + ", error)" | |
| 523 | - | data.ErrorReturn = "nil, err" | |
| 524 | - | } else { | |
| 525 | - | data.Results = "error" | |
| 526 | - | data.ErrorReturn = "err" | |
| 527 | - | } | |
| 528 | - | ||
| 529 | - | return data, nil | |
| 530 | - | } | |
| 531 | - | ||
| 532 | - | func (s *Scanner) processEvent(event Event, opcode int) (eventData, error) { | |
| 533 | - | goName := s.toGoName(event.Name) | |
| 534 | - | data := eventData{ | |
| 535 | - | ServerDestroy: event.Type == "destructor", | |
| 536 | - | Name: event.Name, | |
| 537 | - | GoName: goName, | |
| 538 | - | Opcode: opcode, | |
| 539 | - | HandlerField: "on" + goName, | |
| 540 | - | HandlerAccessor: "handlersFor" + goName, | |
| 541 | - | } | |
| 542 | - | ||
| 543 | - | var params, args []string | |
| 544 | - | ||
| 545 | - | for i, arg := range event.Args { | |
| 546 | - | name := s.paramName(arg.Name, i) | |
| 547 | - | ||
| 548 | - | switch arg.Type { | |
| 549 | - | case "new_id": | |
| 550 | - | childType, err := s.goTypeForArg(arg) | |
| 551 | - | if err != nil { | |
| 552 | - | return data, fmt.Errorf("%s.%s: %w", event.Name, arg.Name, err) | |
| 553 | - | } | |
| 554 | - | child := name + "Object" | |
| 555 | - | data.DecodeLines = append(data.DecodeLines, fmt.Sprintf("%sID := event.Uint32()", name)) | |
| 556 | - | if strings.Contains(childType, ".") { | |
| 557 | - | factory := childType[:strings.LastIndex(childType, ".")+1] + "New" + s.toGoName(arg.Interface) | |
| 558 | - | data.DecodeLines = append(data.DecodeLines, fmt.Sprintf("%s := %s(o.Context())", child, factory)) | |
| 559 | - | } else { | |
| 560 | - | data.DecodeLines = append(data.DecodeLines, | |
| 561 | - | fmt.Sprintf("%s := &%s{}", child, childType), | |
| 562 | - | fmt.Sprintf("%s.SetContext(o.Context())", child), | |
| 563 | - | ) | |
| 564 | - | } | |
| 565 | - | data.DecodeLines = append(data.DecodeLines, | |
| 566 | - | fmt.Sprintf("%s.SetID(%sID)", child, name), | |
| 567 | - | fmt.Sprintf("%s.SetVersion(o.Version())", child), | |
| 568 | - | fmt.Sprintf("o.Context().Register(%s)", child), | |
| 569 | - | ) | |
| 570 | - | params = append(params, child+" *"+childType) | |
| 571 | - | args = append(args, child) | |
| 572 | - | ||
| 573 | - | case "object": | |
| 574 | - | // Object references are reported as raw object IDs: the generated | |
| 575 | - | // layer does not own a registry of foreign proxies. | |
| 576 | - | data.DecodeLines = append(data.DecodeLines, fmt.Sprintf("%sID := event.Uint32()", name)) | |
| 577 | - | params = append(params, name+"ID uint32") | |
| 578 | - | args = append(args, name+"ID") | |
| 579 | - | ||
| 580 | - | default: | |
| 581 | - | if arg.Type == "fd" { | |
| 582 | - | data.HasFD = true | |
| 583 | - | data.FDNames = append(data.FDNames, name) | |
| 584 | - | } | |
| 585 | - | goType, decoder, err := s.scalarDecoder(arg) | |
| 586 | - | if err != nil { | |
| 587 | - | return data, fmt.Errorf("%s.%s: %w", event.Name, arg.Name, err) | |
| 588 | - | } | |
| 589 | - | data.DecodeLines = append(data.DecodeLines, fmt.Sprintf("%s := event.%s()", name, decoder)) | |
| 590 | - | params = append(params, name+" "+goType) | |
| 591 | - | args = append(args, name) | |
| 592 | - | } | |
| 593 | - | } | |
| 594 | - | ||
| 595 | - | data.HandlerParams = strings.Join(params, ", ") | |
| 596 | - | data.HandlerArgs = strings.Join(args, ", ") | |
| 597 | - | return data, nil | |
| 598 | - | } | |
| 599 | - | ||
| 600 | - | // scalarDecoder maps a simple argument to its Go type and event decoder. | |
| 601 | - | func (s *Scanner) scalarDecoder(arg Arg) (goType, decoder string, err error) { | |
| 602 | - | switch arg.Type { | |
| 603 | - | case "int": | |
| 604 | - | return "int32", "Int32", nil | |
| 605 | - | case "uint": | |
| 606 | - | return "uint32", "Uint32", nil | |
| 607 | - | case "fixed": | |
| 608 | - | return "wl.Fixed", "Fixed", nil | |
| 609 | - | case "string": | |
| 610 | - | return "string", "String", nil | |
| 611 | - | case "array": | |
| 612 | - | return "[]byte", "Array", nil | |
| 613 | - | case "fd": | |
| 614 | - | return "*wl.OwnedFD", "FD", nil | |
| 615 | - | } | |
| 616 | - | return "", "", fmt.Errorf("unsupported event argument type %q", arg.Type) | |
| 617 | - | } | |
| 618 | - | ||
| 619 | - | // goTypeForArg returns the Go type of an object-like argument. Protocol-local | |
| 620 | - | // interfaces map to generated types, explicit external references to their | |
| 621 | - | // mapped package, and bootstrap display/registry to transport wrappers. | |
| 622 | - | func (s *Scanner) goTypeForArg(arg Arg) (string, error) { | |
| 623 | - | switch arg.Type { | |
| 624 | - | case "int": | |
| 625 | - | return "int32", nil | |
| 626 | - | case "uint": | |
| 627 | - | return "uint32", nil | |
| 628 | - | case "fixed": | |
| 629 | - | return "wl.Fixed", nil | |
| 630 | - | case "string": | |
| 631 | - | return "string", nil | |
| 632 | - | case "array": | |
| 633 | - | return "[]byte", nil | |
| 634 | - | case "fd": | |
| 635 | - | return "int", nil | |
| 636 | - | case "object", "new_id": | |
| 637 | - | return s.goTypeForInterface(arg.Interface) | |
| 638 | - | } | |
| 639 | - | return "", fmt.Errorf("unsupported argument type %q", arg.Type) | |
| 640 | - | } | |
| 641 | - | ||
| 642 | - | func (s *Scanner) goTypeForInterface(iface string) (string, error) { | |
| 643 | - | if iface == "" { | |
| 644 | - | return "wl.BaseProxy", nil | |
| 645 | - | } | |
| 646 | - | // The XML package owns its own definitions even when the name starts wl_. | |
| 647 | - | for _, local := range s.protocol.Interfaces { | |
| 648 | - | if local.Name == iface && iface != "wl_display" && iface != "wl_registry" { | |
| 649 | - | return s.toGoName(iface), nil | |
| 650 | - | } | |
| 651 | - | } | |
| 652 | - | if bootstrapTypes[s.toGoName(iface)] { | |
| 653 | - | return "wl." + s.toGoName(iface), nil | |
| 654 | - | } | |
| 655 | - | if _, ok := s.CrossPackage[iface]; ok { | |
| 656 | - | return "cross_" + strings.ReplaceAll(iface, "-", "_") + "." + s.toGoName(iface), nil | |
| 657 | - | } | |
| 658 | - | return "", fmt.Errorf("unresolved interface %q: add CrossPackage mapping", iface) | |
| 659 | - | } | |
| 660 | - | ||
| 661 | - | // paramName turns a protocol argument name into a Go parameter name. | |
| 662 | - | func (s *Scanner) paramName(name string, index int) string { | |
| 663 | - | if name == "" { | |
| 664 | - | return fmt.Sprintf("arg%d", index) | |
| 665 | - | } | |
| 666 | - | ||
| 667 | - | parts := strings.Split(name, "_") | |
| 668 | - | for i, part := range parts { | |
| 669 | - | if part == "" { | |
| 670 | - | continue | |
| 671 | - | } | |
| 672 | - | if i == 0 { | |
| 673 | - | parts[i] = strings.ToLower(part[:1]) + part[1:] | |
| 674 | - | continue | |
| 675 | - | } | |
| 676 | - | parts[i] = strings.ToUpper(part[:1]) + part[1:] | |
| 677 | - | } | |
| 678 | - | result := strings.Join(parts, "") | |
| 679 | - | if result == "" { | |
| 680 | - | return fmt.Sprintf("arg%d", index) | |
| 681 | - | } | |
| 682 | - | if goKeywords[result] { | |
| 683 | - | return result + "Arg" | |
| 684 | - | } | |
| 685 | - | return result | |
| 686 | - | } | |
| 687 | - | ||
| 688 | - | func (s *Scanner) toGoName(name string) string { | |
| 689 | - | name = strings.TrimPrefix(name, "zwlr_") | |
| 690 | - | name = strings.TrimPrefix(name, "zwp_") | |
| 691 | - | name = strings.TrimPrefix(name, "wl_") | |
| 692 | - | name = strings.TrimSuffix(name, "_v1") | |
| 693 | - | name = strings.TrimSuffix(name, "_v2") | |
| 694 | - | ||
| 695 | - | parts := strings.Split(name, "_") | |
| 696 | - | for i, part := range parts { | |
| 697 | - | if part != "" { | |
| 698 | - | parts[i] = strings.ToUpper(part[:1]) + part[1:] | |
| 699 | - | } | |
| 700 | - | } | |
| 701 | - | return strings.Join(parts, "") | |
| 702 | - | } | |
| 703 | - | ||
| 704 | - | // constantName renders an enum entry as the unprefixed constant name. | |
| 705 | - | func constantName(enum, entry string) string { | |
| 706 | - | return strings.Join(append(joinName(enum), joinName(entry)...), "_") | |
| 707 | - | } | |
| 708 | - | ||
| 709 | - | // qualifiedConstantName prefixes an enum entry constant with its interface | |
| 710 | - | // name. It is used for entries that several interfaces declare, which would | |
| 711 | - | // otherwise collide in the generated package. | |
| 712 | - | func qualifiedConstantName(iface, enum, entry string) string { | |
| 713 | - | return strings.Join(append(joinName(iface), constantName(enum, entry)), "_") | |
| 714 | - | } | |
| 715 | - | ||
| 716 | - | // joinName upper-cases the underscore-separated parts of a protocol name. | |
| 717 | - | func joinName(value string) []string { | |
| 718 | - | parts := strings.Split(value, "_") | |
| 719 | - | out := make([]string, 0, len(parts)) | |
| 720 | - | for _, part := range parts { | |
| 721 | - | if part != "" { | |
| 722 | - | out = append(out, strings.ToUpper(part)) | |
| 723 | - | } | |
| 724 | - | } | |
| 725 | - | return out | |
| 726 | - | } | |
| 727 | - | ||
| 728 | - | // formatDescription renders an argument or request description as a single | |
| 729 | - | // documentation line. | |
| 730 | - | func (s *Scanner) formatDescription(desc *Description) string { | |
| 731 | - | if desc == nil { | |
| 732 | - | return "" | |
| 733 | - | } | |
| 734 | - | ||
| 735 | - | text := strings.TrimSpace(desc.Text) | |
| 736 | - | if text == "" { | |
| 737 | - | return desc.Summary | |
| 738 | - | } | |
| 739 | - | ||
| 740 | - | lines := strings.Split(text, "\n") | |
| 741 | - | formatted := make([]string, 0, len(lines)) | |
| 742 | - | for _, line := range lines { | |
| 743 | - | if line = strings.TrimSpace(line); line != "" { | |
| 744 | - | formatted = append(formatted, line) | |
| 745 | - | } | |
| 746 | - | } | |
| 747 | - | return strings.Join(formatted, " ") | |
| 748 | - | } | |
D internal/scanner/scanner_test.go +0 -163
| @@ -1,163 +0,0 @@ | |||
| 1 | - | package scanner | |
| 2 | - | ||
| 3 | - | import ( | |
| 4 | - | "os" | |
| 5 | - | "os/exec" | |
| 6 | - | "path/filepath" | |
| 7 | - | "strings" | |
| 8 | - | "testing" | |
| 9 | - | ) | |
| 10 | - | ||
| 11 | - | func TestResolution(t *testing.T) { | |
| 12 | - | p := filepath.Join(t.TempDir(), "fixture.xml") | |
| 13 | - | xml := `<protocol name="sample"><interface name="wl_surface" version="1"><event name="done"><arg name="value" type="uint"/></event></interface><interface name="custom_thing" version="1"><request name="make"><arg name="id" type="new_id" interface="wl_surface"/><arg name="output" type="object" interface="wl_output"/></request></interface></protocol>` | |
| 14 | - | if err := os.WriteFile(p, []byte(xml), 0600); err != nil { | |
| 15 | - | t.Fatal(err) | |
| 16 | - | } | |
| 17 | - | s := NewScanner() | |
| 18 | - | if err := s.ParseXML(p); err != nil { | |
| 19 | - | t.Fatal(err) | |
| 20 | - | } | |
| 21 | - | s.CrossPackage = map[string]string{"wl_surface": "github.com/bnema/wlturbo/protocol/core", "wl_output": "github.com/bnema/wlturbo/protocol/core"} | |
| 22 | - | b, err := s.Generate("fixture") | |
| 23 | - | if err != nil { | |
| 24 | - | t.Fatal(err) | |
| 25 | - | } | |
| 26 | - | text := string(b) | |
| 27 | - | if !strings.Contains(text, "(*Surface, error)") || !strings.Contains(text, "output *cross_wl_output.Output") || strings.Contains(text, "cross_wl_surface") { | |
| 28 | - | t.Fatalf("wrong resolution: %s", text) | |
| 29 | - | } | |
| 30 | - | } | |
| 31 | - | func TestCoreGeneration(t *testing.T) { | |
| 32 | - | s := NewScanner() | |
| 33 | - | if err := s.ParseXML("../../protocol/wayland.xml"); err != nil { | |
| 34 | - | t.Fatal(err) | |
| 35 | - | } | |
| 36 | - | b, err := s.Generate("core") | |
| 37 | - | if err != nil { | |
| 38 | - | t.Fatal(err) | |
| 39 | - | } | |
| 40 | - | for _, want := range []string{"type Keyboard struct", "type Subsurface struct", "type Buffer struct", "type Callback struct", "return \"uint,fd,uint,\", true", "child := &Keyboard{}"} { | |
| 41 | - | if !strings.Contains(string(b), want) { | |
| 42 | - | t.Errorf("missing %s", want) | |
| 43 | - | } | |
| 44 | - | } | |
| 45 | - | if strings.Contains(string(b), "type Display struct") || strings.Contains(string(b), "type Registry struct") { | |
| 46 | - | t.Fatal("bootstrap generated twice") | |
| 47 | - | } | |
| 48 | - | } | |
| 49 | - | ||
| 50 | - | // Extension protocols use wl_buffer as both an event-created child and a request-created child. | |
| 51 | - | // Verify the generated code uses the public constructor instead of embedding | |
| 52 | - | // an inaccessible BaseProxy context field across package boundaries. | |
| 53 | - | func TestExternalChildFactory(t *testing.T) { | |
| 54 | - | path := filepath.Join(t.TempDir(), "external.xml") | |
| 55 | - | xml := `<protocol name="fixture"><interface name="ext_params" version="1"><request name="create"><arg name="id" type="new_id" interface="wl_buffer"/></request><event name="created"><arg name="id" type="new_id" interface="wl_buffer"/></event></interface></protocol>` | |
| 56 | - | if err := os.WriteFile(path, []byte(xml), 0600); err != nil { | |
| 57 | - | t.Fatal(err) | |
| 58 | - | } | |
| 59 | - | s := NewScanner() | |
| 60 | - | if err := s.ParseXML(path); err != nil { | |
| 61 | - | t.Fatal(err) | |
| 62 | - | } | |
| 63 | - | s.CrossPackage = map[string]string{"wl_buffer": "github.com/bnema/wlturbo/protocol/core"} | |
| 64 | - | generated, err := s.Generate("ext") | |
| 65 | - | if err != nil { | |
| 66 | - | t.Fatal(err) | |
| 67 | - | } | |
| 68 | - | for _, part := range []string{"cross_wl_buffer.NewBuffer(o.Context())", "(*cross_wl_buffer.Buffer, error)", "idObject.SetID(idID)"} { | |
| 69 | - | if !strings.Contains(string(generated), part) { | |
| 70 | - | t.Errorf("generated code missing %q", part) | |
| 71 | - | } | |
| 72 | - | } | |
| 73 | - | if strings.Contains(string(generated), "&cross_wl_buffer.Buffer{}") { | |
| 74 | - | t.Fatal("foreign child was constructed without its package factory") | |
| 75 | - | } | |
| 76 | - | } | |
| 77 | - | ||
| 78 | - | func TestUnresolvedExternalInterface(t *testing.T) { | |
| 79 | - | path := filepath.Join(t.TempDir(), "extension.xml") | |
| 80 | - | xml := `<protocol name="ext"><interface name="ext_parent" version="1"><request name="make"><arg name="id" type="new_id" interface="wl_surface"/></request></interface></protocol>` | |
| 81 | - | if err := os.WriteFile(path, []byte(xml), 0600); err != nil { | |
| 82 | - | t.Fatal(err) | |
| 83 | - | } | |
| 84 | - | s := NewScanner() | |
| 85 | - | if err := s.ParseXML(path); err != nil { | |
| 86 | - | t.Fatal(err) | |
| 87 | - | } | |
| 88 | - | if _, err := s.Generate("ext"); err == nil || !strings.Contains(err.Error(), "wl_surface") { | |
| 89 | - | t.Fatalf("unmapped external reference: %v", err) | |
| 90 | - | } | |
| 91 | - | } | |
| 92 | - | ||
| 93 | - | func TestMappedExtensionCompilesAndDispatchesChild(t *testing.T) { | |
| 94 | - | goBin, err := exec.LookPath("go") | |
| 95 | - | if err != nil { | |
| 96 | - | t.Skip("go unavailable: generated extension compilation requires go") | |
| 97 | - | } | |
| 98 | - | root, err := filepath.Abs("../..") | |
| 99 | - | if err != nil { | |
| 100 | - | t.Fatal(err) | |
| 101 | - | } | |
| 102 | - | dir := t.TempDir() | |
| 103 | - | xml := `<protocol name="ext"><interface name="ext_parent" version="1"><event name="child"><arg name="id" type="new_id" interface="wl_buffer"/></event></interface></protocol>` | |
| 104 | - | path := filepath.Join(dir, "ext.xml") | |
| 105 | - | if err := os.WriteFile(path, []byte(xml), 0600); err != nil { | |
| 106 | - | t.Fatal(err) | |
| 107 | - | } | |
| 108 | - | s := NewScanner() | |
| 109 | - | if err := s.ParseXML(path); err != nil { | |
| 110 | - | t.Fatal(err) | |
| 111 | - | } | |
| 112 | - | s.CrossPackage = map[string]string{"wl_buffer": "github.com/bnema/wlturbo/protocol/core"} | |
| 113 | - | generated, err := s.Generate("ext") | |
| 114 | - | if err != nil { | |
| 115 | - | t.Fatal(err) | |
| 116 | - | } | |
| 117 | - | if err := os.WriteFile(filepath.Join(dir, "ext.go"), generated, 0600); err != nil { | |
| 118 | - | t.Fatal(err) | |
| 119 | - | } | |
| 120 | - | mod := "module example.com/ext\n\ngo 1.27\n\nrequire github.com/bnema/wlturbo v0.0.0\nreplace github.com/bnema/wlturbo => " + root + "\n" | |
| 121 | - | if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte(mod), 0600); err != nil { | |
| 122 | - | t.Fatal(err) | |
| 123 | - | } | |
| 124 | - | test := `package ext | |
| 125 | - | import ( | |
| 126 | - | "encoding/binary" | |
| 127 | - | "net" | |
| 128 | - | "os" | |
| 129 | - | "testing" | |
| 130 | - | "github.com/bnema/wlturbo" | |
| 131 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 132 | - | "golang.org/x/sys/unix" | |
| 133 | - | ) | |
| 134 | - | func TestTypedChild(t *testing.T) { | |
| 135 | - | f, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0); if err != nil { t.Fatal(err) } | |
| 136 | - | a, b := os.NewFile(uintptr(f[0]), "a"), os.NewFile(uintptr(f[1]), "b") | |
| 137 | - | c, err := net.FileConn(a); a.Close(); if err != nil { t.Fatal(err) }; defer c.Close() | |
| 138 | - | p, err := net.FileConn(b); b.Close(); if err != nil { t.Fatal(err) }; defer p.Close() | |
| 139 | - | d, err := wlturbo.ConnectFromConn(c); if err != nil { t.Fatal(err) }; defer d.Close() | |
| 140 | - | parent := NewExtParent(d.Context()); parent.SetID(d.AllocateID()); d.Context().Register(parent) | |
| 141 | - | var child *core.Buffer | |
| 142 | - | parent.OnChild(func(b *core.Buffer) { child = b }) | |
| 143 | - | frame := make([]byte, 12); binary.LittleEndian.PutUint32(frame, parent.ID()); binary.LittleEndian.PutUint32(frame[4:], 12<<16); binary.LittleEndian.PutUint32(frame[8:], 0xff000001) | |
| 144 | - | if _, err := p.Write(frame); err != nil { t.Fatal(err) } | |
| 145 | - | if err := d.Dispatch(); err != nil { t.Fatal(err) } | |
| 146 | - | if child == nil || child.ID() != 0xff000001 { t.Fatalf("child: %v", child) } | |
| 147 | - | called := false; child.OnRelease(func(){ called = true }) | |
| 148 | - | frame = frame[:8]; binary.LittleEndian.PutUint32(frame, child.ID()); binary.LittleEndian.PutUint32(frame[4:], 8<<16) | |
| 149 | - | if _, err := p.Write(frame); err != nil { t.Fatal(err) } | |
| 150 | - | if err := d.Dispatch(); err != nil { t.Fatal(err) } | |
| 151 | - | if !called { t.Fatal("typed child did not dispatch release") } | |
| 152 | - | } | |
| 153 | - | ` | |
| 154 | - | if err := os.WriteFile(filepath.Join(dir, "ext_test.go"), []byte(test), 0600); err != nil { | |
| 155 | - | t.Fatal(err) | |
| 156 | - | } | |
| 157 | - | cmd := exec.Command(goBin, "test", "./...") | |
| 158 | - | cmd.Dir = dir | |
| 159 | - | cmd.Env = append(os.Environ(), "GOWORK=off", "GOFLAGS=-mod=mod") | |
| 160 | - | if out, err := cmd.CombinedOutput(); err != nil { | |
| 161 | - | t.Fatalf("generated extension test: %v\n%s", err, out) | |
| 162 | - | } | |
| 163 | - | } | |
D internal/scanner/sources_test.go +0 -71
| @@ -1,71 +0,0 @@ | |||
| 1 | - | package scanner | |
| 2 | - | ||
| 3 | - | import ( | |
| 4 | - | "crypto/sha256" | |
| 5 | - | "fmt" | |
| 6 | - | "os" | |
| 7 | - | "path/filepath" | |
| 8 | - | "regexp" | |
| 9 | - | "strings" | |
| 10 | - | "testing" | |
| 11 | - | ) | |
| 12 | - | ||
| 13 | - | func TestProtocolSourceChecksums(t *testing.T) { | |
| 14 | - | root := filepath.Join("..", "..", "protocol") | |
| 15 | - | content, err := os.ReadFile(filepath.Join(root, "SOURCE.md")) | |
| 16 | - | if err != nil { | |
| 17 | - | t.Fatal(err) | |
| 18 | - | } | |
| 19 | - | coreChecksum := regexp.MustCompile("(?m)^SHA-256: `([a-f0-9]{64})`\\.").FindSubmatch(content) | |
| 20 | - | if coreChecksum == nil { | |
| 21 | - | t.Fatal("core protocol source checksum is missing") | |
| 22 | - | } | |
| 23 | - | // Extension tables record upstream path, vendored path and SHA-256. | |
| 24 | - | rows := regexp.MustCompile("(?m)^\\| `[^`]+` \\| `([^`]+)` \\| `([a-f0-9]{64})` \\|$").FindAllSubmatch(content, -1) | |
| 25 | - | if len(rows) == 0 { | |
| 26 | - | t.Fatal("no protocol source checksums found") | |
| 27 | - | } | |
| 28 | - | rows = append(rows, [][]byte{nil, []byte("wayland.xml"), coreChecksum[1]}) | |
| 29 | - | recorded := make(map[string]bool) | |
| 30 | - | for _, row := range rows { | |
| 31 | - | path, want := string(row[1]), string(row[2]) | |
| 32 | - | if !filepath.IsLocal(path) { | |
| 33 | - | t.Fatalf("source path must be repository-relative: %q", path) | |
| 34 | - | } | |
| 35 | - | if recorded[path] { | |
| 36 | - | t.Fatalf("duplicate source record: %s", path) | |
| 37 | - | } | |
| 38 | - | recorded[path] = true | |
| 39 | - | t.Run(path, func(t *testing.T) { | |
| 40 | - | data, err := os.ReadFile(filepath.Join(root, path)) | |
| 41 | - | if err != nil { | |
| 42 | - | t.Fatal(err) | |
| 43 | - | } | |
| 44 | - | if got := fmt.Sprintf("%x", sha256.Sum256(data)); got != want { | |
| 45 | - | t.Fatalf("SHA-256 %s, recorded %s", got, want) | |
| 46 | - | } | |
| 47 | - | if !strings.Contains(string(data), "<copyright>") { | |
| 48 | - | t.Fatal("vendored XML is missing upstream copyright/license") | |
| 49 | - | } | |
| 50 | - | }) | |
| 51 | - | } | |
| 52 | - | err = filepath.WalkDir(root, func(path string, entry os.DirEntry, err error) error { | |
| 53 | - | if err != nil { | |
| 54 | - | return err | |
| 55 | - | } | |
| 56 | - | if entry.IsDir() || filepath.Ext(path) != ".xml" { | |
| 57 | - | return nil | |
| 58 | - | } | |
| 59 | - | rel, err := filepath.Rel(root, path) | |
| 60 | - | if err != nil { | |
| 61 | - | return err | |
| 62 | - | } | |
| 63 | - | if !recorded[filepath.ToSlash(rel)] { | |
| 64 | - | t.Errorf("%s has no source/checksum record", rel) | |
| 65 | - | } | |
| 66 | - | return nil | |
| 67 | - | }) | |
| 68 | - | if err != nil { | |
| 69 | - | t.Fatal(err) | |
| 70 | - | } | |
| 71 | - | } | |
D internal/scanner/template.go +0 -140
| @@ -1,140 +0,0 @@ | |||
| 1 | - | package scanner | |
| 2 | - | ||
| 3 | - | // protocolTemplate is the template for generating WLTurbo-backed Go bindings. | |
| 4 | - | // | |
| 5 | - | // Generated objects embed wl.BaseProxy, send every request through | |
| 6 | - | // wl.Context.RequestArgs (typed arguments, no interface boxing; it owns | |
| 7 | - | // version checks, child registration and FD cleanup), and dispatch typed | |
| 8 | - | // events to registered handlers. Nothing in the generated code opens a | |
| 9 | - | // socket or frames messages itself: that is the transport's job. | |
| 10 | - | const protocolTemplate = `// Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 11 | - | // Protocol: {{.Protocol}} | |
| 12 | - | // Source: {{.Source}} | |
| 13 | - | {{if .Copyright}} | |
| 14 | - | // Upstream protocol copyright and license: | |
| 15 | - | {{.Copyright}}{{end}} | |
| 16 | - | package {{.Package}} | |
| 17 | - | ||
| 18 | - | {{.ImportBlock}} | |
| 19 | - | ||
| 20 | - | {{range .Constants}} | |
| 21 | - | // {{.Name}} is the {{.Enum}} {{.Entry}} value. | |
| 22 | - | const {{.Name}}{{if .Type}} {{.Type}}{{end}} = {{.Value}} | |
| 23 | - | {{- end}} | |
| 24 | - | {{range .Interfaces}} | |
| 25 | - | {{- $iface := .}} | |
| 26 | - | ||
| 27 | - | // {{$iface.GoName}}Interface is the protocol interface name. | |
| 28 | - | const {{$iface.GoName}}Interface = "{{$iface.Name}}" | |
| 29 | - | ||
| 30 | - | // {{$iface.GoName}} is the generated binding for {{$iface.Name}} version {{$iface.Version}}. | |
| 31 | - | type {{$iface.GoName}} struct { | |
| 32 | - | wl.BaseProxy | |
| 33 | - | {{- if $iface.HasEvents}} | |
| 34 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 35 | - | // handlers while another goroutine dispatches events. | |
| 36 | - | handlersMu sync.Mutex | |
| 37 | - | {{- end}} | |
| 38 | - | {{- range $iface.Events}} | |
| 39 | - | {{.HandlerField}} []func({{.HandlerParams}}) | |
| 40 | - | {{- end}} | |
| 41 | - | } | |
| 42 | - | ||
| 43 | - | // New{{$iface.GoName}} returns an unbound {{$iface.GoName}}. | |
| 44 | - | func New{{$iface.GoName}}(ctx *wl.Context) *{{$iface.GoName}} { | |
| 45 | - | obj := &{{$iface.GoName}}{} | |
| 46 | - | obj.SetContext(ctx) | |
| 47 | - | ctx.Register(obj) | |
| 48 | - | return obj | |
| 49 | - | } | |
| 50 | - | {{- range $iface.Requests}} | |
| 51 | - | ||
| 52 | - | {{- if .Doc}} | |
| 53 | - | // {{.Doc}} | |
| 54 | - | {{- end}} | |
| 55 | - | func (o *{{$iface.GoName}}) {{.GoName}}({{.Params}}) {{.Results}} { | |
| 56 | - | {{- range .ArgPreparations}} | |
| 57 | - | {{.}} | |
| 58 | - | {{- end}} | |
| 59 | - | {{- if .CreatesChild}} | |
| 60 | - | {{- if .ChildFactory}} | |
| 61 | - | {{.ChildVar}} := {{.ChildFactory}}(o.Context()) | |
| 62 | - | {{- else}} | |
| 63 | - | {{.ChildVar}} := &{{.ChildType}}{} | |
| 64 | - | {{.ChildVar}}.SetContext(o.Context()) | |
| 65 | - | {{- end}} | |
| 66 | - | {{- end}} | |
| 67 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: {{.Opcode}}, Name: "{{$iface.Name}}.{{.Name}}" | |
| 68 | - | {{- if gt .Since 1}}, Since: {{.Since}}{{end}} | |
| 69 | - | {{- if .Destructor}}, Destructor: true{{end}} | |
| 70 | - | {{- if .CreatesChild}}, Child: {{.ChildVar}}{{end}} | |
| 71 | - | {{- if .HasFDs}}, FDs: []int{ {{- .FDList -}} }{{end}}}{{.ArgList}}); err != nil { | |
| 72 | - | return {{.ErrorReturn}} | |
| 73 | - | } | |
| 74 | - | {{- if .CreatesChild}} | |
| 75 | - | return {{.ChildVar}}, nil | |
| 76 | - | {{- else}} | |
| 77 | - | return nil | |
| 78 | - | {{- end}} | |
| 79 | - | } | |
| 80 | - | {{- end}} | |
| 81 | - | {{- range $iface.Events}} | |
| 82 | - | ||
| 83 | - | // On{{.GoName}} registers a handler for the {{.Name}} event. | |
| 84 | - | // | |
| 85 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 86 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 87 | - | func (o *{{$iface.GoName}}) On{{.GoName}}(handler func({{.HandlerParams}})) { | |
| 88 | - | if handler == nil { return } | |
| 89 | - | o.handlersMu.Lock() | |
| 90 | - | defer o.handlersMu.Unlock() | |
| 91 | - | o.{{.HandlerField}} = append(o.{{.HandlerField}}, handler) | |
| 92 | - | } | |
| 93 | - | ||
| 94 | - | // {{.HandlerAccessor}} returns the handlers registered for {{.Name}}, taken | |
| 95 | - | // under the lock so a handler may register another handler while events are | |
| 96 | - | // being dispatched. | |
| 97 | - | func (o *{{$iface.GoName}}) {{.HandlerAccessor}}() []func({{.HandlerParams}}) { | |
| 98 | - | o.handlersMu.Lock() | |
| 99 | - | defer o.handlersMu.Unlock() | |
| 100 | - | return o.{{.HandlerField}} | |
| 101 | - | } | |
| 102 | - | {{- end}} | |
| 103 | - | ||
| 104 | - | // EventSignature returns the declared event argument types in wire order. | |
| 105 | - | func (o *{{$iface.GoName}}) EventSignature(opcode uint16) (string, bool) { | |
| 106 | - | switch opcode { | |
| 107 | - | {{- range $iface.SignatureCases}} | |
| 108 | - | case {{.Opcode}}: return "{{.Signature}}", true | |
| 109 | - | {{- end}} | |
| 110 | - | default: return "", false | |
| 111 | - | } | |
| 112 | - | } | |
| 113 | - | ||
| 114 | - | // Dispatch decodes one event on {{$iface.Name}} and calls the registered handlers. | |
| 115 | - | func (o *{{$iface.GoName}}) Dispatch(event *wl.Event) { | |
| 116 | - | switch event.Opcode { | |
| 117 | - | {{- range $iface.Events}} | |
| 118 | - | case {{.Opcode}}: // {{.Name}} | |
| 119 | - | {{- range .DecodeLines}} | |
| 120 | - | {{.}} | |
| 121 | - | {{- end}} | |
| 122 | - | {{if .HasFD}}{{range .FDNames}}owned{{.}} := {{.}}; defer owned{{.}}.Close() | |
| 123 | - | {{end}}{{end}} | |
| 124 | - | for i, handler := range o.{{.HandlerAccessor}}() { | |
| 125 | - | {{- if .HasFD}} | |
| 126 | - | if i > 0 { {{range .FDNames}}{{.}} = nil; {{end}} } | |
| 127 | - | {{- else}} | |
| 128 | - | _ = i | |
| 129 | - | {{- end}} | |
| 130 | - | handler({{.HandlerArgs}}) | |
| 131 | - | } | |
| 132 | - | {{- if .ServerDestroy}} | |
| 133 | - | o.Context().Unregister(o) | |
| 134 | - | {{- end}} | |
| 135 | - | {{- end}} | |
| 136 | - | default: | |
| 137 | - | } | |
| 138 | - | } | |
| 139 | - | {{end}} | |
| 140 | - | ` | |
D internal/scanner/testdata/protocol_fixture.xml +0 -112
| @@ -1,112 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="wlvision_fixture"> | |
| 3 | - | <copyright> | |
| 4 | - | Synthetic protocol used to test the wlvision protocol generator. It exists | |
| 5 | - | only in this repository's tests. | |
| 6 | - | </copyright> | |
| 7 | - | ||
| 8 | - | <interface name="zwlr_fixture_manager_v1" version="2"> | |
| 9 | - | <description summary="fixture manager"> | |
| 10 | - | Exercises new_id requests, object references, fixed point numbers, | |
| 11 | - | strings, arrays, file descriptors and destructors. | |
| 12 | - | </description> | |
| 13 | - | ||
| 14 | - | <request name="create_thing"> | |
| 15 | - | <description summary="create a fixture object"/> | |
| 16 | - | <arg name="seat" type="object" interface="wl_seat"/> | |
| 17 | - | <arg name="id" type="new_id" interface="zwlr_fixture_thing_v1"/> | |
| 18 | - | </request> | |
| 19 | - | ||
| 20 | - | <request name="set_ratio"> | |
| 21 | - | <arg name="ratio" type="fixed"/> | |
| 22 | - | </request> | |
| 23 | - | ||
| 24 | - | <request name="set_label"> | |
| 25 | - | <arg name="label" type="string"/> | |
| 26 | - | </request> | |
| 27 | - | ||
| 28 | - | <request name="set_region"> | |
| 29 | - | <arg name="region" type="object" interface="wl_region"/> | |
| 30 | - | </request> | |
| 31 | - | ||
| 32 | - | <request name="set_buffer"> | |
| 33 | - | <description summary="reference an interface without a typed wrapper"/> | |
| 34 | - | <arg name="buffer" type="object" interface="wl_buffer"/> | |
| 35 | - | </request> | |
| 36 | - | ||
| 37 | - | <request name="set_optional_output"> | |
| 38 | - | <arg name="output" type="object" interface="wl_output" allow-null="true"/> | |
| 39 | - | </request> | |
| 40 | - | ||
| 41 | - | <request name="attach_raw"> | |
| 42 | - | <arg name="data" type="array"/> | |
| 43 | - | </request> | |
| 44 | - | ||
| 45 | - | <request name="pass_fd"> | |
| 46 | - | <arg name="fd" type="fd"/> | |
| 47 | - | </request> | |
| 48 | - | ||
| 49 | - | <request name="destroy" type="destructor"> | |
| 50 | - | <description summary="destroy the manager"/> | |
| 51 | - | </request> | |
| 52 | - | ||
| 53 | - | <request name="create_labeled_thing"> | |
| 54 | - | <description summary="new_id argument that is not the last one"/> | |
| 55 | - | <arg name="id" type="new_id" interface="zwlr_fixture_thing_v1"/> | |
| 56 | - | <arg name="label" type="string"/> | |
| 57 | - | <arg name="ratio" type="fixed"/> | |
| 58 | - | </request> | |
| 59 | - | </interface> | |
| 60 | - | ||
| 61 | - | <interface name="zwlr_fixture_thing_v1" version="1"> | |
| 62 | - | <description summary="fixture object"/> | |
| 63 | - | ||
| 64 | - | <enum name="fixture_state"> | |
| 65 | - | <entry name="idle" value="0"/> | |
| 66 | - | <entry name="busy" value="1"/> | |
| 67 | - | </enum> | |
| 68 | - | ||
| 69 | - | <request name="set_scale"> | |
| 70 | - | <arg name="scale" type="fixed"/> | |
| 71 | - | </request> | |
| 72 | - | ||
| 73 | - | <request name="destroy" type="destructor"/> | |
| 74 | - | ||
| 75 | - | <event name="ready"> | |
| 76 | - | <arg name="serial" type="uint"/> | |
| 77 | - | </event> | |
| 78 | - | ||
| 79 | - | <event name="label_changed"> | |
| 80 | - | <arg name="label" type="string"/> | |
| 81 | - | </event> | |
| 82 | - | ||
| 83 | - | <event name="geometry"> | |
| 84 | - | <arg name="x" type="int"/> | |
| 85 | - | <arg name="y" type="int"/> | |
| 86 | - | <arg name="width" type="uint"/> | |
| 87 | - | <arg name="height" type="uint"/> | |
| 88 | - | </event> | |
| 89 | - | ||
| 90 | - | <event name="mode"> | |
| 91 | - | <arg name="mode" type="new_id" interface="zwlr_fixture_mode_v1"/> | |
| 92 | - | </event> | |
| 93 | - | ||
| 94 | - | <event name="peer"> | |
| 95 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 96 | - | </event> | |
| 97 | - | ||
| 98 | - | <event name="scaled"> | |
| 99 | - | <arg name="scale" type="fixed"/> | |
| 100 | - | </event> | |
| 101 | - | ||
| 102 | - | <event name="blob"> | |
| 103 | - | <arg name="data" type="array"/> | |
| 104 | - | </event> | |
| 105 | - | </interface> | |
| 106 | - | ||
| 107 | - | <interface name="zwlr_fixture_mode_v1" version="1"> | |
| 108 | - | <description summary="fixture mode object"/> | |
| 109 | - | ||
| 110 | - | <request name="destroy" type="destructor"/> | |
| 111 | - | </interface> | |
| 112 | - | </protocol> | |
D protocol/SOURCE.md +0 -94
| @@ -1,94 +0,0 @@ | |||
| 1 | - | # Core protocol source | |
| 2 | - | ||
| 3 | - | `wayland.xml` is from Wayland 1.26.0, upstream GitLab | |
| 4 | - | `https://gitlab.freedesktop.org/wayland/wayland`, tag `1.26.0`, peeled commit | |
| 5 | - | `87cc8a8728a923fc57938faa81ba0e74f34ecdc7`. | |
| 6 | - | SHA-256: `cc860987e54f8d85c940e97fa1270c69b6e4ad31fbcf5a7f00107ce1157f5e07`. | |
| 7 | - | License: MIT (full copyright and grant in `wayland.xml` `<copyright>`). | |
| 8 | - | ||
| 9 | - | ## wayland-protocols extensions | |
| 10 | - | ||
| 11 | - | The following XML files come from `https://gitlab.freedesktop.org/wayland/wayland-protocols`, | |
| 12 | - | tag `1.49` (peeled commit `ee78491a237eaff9389a0ccf8680521d074407d3`). | |
| 13 | - | Each XML retains its upstream `<copyright>` and license grant; consult the file for its exact terms. | |
| 14 | - | SHA-256 (of the vendored XML bytes): | |
| 15 | - | ||
| 16 | - | | Upstream path (under tag 1.49) | Vendored path | SHA-256 | | |
| 17 | - | |---|---|---| | |
| 18 | - | | `stable/xdg-shell/xdg-shell.xml` | `xdgshell/xdg-shell.xml` | `7ba7f9c8473deee674cb1f154a18abd0bb0cc072604fc055b0c15e459fc4c7df` | | |
| 19 | - | | `stable/linux-dmabuf/linux-dmabuf-v1.xml` | `linuxdmabuf/linux-dmabuf-v1.xml` | `2735bb4589cbb364dfcb6a821dd3abbf0c0257956b716b9691718ddfd453df4c` | | |
| 20 | - | | `staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml` | `drmsyncobj/linux-drm-syncobj-v1.xml` | `5ede41a56eced6aa635caa7ab2996066bff9fd211620dbf9f73aafab740bec71` | | |
| 21 | - | | `stable/viewporter/viewporter.xml` | `viewporter/viewporter.xml` | `dcb12279a03746301fe490aaed4b38a403485a925abfce2ccfceb644e104fe71` | | |
| 22 | - | | `staging/fractional-scale/fractional-scale-v1.xml` | `fractionalscale/fractional-scale-v1.xml` | `5941de5d28f427ecdadddc8623a6f6af0a30b0ab4726847236ba7a7652b81316` | | |
| 23 | - | | `unstable/text-input/text-input-unstable-v3.xml` | `textinput/text-input-unstable-v3.xml` | `160815cda13c285a30df1971d8f0a5b3aac07071537df59916d2f748b18e4f59` | | |
| 24 | - | | `staging/cursor-shape/cursor-shape-v1.xml` | `cursorshape/cursor-shape-v1.xml` | `bb57d91e53a79dadab7c612dab87c233393cee73673feefa7442cfbfdd9aed2f` | | |
| 25 | - | | `stable/tablet/tablet-v2.xml` | `tablet/tablet-v2.xml` | `ac1128b26c779cf90b9ed71182ba5e34a7262826789adae206d825a4d45908b4` | | |
| 26 | - | | `staging/alpha-modifier/alpha-modifier-v1.xml` | `alphamodifier/alpha-modifier-v1.xml` | `f0b4a43b9e48783fafdb46319fa72b34a41afd932f8613d7cadaf7203f2ffa35` | | |
| 27 | - | | `staging/color-management/color-management-v1.xml` | `colormanagement/color-management-v1.xml` | `18a2678e3352c3be3fbeed20005d48852b7235d0d78f08b9c987a0b8e91449f9` | | |
| 28 | - | | `staging/color-representation/color-representation-v1.xml` | `colorrepresentation/color-representation-v1.xml` | `b824688e0e5c1d01e12afe1d3f82503092ec7599affcd6471fda6d296d4f7e3b` | | |
| 29 | - | | `staging/commit-timing/commit-timing-v1.xml` | `committiming/commit-timing-v1.xml` | `ff3fcf31d13d44bad756a50fda663a43008bacbbd2bf8cba3a1bf5ffe7f54172` | | |
| 30 | - | | `staging/content-type/content-type-v1.xml` | `contenttype/content-type-v1.xml` | `203d17a26baa2ab4a8c2c9cb737c953fa3263c73a0a8aa6e552a41b3eac2196d` | | |
| 31 | - | | `staging/ext-data-control/ext-data-control-v1.xml` | `datacontrol/ext-data-control-v1.xml` | `293deba5dfdb974fbcf8dcf891a30a51a36a8bba0047dc6bdf6a03194089b7fb` | | |
| 32 | - | | `staging/drm-lease/drm-lease-v1.xml` | `drmlease/drm-lease-v1.xml` | `18f325e92285473eca0567ea1038abb16849b8638b36e458ff551f3ca68ef80c` | | |
| 33 | - | | `staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml` | `extforeigntoplevel/ext-foreign-toplevel-list-v1.xml` | `6b2ffb3a07d679d1c4170263adfefb9a7c37dd34ed3db5180bf58cb8ff8fbd0b` | | |
| 34 | - | | `staging/fifo/fifo-v1.xml` | `fifo/fifo-v1.xml` | `0b6c31dfe6bca19b712745c9de7a4a398558cfa1087b1938e96fd3b10ffc1069` | | |
| 35 | - | | `unstable/idle-inhibit/idle-inhibit-unstable-v1.xml` | `idleinhibit/idle-inhibit-unstable-v1.xml` | `c2ac9f002c6669ca6c02eb9b587b8e9108e3ce6deab4a2de58b576f4f864ca38` | | |
| 36 | - | | `staging/ext-idle-notify/ext-idle-notify-v1.xml` | `idlenotify/ext-idle-notify-v1.xml` | `e56a9c22684e6b46655f7221b798328e304c1efc8f63f01241a1cf8c070f4c30` | | |
| 37 | - | | `staging/ext-image-capture-source/ext-image-capture-source-v1.xml` | `imagecapturesource/ext-image-capture-source-v1.xml` | `4ef41d15e4cdb9f550158391358ceec724a6708b43b7efedec03121a6bb8458d` | | |
| 38 | - | | `staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml` | `imagecopycapture/ext-image-copy-capture-v1.xml` | `41a446653f788fabb404cab3168c0bd667c1ff4b54f1f0bb1e18810a1f47d73f` | | |
| 39 | - | | `staging/ext-session-lock/ext-session-lock-v1.xml` | `extsessionlock/ext-session-lock-v1.xml` | `a05df7d95c5e523e457037b3a149484e8064828cda66971f3c7caeb87d597a81` | | |
| 40 | - | | `unstable/pointer-constraints/pointer-constraints-unstable-v1.xml` | `pointerconstraints/pointer-constraints-unstable-v1.xml` | `f980fac900ba1dcfbbe97f588fc17b893926bd2b57624563653a1bfe4d035948` | | |
| 41 | - | | `staging/pointer-warp/pointer-warp-v1.xml` | `pointerwarp/pointer-warp-v1.xml` | `1389e89c68c6f6d231fd2dcda57fa9c75c5230d0ac1deffa8d80a7648e197e66` | | |
| 42 | - | | `stable/presentation-time/presentation-time.xml` | `presentation/presentation-time.xml` | `dffac93bcb2bb1d8c385e72b8a8c2c0d4d79a336866322f3ba886dce2b27b1e2` | | |
| 43 | - | | `unstable/primary-selection/primary-selection-unstable-v1.xml` | `primaryselection/primary-selection-unstable-v1.xml` | `d568482ba84df6e531698b1f531810860995ca24d69495427fe43aee6017f52c` | | |
| 44 | - | | `unstable/relative-pointer/relative-pointer-unstable-v1.xml` | `relativepointer/relative-pointer-unstable-v1.xml` | `ab4930dd3084f732b6fdd12ee6dbd0a112a758ed8a57b170366391dbeb1a22ff` | | |
| 45 | - | | `unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml` | `shortcutsinhibit/keyboard-shortcuts-inhibit-unstable-v1.xml` | `9117d9e8ec02e9a3c3c55803b41e1227e76986f555f7c12eeb29f796fa63e69b` | | |
| 46 | - | | `staging/tearing-control/tearing-control-v1.xml` | `tearingcontrol/tearing-control-v1.xml` | `846895b4a90ba1ddd75673cefc596480beef318f1694ec7dbca0fec54bb27043` | | |
| 47 | - | | `staging/ext-workspace/ext-workspace-v1.xml` | `workspace/ext-workspace-v1.xml` | `9b449d9d5d40f6032eba9813d18093b84f249a2cf38d6755dec7bca7eb96b0f3` | | |
| 48 | - | | `staging/xdg-activation/xdg-activation-v1.xml` | `xdgactivation/xdg-activation-v1.xml` | `d8418be2d5738d50aff788bef1c7574f33f26659aa045447ff2ef9b78c58fe01` | | |
| 49 | - | | `unstable/xdg-decoration/xdg-decoration-unstable-v1.xml` | `xdgdecoration/xdg-decoration-unstable-v1.xml` | `68753c4a85a28659e3aa1fe0f138329a8bf3dff0b4789f4663a2c7fedbfecf2f` | | |
| 50 | - | | `unstable/xdg-output/xdg-output-unstable-v1.xml` | `xdgoutput/xdg-output-unstable-v1.xml` | `363d547c3eefe8959160cac903ff90b311d4b183005557d73640d9df2cfd7f79` | | |
| 51 | - | ||
| 52 | - | ## wlr-protocols | |
| 53 | - | ||
| 54 | - | Source: `https://gitlab.freedesktop.org/wlroots/wlr-protocols`, commit | |
| 55 | - | `bf4fc79abc359eea5a0edec0ac6d4a2b2955f82a`. The XML files retain their upstream | |
| 56 | - | license grants, including the no-fee/no-advertising terms where applicable. | |
| 57 | - | ||
| 58 | - | | Upstream path | Vendored path | SHA-256 | | |
| 59 | - | |---|---|---| | |
| 60 | - | | `unstable/wlr-layer-shell-unstable-v1.xml` | `layershell/wlr-layer-shell-unstable-v1.xml` | `87e0b9c837aecd6977f76f3c47d73088b7159871f5d979dc1840f6cadb5e2ed8` | | |
| 61 | - | | `unstable/wlr-screencopy-unstable-v1.xml` | `screencopy/wlr-screencopy-unstable-v1.xml` | `131b8f9b4aad0c8a9cf705e90d2a1511a5ca0c477637fd3400cf1cc4fa963fb8` | | |
| 62 | - | | `unstable/wlr-foreign-toplevel-management-unstable-v1.xml` | `foreigntoplevel/wlr-foreign-toplevel-management-unstable-v1.xml` | `4ecc4588858e29fe680a33521e1f22bcf22071d66d1553fe96b4ddec03d591d2` | | |
| 63 | - | | `unstable/wlr-output-management-unstable-v1.xml` | `outputmanagement/wlr-output-management-unstable-v1.xml` | `65b0f82a6cf129bf1a1c31a2428795abd33886c15ddd5f3ad97e5922d7bdc3a7` | | |
| 64 | - | | `unstable/wlr-output-power-management-unstable-v1.xml` | `outputpower/wlr-output-power-management-unstable-v1.xml` | `7ebd98f3449d246a57829e4b4dd9fbc3ef98e3dd42fa94ea102f14f490eb20de` | | |
| 65 | - | ||
| 66 | - | ## wlroots input protocols | |
| 67 | - | ||
| 68 | - | Source: `https://gitlab.freedesktop.org/wlroots/wlroots`, tag `0.19.0`, peeled | |
| 69 | - | commit `13a62a23a258d96f902c740310d5c7c59784a4d1`. Both XML files retain their | |
| 70 | - | MIT-style license grants. | |
| 71 | - | ||
| 72 | - | | Upstream path | Vendored path | SHA-256 | | |
| 73 | - | |---|---|---| | |
| 74 | - | | `protocol/virtual-keyboard-unstable-v1.xml` | `virtualkeyboard/virtual-keyboard-unstable-v1.xml` | `7ad7870003ecd592cae47dc19d277a609b7f18fd7b7be012623cf3225a7294f5` | | |
| 75 | - | | `protocol/input-method-unstable-v2.xml` | `inputmethod/input-method-unstable-v2.xml` | `99414dbad9458e71aa1fa01bc45f94ca6685787bfcb4d98948f72c1b45b60703` | | |
| 76 | - | ||
| 77 | - | ## KDE server decoration | |
| 78 | - | ||
| 79 | - | Source: `https://invent.kde.org/libraries/plasma-wayland-protocols`, tag | |
| 80 | - | `v1.23.0`, peeled commit `c5ac4db818f4a575a6ccfe0065b73ecfaba6e93e`. | |
| 81 | - | The XML and its generated `kdeserverdecoration` bindings retain | |
| 82 | - | **LGPL-2.1-or-later**, including the copied protocol documentation. They are not | |
| 83 | - | relicensed under WLTurbo's MIT license. The [license text](../LICENSES/LGPL-2.1-or-later.txt) | |
| 84 | - | is included; generated files retain the upstream notice. | |
| 85 | - | ||
| 86 | - | | Upstream path | Vendored path | SHA-256 | | |
| 87 | - | |---|---|---| | |
| 88 | - | | `src/protocols/server-decoration.xml` | `kdeserverdecoration/server-decoration.xml` | `c5f857734bb190dc9adfb65fb05550a6245f12af1a2be5eefd05be199805a68c` | | |
| 89 | - | ||
| 90 | - | ## Cross-package types | |
| 91 | - | ||
| 92 | - | Cross-package references use canonical generated types. Cursor-shape depends on | |
| 93 | - | `tablet`; xdg-decoration and layer-shell depend on `xdgshell`; image-copy-capture | |
| 94 | - | depends on `imagecapturesource`, which depends on `extforeigntoplevel`. | |
D protocol/alphamodifier/alpha-modifier-v1.xml +0 -103
| @@ -1,103 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="alpha_modifier_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2024 Xaver Hugl | |
| 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="wp_alpha_modifier_v1" version="1"> | |
| 27 | - | <description summary="surface alpha modifier manager"> | |
| 28 | - | This interface allows a client to set a factor for the alpha values on a | |
| 29 | - | surface, which can be used to offload such operations to the compositor, | |
| 30 | - | which can in turn for example offload them to KMS. | |
| 31 | - | ||
| 32 | - | Warning! The protocol described in this file is currently in the testing | |
| 33 | - | phase. Backward compatible changes may be added together with the | |
| 34 | - | corresponding interface version bump. Backward incompatible changes can | |
| 35 | - | only be done by creating a new major version of the extension. | |
| 36 | - | </description> | |
| 37 | - | ||
| 38 | - | <request name="destroy" type="destructor"> | |
| 39 | - | <description summary="destroy the alpha modifier manager object"> | |
| 40 | - | Destroy the alpha modifier manager. This doesn't destroy objects | |
| 41 | - | created with the manager. | |
| 42 | - | </description> | |
| 43 | - | </request> | |
| 44 | - | ||
| 45 | - | <enum name="error"> | |
| 46 | - | <entry name="already_constructed" value="0" | |
| 47 | - | summary="wl_surface already has a alpha modifier object"/> | |
| 48 | - | </enum> | |
| 49 | - | ||
| 50 | - | <request name="get_surface"> | |
| 51 | - | <description summary="create a new alpha modifier surface object"> | |
| 52 | - | Create a new alpha modifier surface object associated with the | |
| 53 | - | given wl_surface. If there is already such an object associated with | |
| 54 | - | the wl_surface, the already_constructed error will be raised. | |
| 55 | - | </description> | |
| 56 | - | <arg name="id" type="new_id" interface="wp_alpha_modifier_surface_v1"/> | |
| 57 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 58 | - | </request> | |
| 59 | - | </interface> | |
| 60 | - | ||
| 61 | - | <interface name="wp_alpha_modifier_surface_v1" version="1"> | |
| 62 | - | <description summary="alpha modifier object for a surface"> | |
| 63 | - | This interface allows the client to set a factor for the alpha values on | |
| 64 | - | a surface, which can be used to offload such operations to the compositor. | |
| 65 | - | The default factor is UINT32_MAX. | |
| 66 | - | ||
| 67 | - | This object has to be destroyed before the associated wl_surface. Once the | |
| 68 | - | wl_surface is destroyed, all request on this object will raise the | |
| 69 | - | no_surface error. | |
| 70 | - | </description> | |
| 71 | - | ||
| 72 | - | <enum name="error"> | |
| 73 | - | <entry name="no_surface" value="0" summary="wl_surface was destroyed"/> | |
| 74 | - | </enum> | |
| 75 | - | ||
| 76 | - | <request name="destroy" type="destructor"> | |
| 77 | - | <description summary="destroy the alpha modifier object"> | |
| 78 | - | This destroys the object, and is equivalent to set_multiplier with | |
| 79 | - | a value of UINT32_MAX, with the same double-buffered semantics as | |
| 80 | - | set_multiplier. | |
| 81 | - | </description> | |
| 82 | - | </request> | |
| 83 | - | ||
| 84 | - | <request name="set_multiplier"> | |
| 85 | - | <description summary="specify the alpha multiplier"> | |
| 86 | - | Sets the alpha multiplier for the surface. The alpha multiplier is | |
| 87 | - | double-buffered state, see wl_surface.commit for details. | |
| 88 | - | ||
| 89 | - | This factor is applied in the compositor's blending space, as an | |
| 90 | - | additional step after the processing of per-pixel alpha values for the | |
| 91 | - | wl_surface. The exact meaning of the factor is thus undefined, unless | |
| 92 | - | the blending space is specified in a different extension. | |
| 93 | - | ||
| 94 | - | This multiplier is applied even if the buffer attached to the | |
| 95 | - | wl_surface doesn't have an alpha channel; in that case an alpha value | |
| 96 | - | of one is used instead. | |
| 97 | - | ||
| 98 | - | Zero means completely transparent, UINT32_MAX means completely opaque. | |
| 99 | - | </description> | |
| 100 | - | <arg name="factor" type="uint"/> | |
| 101 | - | </request> | |
| 102 | - | </interface> | |
| 103 | - | </protocol> | |
D protocol/alphamodifier/alpha-modifier-v1_generated.go +0 -138
| @@ -1,138 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: alpha_modifier_v1 | |
| 3 | - | // Source: alpha-modifier-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2024 Xaver Hugl | |
| 7 | - | // | |
| 8 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 9 | - | // copy of this software and associated documentation files (the "Software"), | |
| 10 | - | // to deal in the Software without restriction, including without limitation | |
| 11 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 12 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 13 | - | // Software is furnished to do so, subject to the following conditions: | |
| 14 | - | // | |
| 15 | - | // The above copyright notice and this permission notice (including the next | |
| 16 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | // Software. | |
| 18 | - | // | |
| 19 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 22 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 24 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 25 | - | // DEALINGS IN THE SOFTWARE. | |
| 26 | - | ||
| 27 | - | package alphamodifier | |
| 28 | - | ||
| 29 | - | import ( | |
| 30 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 31 | - | "github.com/bnema/wlturbo/wl" | |
| 32 | - | ) | |
| 33 | - | ||
| 34 | - | // ERROR_ALREADY_CONSTRUCTED is the error already_constructed value. | |
| 35 | - | const ERROR_ALREADY_CONSTRUCTED = 0 | |
| 36 | - | ||
| 37 | - | // ERROR_NO_SURFACE is the error no_surface value. | |
| 38 | - | const ERROR_NO_SURFACE = 0 | |
| 39 | - | ||
| 40 | - | // WpAlphaModifierInterface is the protocol interface name. | |
| 41 | - | const WpAlphaModifierInterface = "wp_alpha_modifier_v1" | |
| 42 | - | ||
| 43 | - | // WpAlphaModifier is the generated binding for wp_alpha_modifier_v1 version 1. | |
| 44 | - | type WpAlphaModifier struct { | |
| 45 | - | wl.BaseProxy | |
| 46 | - | } | |
| 47 | - | ||
| 48 | - | // NewWpAlphaModifier returns an unbound WpAlphaModifier. | |
| 49 | - | func NewWpAlphaModifier(ctx *wl.Context) *WpAlphaModifier { | |
| 50 | - | obj := &WpAlphaModifier{} | |
| 51 | - | obj.SetContext(ctx) | |
| 52 | - | ctx.Register(obj) | |
| 53 | - | return obj | |
| 54 | - | } | |
| 55 | - | ||
| 56 | - | // Destroy the alpha modifier manager. This doesn't destroy objects created with the manager. | |
| 57 | - | func (o *WpAlphaModifier) Destroy() error { | |
| 58 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_alpha_modifier_v1.destroy", Destructor: true}); err != nil { | |
| 59 | - | return err | |
| 60 | - | } | |
| 61 | - | return nil | |
| 62 | - | } | |
| 63 | - | ||
| 64 | - | // Create a new alpha modifier surface object associated with the given wl_surface. If there is already such an object associated with the wl_surface, the already_constructed error will be raised. | |
| 65 | - | func (o *WpAlphaModifier) GetSurface(surface *cross_wl_surface.Surface) (*WpAlphaModifierSurface, error) { | |
| 66 | - | var arg1 wl.Object | |
| 67 | - | if surface != nil { | |
| 68 | - | arg1 = surface | |
| 69 | - | } | |
| 70 | - | child := &WpAlphaModifierSurface{} | |
| 71 | - | child.SetContext(o.Context()) | |
| 72 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_alpha_modifier_v1.get_surface", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 73 | - | return nil, err | |
| 74 | - | } | |
| 75 | - | return child, nil | |
| 76 | - | } | |
| 77 | - | ||
| 78 | - | // EventSignature returns the declared event argument types in wire order. | |
| 79 | - | func (o *WpAlphaModifier) EventSignature(opcode uint16) (string, bool) { | |
| 80 | - | switch opcode { | |
| 81 | - | default: | |
| 82 | - | return "", false | |
| 83 | - | } | |
| 84 | - | } | |
| 85 | - | ||
| 86 | - | // Dispatch decodes one event on wp_alpha_modifier_v1 and calls the registered handlers. | |
| 87 | - | func (o *WpAlphaModifier) Dispatch(event *wl.Event) { | |
| 88 | - | switch event.Opcode { | |
| 89 | - | default: | |
| 90 | - | } | |
| 91 | - | } | |
| 92 | - | ||
| 93 | - | // WpAlphaModifierSurfaceInterface is the protocol interface name. | |
| 94 | - | const WpAlphaModifierSurfaceInterface = "wp_alpha_modifier_surface_v1" | |
| 95 | - | ||
| 96 | - | // WpAlphaModifierSurface is the generated binding for wp_alpha_modifier_surface_v1 version 1. | |
| 97 | - | type WpAlphaModifierSurface struct { | |
| 98 | - | wl.BaseProxy | |
| 99 | - | } | |
| 100 | - | ||
| 101 | - | // NewWpAlphaModifierSurface returns an unbound WpAlphaModifierSurface. | |
| 102 | - | func NewWpAlphaModifierSurface(ctx *wl.Context) *WpAlphaModifierSurface { | |
| 103 | - | obj := &WpAlphaModifierSurface{} | |
| 104 | - | obj.SetContext(ctx) | |
| 105 | - | ctx.Register(obj) | |
| 106 | - | return obj | |
| 107 | - | } | |
| 108 | - | ||
| 109 | - | // This destroys the object, and is equivalent to set_multiplier with a value of UINT32_MAX, with the same double-buffered semantics as set_multiplier. | |
| 110 | - | func (o *WpAlphaModifierSurface) Destroy() error { | |
| 111 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_alpha_modifier_surface_v1.destroy", Destructor: true}); err != nil { | |
| 112 | - | return err | |
| 113 | - | } | |
| 114 | - | return nil | |
| 115 | - | } | |
| 116 | - | ||
| 117 | - | // Sets the alpha multiplier for the surface. The alpha multiplier is double-buffered state, see wl_surface.commit for details. This factor is applied in the compositor's blending space, as an additional step after the processing of per-pixel alpha values for the wl_surface. The exact meaning of the factor is thus undefined, unless the blending space is specified in a different extension. This multiplier is applied even if the buffer attached to the wl_surface doesn't have an alpha channel; in that case an alpha value of one is used instead. Zero means completely transparent, UINT32_MAX means completely opaque. | |
| 118 | - | func (o *WpAlphaModifierSurface) SetMultiplier(factor uint32) error { | |
| 119 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_alpha_modifier_surface_v1.set_multiplier"}, wl.ArgUint(factor)); err != nil { | |
| 120 | - | return err | |
| 121 | - | } | |
| 122 | - | return nil | |
| 123 | - | } | |
| 124 | - | ||
| 125 | - | // EventSignature returns the declared event argument types in wire order. | |
| 126 | - | func (o *WpAlphaModifierSurface) EventSignature(opcode uint16) (string, bool) { | |
| 127 | - | switch opcode { | |
| 128 | - | default: | |
| 129 | - | return "", false | |
| 130 | - | } | |
| 131 | - | } | |
| 132 | - | ||
| 133 | - | // Dispatch decodes one event on wp_alpha_modifier_surface_v1 and calls the registered handlers. | |
| 134 | - | func (o *WpAlphaModifierSurface) Dispatch(event *wl.Event) { | |
| 135 | - | switch event.Opcode { | |
| 136 | - | default: | |
| 137 | - | } | |
| 138 | - | } | |
D protocol/alphamodifier/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package alphamodifier | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p alphamodifier -o alpha-modifier-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core alpha-modifier-v1.xml | |
D protocol/colormanagement/color-management-v1.xml +0 -1756
| @@ -1,1756 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="color_management_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright 2019 Sebastian Wick | |
| 5 | - | Copyright 2019 Erwin Burema | |
| 6 | - | Copyright 2020 AMD | |
| 7 | - | Copyright 2020-2024 Collabora, Ltd. | |
| 8 | - | Copyright 2024 Xaver Hugl | |
| 9 | - | Copyright 2022-2025 Red Hat, Inc. | |
| 10 | - | ||
| 11 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 12 | - | copy of this software and associated documentation files (the "Software"), | |
| 13 | - | to deal in the Software without restriction, including without limitation | |
| 14 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 15 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 16 | - | Software is furnished to do so, subject to the following conditions: | |
| 17 | - | ||
| 18 | - | The above copyright notice and this permission notice (including the next | |
| 19 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 20 | - | Software. | |
| 21 | - | ||
| 22 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 23 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 24 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 25 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 26 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 27 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 28 | - | DEALINGS IN THE SOFTWARE. | |
| 29 | - | </copyright> | |
| 30 | - | ||
| 31 | - | <description summary="color management protocol"> | |
| 32 | - | The aim of the color management extension is to allow clients to know | |
| 33 | - | the color properties of outputs, and to tell the compositor about the color | |
| 34 | - | properties of their content on surfaces. All surface contents must be | |
| 35 | - | readily intended for some display, but not necessarily for the display at | |
| 36 | - | hand. Doing this enables a compositor to perform automatic color management | |
| 37 | - | of content for different outputs according to how content is intended to | |
| 38 | - | look like. | |
| 39 | - | ||
| 40 | - | For an introduction, see the section "Color management" in the Wayland | |
| 41 | - | documentation at https://wayland.freedesktop.org/docs/html/ . | |
| 42 | - | ||
| 43 | - | The color properties are represented as an image description object which | |
| 44 | - | is immutable after it has been created. A wl_output always has an | |
| 45 | - | associated image description that clients can observe. A wl_surface | |
| 46 | - | always has an associated preferred image description as a hint chosen by | |
| 47 | - | the compositor that clients can also observe. Clients can set an image | |
| 48 | - | description on a wl_surface to denote the color characteristics of the | |
| 49 | - | surface contents. | |
| 50 | - | ||
| 51 | - | An image description essentially defines a display and (indirectly) its | |
| 52 | - | viewing environment. An image description includes SDR and HDR colorimetry | |
| 53 | - | and encoding, HDR metadata, and some parameters related to the viewing | |
| 54 | - | environment. An image description does not include the properties set | |
| 55 | - | through color-representation extension. It is expected that the | |
| 56 | - | color-representation extension is used in conjunction with the | |
| 57 | - | color-management extension when necessary, particularly with the YUV family | |
| 58 | - | of pixel formats. | |
| 59 | - | ||
| 60 | - | The normative appendix for this protocol is in the appendix.md file beside | |
| 61 | - | this XML file. | |
| 62 | - | ||
| 63 | - | The color-and-hdr repository | |
| 64 | - | (https://gitlab.freedesktop.org/pq/color-and-hdr) contains | |
| 65 | - | background information on the protocol design and legacy color management. | |
| 66 | - | It also contains a glossary, learning resources for digital color, tools, | |
| 67 | - | samples and more. | |
| 68 | - | ||
| 69 | - | The terminology used in this protocol is based on common color science and | |
| 70 | - | color encoding terminology where possible. The glossary in the color-and-hdr | |
| 71 | - | repository shall be the authority on the definition of terms in this | |
| 72 | - | protocol. | |
| 73 | - | ||
| 74 | - | Warning! The protocol described in this file is currently in the testing | |
| 75 | - | phase. Backward compatible changes may be added together with the | |
| 76 | - | corresponding interface version bump. Backward incompatible changes can | |
| 77 | - | only be done by creating a new major version of the extension. | |
| 78 | - | </description> | |
| 79 | - | ||
| 80 | - | <interface name="wp_color_manager_v1" version="3"> | |
| 81 | - | <description summary="color manager singleton"> | |
| 82 | - | A singleton global interface used for getting color management extensions | |
| 83 | - | for wl_surface and wl_output objects, and for creating client defined | |
| 84 | - | image description objects. The extension interfaces allow | |
| 85 | - | getting the image description of outputs and setting the image | |
| 86 | - | description of surfaces. | |
| 87 | - | ||
| 88 | - | Compositors should never remove this global. | |
| 89 | - | </description> | |
| 90 | - | ||
| 91 | - | <request name="destroy" type="destructor"> | |
| 92 | - | <description summary="destroy the color manager"> | |
| 93 | - | Destroy the wp_color_manager_v1 object. This does not affect any other | |
| 94 | - | objects in any way. | |
| 95 | - | </description> | |
| 96 | - | </request> | |
| 97 | - | ||
| 98 | - | <enum name="error"> | |
| 99 | - | <entry name="unsupported_feature" value="0" | |
| 100 | - | summary="request not supported"/> | |
| 101 | - | <entry name="surface_exists" value="1" | |
| 102 | - | summary="color management surface exists already"/> | |
| 103 | - | </enum> | |
| 104 | - | ||
| 105 | - | <enum name="render_intent"> | |
| 106 | - | <description summary="rendering intents"> | |
| 107 | - | See the ICC.1:2022 specification from the International Color Consortium | |
| 108 | - | for more details about rendering intents. | |
| 109 | - | ||
| 110 | - | The principles of ICC defined rendering intents apply with all types of | |
| 111 | - | image descriptions, not only those with ICC file profiles. | |
| 112 | - | ||
| 113 | - | Compositors must support the perceptual rendering intent. Other | |
| 114 | - | rendering intents are optional. | |
| 115 | - | </description> | |
| 116 | - | ||
| 117 | - | <entry name="perceptual" value="0" | |
| 118 | - | summary="perceptual"/> | |
| 119 | - | <entry name="relative" value="1" | |
| 120 | - | summary="media-relative colorimetric"/> | |
| 121 | - | <entry name="saturation" value="2" | |
| 122 | - | summary="saturation"/> | |
| 123 | - | <entry name="absolute" value="3" | |
| 124 | - | summary="ICC-absolute colorimetric"/> | |
| 125 | - | <entry name="relative_bpc" value="4" | |
| 126 | - | summary="media-relative colorimetric + black point compensation"/> | |
| 127 | - | <entry name="absolute_no_adaptation" value="5" since="2"> | |
| 128 | - | <description summary="ICC-absolute colorimetric without adaptation"> | |
| 129 | - | This rendering intent is a modified absolute rendering intent that | |
| 130 | - | assumes the viewer is not adapted to the display white point, so no | |
| 131 | - | chromatic adaptation between surface and display is done. | |
| 132 | - | This can be useful for color proofing applications. | |
| 133 | - | </description> | |
| 134 | - | </entry> | |
| 135 | - | </enum> | |
| 136 | - | ||
| 137 | - | <enum name="feature"> | |
| 138 | - | <description summary="compositor supported features"/> | |
| 139 | - | ||
| 140 | - | <entry name="icc_v2_v4" value="0" | |
| 141 | - | summary="create_icc_creator request"/> | |
| 142 | - | <entry name="parametric" value="1" | |
| 143 | - | summary="create_parametric_creator request"/> | |
| 144 | - | <entry name="set_primaries" value="2" | |
| 145 | - | summary="parametric set_primaries request"/> | |
| 146 | - | <entry name="set_tf_power" value="3" | |
| 147 | - | summary="parametric set_tf_power request"/> | |
| 148 | - | <entry name="set_luminances" value="4" | |
| 149 | - | summary="parametric set_luminances request"/> | |
| 150 | - | <entry name="set_mastering_display_primaries" value="5"> | |
| 151 | - | <description summary="parametric set_mastering_display_primaries request"> | |
| 152 | - | The compositor supports set_mastering_display_primaries request with a | |
| 153 | - | target color volume fully contained inside the primary color volume. | |
| 154 | - | </description> | |
| 155 | - | </entry> | |
| 156 | - | <entry name="extended_target_volume" value="6"> | |
| 157 | - | <description summary="parametric target exceeds primary color volume"> | |
| 158 | - | The compositor additionally supports target color volumes that | |
| 159 | - | extend outside of the primary color volume. | |
| 160 | - | ||
| 161 | - | This can only be advertised if feature set_mastering_display_primaries | |
| 162 | - | is supported as well. | |
| 163 | - | </description> | |
| 164 | - | </entry> | |
| 165 | - | <entry name="windows_scrgb" value="7" | |
| 166 | - | summary="create_windows_scrgb request"/> | |
| 167 | - | <entry name="windows_bt2100" value="8" | |
| 168 | - | summary="create_windows_bt2100 request"/> | |
| 169 | - | </enum> | |
| 170 | - | ||
| 171 | - | <enum name="primaries"> | |
| 172 | - | <description summary="named color primaries"> | |
| 173 | - | Named color primaries used to encode well-known sets of primaries. | |
| 174 | - | ||
| 175 | - | A value of 0 is invalid and will never be present in the list of enums. | |
| 176 | - | </description> | |
| 177 | - | ||
| 178 | - | <entry name="srgb" value="1"> | |
| 179 | - | <description summary="Color primaries for the sRGB color space as defined by the BT.709 standard"> | |
| 180 | - | Color primaries as defined by | |
| 181 | - | - Rec. ITU-R BT.709-6 | |
| 182 | - | - Rec. ITU-R BT.1361-0 conventional colour gamut system and extended | |
| 183 | - | colour gamut system (historical) | |
| 184 | - | - IEC 61966-2-1 sRGB or sYCC | |
| 185 | - | - IEC 61966-2-4 | |
| 186 | - | - Society of Motion Picture and Television Engineers (SMPTE) RP 177 | |
| 187 | - | (1993) Annex B | |
| 188 | - | </description> | |
| 189 | - | </entry> | |
| 190 | - | <entry name="pal_m" value="2"> | |
| 191 | - | <description summary="Color primaries for PAL-M as defined by the BT.470 standard"> | |
| 192 | - | Color primaries as defined by | |
| 193 | - | - Rec. ITU-R BT.470-6 System M (historical) | |
| 194 | - | - United States National Television System Committee 1953 | |
| 195 | - | Recommendation for transmission standards for color television | |
| 196 | - | - United States Federal Communications Commission (2003) Title 47 Code | |
| 197 | - | of Federal Regulations 73.682 (a)(20) | |
| 198 | - | </description> | |
| 199 | - | </entry> | |
| 200 | - | <entry name="pal" value="3"> | |
| 201 | - | <description summary="Color primaries for PAL as defined by the BT.601 standard"> | |
| 202 | - | Color primaries as defined by | |
| 203 | - | - Rec. ITU-R BT.470-6 System B, G (historical) | |
| 204 | - | - Rec. ITU-R BT.601-7 625 | |
| 205 | - | - Rec. ITU-R BT.1358-0 625 (historical) | |
| 206 | - | - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM | |
| 207 | - | </description> | |
| 208 | - | </entry> | |
| 209 | - | <entry name="ntsc" value="4"> | |
| 210 | - | <description summary="Color primaries for NTSC as defined by the BT.601 standard"> | |
| 211 | - | Color primaries as defined by | |
| 212 | - | - Rec. ITU-R BT.601-7 525 | |
| 213 | - | - Rec. ITU-R BT.1358-1 525 or 625 (historical) | |
| 214 | - | - Rec. ITU-R BT.1700-0 NTSC | |
| 215 | - | - SMPTE 170M (2004) | |
| 216 | - | - SMPTE 240M (1999) (historical) | |
| 217 | - | </description> | |
| 218 | - | </entry> | |
| 219 | - | <entry name="generic_film" value="5"> | |
| 220 | - | <description summary="Generic film with colour filters using Illuminant C"> | |
| 221 | - | Color primaries as defined by Recommendation ITU-T H.273 | |
| 222 | - | "Coding-independent code points for video signal type identification" | |
| 223 | - | for "generic film". | |
| 224 | - | </description> | |
| 225 | - | </entry> | |
| 226 | - | <entry name="bt2020" value="6"> | |
| 227 | - | <description summary="Color primaries as defined by the BT.2020 and BT.2100 standard"> | |
| 228 | - | Color primaries as defined by | |
| 229 | - | - Rec. ITU-R BT.2020-2 | |
| 230 | - | - Rec. ITU-R BT.2100-0 | |
| 231 | - | </description> | |
| 232 | - | </entry> | |
| 233 | - | <entry name="cie1931_xyz" value="7"> | |
| 234 | - | <description summary="Color primaries of the full CIE 1931 XYZ color space"> | |
| 235 | - | Color primaries as defined as the maximum of the CIE 1931 XYZ color | |
| 236 | - | space by | |
| 237 | - | - SMPTE ST 428-1 | |
| 238 | - | - (CIE 1931 XYZ as in ISO 11664-1) | |
| 239 | - | </description> | |
| 240 | - | </entry> | |
| 241 | - | <entry name="dci_p3" value="8"> | |
| 242 | - | <description summary="Color primaries of the DCI P3 color space as defined by the SMPTE RP 431 standard"> | |
| 243 | - | Color primaries as defined by Digital Cinema System and published in | |
| 244 | - | SMPTE RP 431-2 (2011). | |
| 245 | - | </description> | |
| 246 | - | </entry> | |
| 247 | - | <entry name="display_p3" value="9"> | |
| 248 | - | <description summary="Color primaries of Display P3 variant of the DCI-P3 color space as defined by the SMPTE EG 432 standard"> | |
| 249 | - | Color primaries as defined by Digital Cinema System and published in | |
| 250 | - | SMPTE EG 432-1 (2010). | |
| 251 | - | </description> | |
| 252 | - | </entry> | |
| 253 | - | <entry name="adobe_rgb" value="10"> | |
| 254 | - | <description summary="Color primaries of the Adobe RGB color space as defined by the ISO 12640 standard"> | |
| 255 | - | Color primaries as defined by Adobe as "Adobe RGB" and later published | |
| 256 | - | by ISO 12640-4 (2011). | |
| 257 | - | </description> | |
| 258 | - | </entry> | |
| 259 | - | </enum> | |
| 260 | - | ||
| 261 | - | <enum name="transfer_function"> | |
| 262 | - | <description summary="named transfer functions"> | |
| 263 | - | Named transfer functions used to represent well-known transfer | |
| 264 | - | characteristics of displays. | |
| 265 | - | ||
| 266 | - | A value of 0 is invalid and will never be present in the list of enums. | |
| 267 | - | ||
| 268 | - | See appendix.md for the formulae. | |
| 269 | - | </description> | |
| 270 | - | ||
| 271 | - | <entry name="bt1886" value="1"> | |
| 272 | - | <description summary="BT.1886 display transfer characteristic"> | |
| 273 | - | Rec. ITU-R BT.1886 is the display transfer characteristic assumed by | |
| 274 | - | - Rec. ITU-R BT.601-7 525 and 625 | |
| 275 | - | - Rec. ITU-R BT.709-6 | |
| 276 | - | - Rec. ITU-R BT.2020-2 | |
| 277 | - | ||
| 278 | - | This TF implies these default luminances from Rec. ITU-R BT.2035: | |
| 279 | - | - primary color volume minimum: 0.01 cd/m² | |
| 280 | - | - primary color volume maximum: 100 cd/m² | |
| 281 | - | - reference white: 100 cd/m² | |
| 282 | - | </description> | |
| 283 | - | </entry> | |
| 284 | - | <entry name="gamma22" value="2"> | |
| 285 | - | <description summary="Assumed display gamma 2.2 transfer function"> | |
| 286 | - | Transfer characteristics as defined by | |
| 287 | - | - Rec. ITU-R BT.470-6 System M (historical) | |
| 288 | - | - United States National Television System Committee 1953 | |
| 289 | - | Recommendation for transmission standards for color television | |
| 290 | - | - United States Federal Communications Commission (2003) Title 47 Code | |
| 291 | - | of Federal Regulations 73.682 (a) (20) | |
| 292 | - | - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM | |
| 293 | - | - IEC 61966-2-1 (reference display) | |
| 294 | - | </description> | |
| 295 | - | </entry> | |
| 296 | - | <entry name="gamma28" value="3"> | |
| 297 | - | <description summary="Assumed display gamma 2.8 transfer function"> | |
| 298 | - | Transfer characteristics as defined by | |
| 299 | - | - Rec. ITU-R BT.470-6 System B, G (historical) | |
| 300 | - | </description> | |
| 301 | - | </entry> | |
| 302 | - | <entry name="st240" value="4"> | |
| 303 | - | <description summary="SMPTE ST 240 transfer function"> | |
| 304 | - | Transfer characteristics as defined by | |
| 305 | - | - SMPTE ST 240 (1999) | |
| 306 | - | </description> | |
| 307 | - | </entry> | |
| 308 | - | <entry name="ext_linear" value="5"> | |
| 309 | - | <description summary="extended linear transfer function"> | |
| 310 | - | Linear transfer function defined over all real numbers. | |
| 311 | - | Normalised electrical values are equal the normalised optical values. | |
| 312 | - | </description> | |
| 313 | - | </entry> | |
| 314 | - | <entry name="log_100" value="6"> | |
| 315 | - | <description summary="logarithmic 100:1 transfer function"> | |
| 316 | - | Logarithmic transfer characteristic (100:1 range). | |
| 317 | - | </description> | |
| 318 | - | </entry> | |
| 319 | - | <entry name="log_316" value="7"> | |
| 320 | - | <description summary="logarithmic (100*Sqrt(10) : 1) transfer function"> | |
| 321 | - | Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range). | |
| 322 | - | </description> | |
| 323 | - | </entry> | |
| 324 | - | <entry name="xvycc" value="8"> | |
| 325 | - | <description summary="IEC 61966-2-4 transfer function"> | |
| 326 | - | Transfer characteristics as defined by | |
| 327 | - | - IEC 61966-2-4 | |
| 328 | - | </description> | |
| 329 | - | </entry> | |
| 330 | - | <entry name="srgb" value="9" deprecated-since="2"> | |
| 331 | - | <description summary="Deprecated (ambiguous sRGB transfer function)"> | |
| 332 | - | Transfer characteristics as defined by | |
| 333 | - | - IEC 61966-2-1 sRGB | |
| 334 | - | ||
| 335 | - | As a rule of thumb, use gamma22 for video, motion picture and | |
| 336 | - | computer graphics, or compound_power_2_4 for ICC calibrated print | |
| 337 | - | workflows. | |
| 338 | - | </description> | |
| 339 | - | </entry> | |
| 340 | - | <entry name="ext_srgb" value="10" deprecated-since="2"> | |
| 341 | - | <description summary="Deprecated (Extended sRGB piece-wise transfer function)"> | |
| 342 | - | Transfer characteristics as defined by | |
| 343 | - | - IEC 61966-2-1 sYCC | |
| 344 | - | </description> | |
| 345 | - | </entry> | |
| 346 | - | <entry name="st2084_pq" value="11"> | |
| 347 | - | <description summary="perceptual quantizer transfer function"> | |
| 348 | - | Transfer characteristics as defined by | |
| 349 | - | - SMPTE ST 2084 (2014) for 10-, 12-, 14- and 16-bit systems | |
| 350 | - | - Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system | |
| 351 | - | ||
| 352 | - | This TF implies these default luminances | |
| 353 | - | - primary color volume minimum: 0.005 cd/m² | |
| 354 | - | - primary color volume maximum: 10000 cd/m² | |
| 355 | - | - reference white: 203 cd/m² | |
| 356 | - | ||
| 357 | - | The difference between the primary color volume minimum and maximum | |
| 358 | - | must be approximately 10000 cd/m² as that is the swing of the EOTF | |
| 359 | - | defined by ST 2084 and BT.2100. The default value for the | |
| 360 | - | reference white is a protocol addition: it is suggested by | |
| 361 | - | Report ITU-R BT.2408-7 and is not part of ST 2084 or BT.2100. | |
| 362 | - | </description> | |
| 363 | - | </entry> | |
| 364 | - | <entry name="st428" value="12"> | |
| 365 | - | <description summary="SMPTE ST 428 transfer function"> | |
| 366 | - | Transfer characteristics as defined by | |
| 367 | - | - SMPTE ST 428-1 (2019) | |
| 368 | - | </description> | |
| 369 | - | </entry> | |
| 370 | - | <entry name="hlg" value="13"> | |
| 371 | - | <description summary="hybrid log-gamma transfer function"> | |
| 372 | - | Transfer characteristics as defined by | |
| 373 | - | - ARIB STD-B67 (2015) | |
| 374 | - | - Rec. ITU-R BT.2100-2 hybrid log-gamma (HLG) system | |
| 375 | - | ||
| 376 | - | This TF implies these default luminances | |
| 377 | - | - primary color volume minimum: 0.005 cd/m² | |
| 378 | - | - primary color volume maximum: 1000 cd/m² | |
| 379 | - | - reference white: 203 cd/m² | |
| 380 | - | ||
| 381 | - | HLG is a relative display-referred signal with a specified | |
| 382 | - | non-linear mapping to the display peak luminance (the HLG OOTF). | |
| 383 | - | All absolute luminance values used here for HLG assume a 1000 cd/m² | |
| 384 | - | peak display. | |
| 385 | - | ||
| 386 | - | The default value for the reference white is a protocol addition: | |
| 387 | - | it is suggested by Report ITU-R BT.2408-7 and is not part of | |
| 388 | - | ARIB STD-B67 or BT.2100. | |
| 389 | - | </description> | |
| 390 | - | </entry> | |
| 391 | - | <entry name="compound_power_2_4" value="14" since="2"> | |
| 392 | - | <description summary="IEC 61966-2-1 encoding function"> | |
| 393 | - | Encoding characteristics as defined by IEC 61966-2-1, for displays | |
| 394 | - | that invert the encoding function. | |
| 395 | - | </description> | |
| 396 | - | </entry> | |
| 397 | - | </enum> | |
| 398 | - | ||
| 399 | - | <request name="get_output"> | |
| 400 | - | <description summary="create a color management interface for a wl_output"> | |
| 401 | - | This creates a new wp_color_management_output_v1 object for the | |
| 402 | - | given wl_output. | |
| 403 | - | ||
| 404 | - | See the wp_color_management_output_v1 interface for more details. | |
| 405 | - | </description> | |
| 406 | - | ||
| 407 | - | <arg name="id" type="new_id" interface="wp_color_management_output_v1"/> | |
| 408 | - | <arg name="output" type="object" interface="wl_output"/> | |
| 409 | - | </request> | |
| 410 | - | ||
| 411 | - | <request name="get_surface"> | |
| 412 | - | <description summary="create a color management interface for a wl_surface"> | |
| 413 | - | If a wp_color_management_surface_v1 object already exists for the given | |
| 414 | - | wl_surface, the protocol error surface_exists is raised. | |
| 415 | - | ||
| 416 | - | This creates a new color wp_color_management_surface_v1 object for the | |
| 417 | - | given wl_surface. | |
| 418 | - | ||
| 419 | - | See the wp_color_management_surface_v1 interface for more details. | |
| 420 | - | </description> | |
| 421 | - | ||
| 422 | - | <arg name="id" type="new_id" interface="wp_color_management_surface_v1"/> | |
| 423 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 424 | - | </request> | |
| 425 | - | ||
| 426 | - | <request name="get_surface_feedback"> | |
| 427 | - | <description summary="create a color management feedback interface"> | |
| 428 | - | This creates a new color wp_color_management_surface_feedback_v1 object | |
| 429 | - | for the given wl_surface. | |
| 430 | - | ||
| 431 | - | See the wp_color_management_surface_feedback_v1 interface for more | |
| 432 | - | details. | |
| 433 | - | </description> | |
| 434 | - | ||
| 435 | - | <arg name="id" type="new_id" | |
| 436 | - | interface="wp_color_management_surface_feedback_v1"/> | |
| 437 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 438 | - | </request> | |
| 439 | - | ||
| 440 | - | <request name="create_icc_creator"> | |
| 441 | - | <description summary="make a new ICC-based image description creator object"> | |
| 442 | - | Makes a new ICC-based image description creator object with all | |
| 443 | - | properties initially unset. The client can then use the object's | |
| 444 | - | interface to define all the required properties for an image description | |
| 445 | - | and finally create a wp_image_description_v1 object. | |
| 446 | - | ||
| 447 | - | This request can be used when the compositor advertises | |
| 448 | - | wp_color_manager_v1.feature.icc_v2_v4. | |
| 449 | - | Otherwise this request raises the protocol error unsupported_feature. | |
| 450 | - | </description> | |
| 451 | - | ||
| 452 | - | <arg name="obj" | |
| 453 | - | type="new_id" interface="wp_image_description_creator_icc_v1" | |
| 454 | - | summary="the new creator object"/> | |
| 455 | - | </request> | |
| 456 | - | ||
| 457 | - | <request name="create_parametric_creator"> | |
| 458 | - | <description summary="make a new parametric image description creator object"> | |
| 459 | - | Makes a new parametric image description creator object with all | |
| 460 | - | properties initially unset. The client can then use the object's | |
| 461 | - | interface to define all the required properties for an image description | |
| 462 | - | and finally create a wp_image_description_v1 object. | |
| 463 | - | ||
| 464 | - | This request can be used when the compositor advertises | |
| 465 | - | wp_color_manager_v1.feature.parametric. | |
| 466 | - | Otherwise this request raises the protocol error unsupported_feature. | |
| 467 | - | </description> | |
| 468 | - | ||
| 469 | - | <arg name="obj" | |
| 470 | - | type="new_id" interface="wp_image_description_creator_params_v1" | |
| 471 | - | summary="the new creator object"/> | |
| 472 | - | </request> | |
| 473 | - | ||
| 474 | - | <request name="create_windows_scrgb"> | |
| 475 | - | <description summary="create Windows-scRGB image description object"> | |
| 476 | - | This creates a pre-defined image description for the so-called | |
| 477 | - | Windows-scRGB stimulus encoding. This comes from the Windows 10 handling | |
| 478 | - | of its own definition of an scRGB color space for an HDR screen | |
| 479 | - | driven in BT.2100/PQ signalling mode. | |
| 480 | - | ||
| 481 | - | Windows-scRGB uses sRGB (BT.709) color primaries and white point. | |
| 482 | - | The transfer characteristic is extended linear. | |
| 483 | - | ||
| 484 | - | The nominal color channel value range is extended, meaning it includes | |
| 485 | - | negative and greater than 1.0 values. Negative values are used to | |
| 486 | - | escape the sRGB color gamut boundaries. To make use of the extended | |
| 487 | - | range, the client needs to use a pixel format that can represent those | |
| 488 | - | values, e.g. floating-point 16 bits per channel. | |
| 489 | - | ||
| 490 | - | Nominal color value R=G=B=0.0 corresponds to BT.2100/PQ system | |
| 491 | - | 0 cd/m², and R=G=B=1.0 corresponds to BT.2100/PQ system 80 cd/m². | |
| 492 | - | The maximum is R=G=B=125.0 corresponding to 10k cd/m². | |
| 493 | - | ||
| 494 | - | Windows-scRGB is displayed by Windows 10 by converting it to | |
| 495 | - | BT.2100/PQ, maintaining the CIE 1931 chromaticity and mapping the | |
| 496 | - | luminance as above. No adjustment is made to the signal to account | |
| 497 | - | for the viewing conditions. | |
| 498 | - | ||
| 499 | - | The reference white level of Windows-scRGB is unknown. If a | |
| 500 | - | reference white level must be assumed for compositor processing, it | |
| 501 | - | should be R=G=B=2.5375 corresponding to 203 cd/m² of Report ITU-R | |
| 502 | - | BT.2408-7. | |
| 503 | - | ||
| 504 | - | The target color volume of Windows-scRGB is unknown. The color gamut | |
| 505 | - | may be anything between sRGB and BT.2100. | |
| 506 | - | ||
| 507 | - | Note: EGL_EXT_gl_colorspace_scrgb_linear definition differs from | |
| 508 | - | Windows-scRGB by using R=G=B=1.0 as the reference white level, while | |
| 509 | - | Windows-scRGB reference white level is unknown or varies. However, | |
| 510 | - | it seems probable that Windows implements both | |
| 511 | - | EGL_EXT_gl_colorspace_scrgb_linear and Vulkan | |
| 512 | - | VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT as Windows-scRGB. | |
| 513 | - | ||
| 514 | - | This request can be used when the compositor advertises | |
| 515 | - | wp_color_manager_v1.feature.windows_scrgb. | |
| 516 | - | Otherwise this request raises the protocol error unsupported_feature. | |
| 517 | - | ||
| 518 | - | The resulting image description object does not allow get_information | |
| 519 | - | request. The wp_image_description_v1.ready event shall be sent. | |
| 520 | - | </description> | |
| 521 | - | ||
| 522 | - | <arg name="image_description" | |
| 523 | - | type="new_id" interface="wp_image_description_v1"/> | |
| 524 | - | </request> | |
| 525 | - | ||
| 526 | - | <event name="supported_intent"> | |
| 527 | - | <description summary="supported rendering intent"> | |
| 528 | - | When this object is created, it shall immediately send this event once | |
| 529 | - | for each rendering intent the compositor supports. | |
| 530 | - | ||
| 531 | - | A compositor must not advertise intents that are deprecated in the | |
| 532 | - | bound version of the interface. | |
| 533 | - | </description> | |
| 534 | - | ||
| 535 | - | <arg name="render_intent" type="uint" enum="render_intent" | |
| 536 | - | summary="rendering intent"/> | |
| 537 | - | </event> | |
| 538 | - | ||
| 539 | - | <event name="supported_feature"> | |
| 540 | - | <description summary="supported features"> | |
| 541 | - | When this object is created, it shall immediately send this event once | |
| 542 | - | for each compositor supported feature listed in the enumeration. | |
| 543 | - | ||
| 544 | - | A compositor must not advertise features that are deprecated in the | |
| 545 | - | bound version of the interface. | |
| 546 | - | </description> | |
| 547 | - | ||
| 548 | - | <arg name="feature" type="uint" enum="feature" | |
| 549 | - | summary="supported feature"/> | |
| 550 | - | </event> | |
| 551 | - | ||
| 552 | - | <event name="supported_tf_named"> | |
| 553 | - | <description summary="supported named transfer characteristic"> | |
| 554 | - | When this object is created, it shall immediately send this event once | |
| 555 | - | for each named transfer function the compositor supports with the | |
| 556 | - | parametric image description creator. | |
| 557 | - | ||
| 558 | - | A compositor must not advertise transfer functions that are deprecated | |
| 559 | - | in the bound version of the interface. | |
| 560 | - | </description> | |
| 561 | - | ||
| 562 | - | <arg name="tf" type="uint" enum="transfer_function" | |
| 563 | - | summary="Named transfer function"/> | |
| 564 | - | </event> | |
| 565 | - | ||
| 566 | - | <event name="supported_primaries_named"> | |
| 567 | - | <description summary="supported named primaries"> | |
| 568 | - | When this object is created, it shall immediately send this event once | |
| 569 | - | for each named set of primaries the compositor supports with the | |
| 570 | - | parametric image description creator. | |
| 571 | - | ||
| 572 | - | A compositor must not advertise names that are deprecated in the | |
| 573 | - | bound version of the interface. | |
| 574 | - | </description> | |
| 575 | - | ||
| 576 | - | <arg name="primaries" type="uint" enum="primaries" | |
| 577 | - | summary="Named color primaries"/> | |
| 578 | - | </event> | |
| 579 | - | ||
| 580 | - | <event name="done"> | |
| 581 | - | <description summary="all features have been sent"> | |
| 582 | - | This event is sent when all supported rendering intents, features, | |
| 583 | - | transfer functions and named primaries have been sent. | |
| 584 | - | </description> | |
| 585 | - | </event> | |
| 586 | - | ||
| 587 | - | <request name="get_image_description" since="2"> | |
| 588 | - | <description summary="create an image description from a reference"> | |
| 589 | - | This request retrieves the image description backing a reference. | |
| 590 | - | ||
| 591 | - | The get_information request can be used if and only if the request that | |
| 592 | - | creates the reference allows it. | |
| 593 | - | </description> | |
| 594 | - | ||
| 595 | - | <arg name="image_description" | |
| 596 | - | type="new_id" interface="wp_image_description_v1"/> | |
| 597 | - | <arg name="reference" | |
| 598 | - | type="object" interface="wp_image_description_reference_v1"/> | |
| 599 | - | </request> | |
| 600 | - | ||
| 601 | - | <request name="create_windows_bt2100" since="3"> | |
| 602 | - | <description summary="create Windows-BT.2100 image description object"> | |
| 603 | - | This creates a pre-defined image description for the so-called | |
| 604 | - | Windows-BT.2100 stimulus encoding. This comes from the Windows 10 | |
| 605 | - | handling of its own definition of a BT.2100 color space for an HDR | |
| 606 | - | screen driven in BT.2100/PQ signalling mode. | |
| 607 | - | ||
| 608 | - | Windows-BT.2100 uses BT.2020 color primaries and white point. | |
| 609 | - | The transfer characteristic is st2084_pq. | |
| 610 | - | ||
| 611 | - | Windows-BT.2100 is generally displayed by Windows 10 without any | |
| 612 | - | adjustments to the signal to account for viewing conditions. | |
| 613 | - | ||
| 614 | - | The reference white level of Windows-BT.2100 is unknown. If a | |
| 615 | - | reference white level must be assumed for compositor processing, it | |
| 616 | - | should be 203 cd/m² of Report ITU-R BT.2408-7. | |
| 617 | - | ||
| 618 | - | The target color volume of Windows-BT.2100 is unknown. The color gamut | |
| 619 | - | may be anything up to BT.2100. | |
| 620 | - | ||
| 621 | - | This request can be used when the compositor advertises | |
| 622 | - | wp_color_manager_v1.feature.windows_bt2100. | |
| 623 | - | Otherwise this request raises the protocol error unsupported_feature. | |
| 624 | - | ||
| 625 | - | The resulting image description object does not allow get_information | |
| 626 | - | request. The wp_image_description_v1.ready event shall be sent. | |
| 627 | - | </description> | |
| 628 | - | ||
| 629 | - | <arg name="image_description" | |
| 630 | - | type="new_id" interface="wp_image_description_v1"/> | |
| 631 | - | </request> | |
| 632 | - | </interface> | |
| 633 | - | ||
| 634 | - | <interface name="wp_color_management_output_v1" version="3"> | |
| 635 | - | <description summary="output color properties"> | |
| 636 | - | A wp_color_management_output_v1 describes the color properties of an | |
| 637 | - | output. | |
| 638 | - | ||
| 639 | - | The wp_color_management_output_v1 is associated with the wl_output global | |
| 640 | - | underlying the wl_output object. Therefore the client destroying the | |
| 641 | - | wl_output object has no impact, but the compositor removing the output | |
| 642 | - | global makes the wp_color_management_output_v1 object inert. | |
| 643 | - | </description> | |
| 644 | - | ||
| 645 | - | <request name="destroy" type="destructor"> | |
| 646 | - | <description summary="destroy the color management output"> | |
| 647 | - | Destroy the color wp_color_management_output_v1 object. This does not | |
| 648 | - | affect any remaining protocol objects. | |
| 649 | - | </description> | |
| 650 | - | </request> | |
| 651 | - | ||
| 652 | - | <event name="image_description_changed"> | |
| 653 | - | <description summary="image description changed"> | |
| 654 | - | This event is sent whenever the image description of the output changed, | |
| 655 | - | followed by one wl_output.done event common to output events across all | |
| 656 | - | extensions. | |
| 657 | - | ||
| 658 | - | If the client wants to use the updated image description, it needs to do | |
| 659 | - | get_image_description again, because image description objects are | |
| 660 | - | immutable. | |
| 661 | - | </description> | |
| 662 | - | </event> | |
| 663 | - | ||
| 664 | - | <request name="get_image_description"> | |
| 665 | - | <description summary="get the image description of the output"> | |
| 666 | - | This creates a new wp_image_description_v1 object for the current image | |
| 667 | - | description of the output. There always is exactly one image description | |
| 668 | - | active for an output so the client should destroy the image description | |
| 669 | - | created by earlier invocations of this request. This request is usually | |
| 670 | - | sent as a reaction to the image_description_changed event or when | |
| 671 | - | creating a wp_color_management_output_v1 object. | |
| 672 | - | ||
| 673 | - | The image description of an output represents the color encoding the | |
| 674 | - | output expects. There might be performance and power advantages, as well | |
| 675 | - | as improved color reproduction, if a content update matches the image | |
| 676 | - | description of the output it is being shown on. If a content update is | |
| 677 | - | shown on any other output than the one it matches the image description | |
| 678 | - | of, then the color reproduction on those outputs might be considerably | |
| 679 | - | worse. | |
| 680 | - | ||
| 681 | - | The created wp_image_description_v1 object preserves the image | |
| 682 | - | description of the output from the time the object was created. | |
| 683 | - | ||
| 684 | - | The resulting image description object allows get_information request. | |
| 685 | - | ||
| 686 | - | If this protocol object is inert, the resulting image description object | |
| 687 | - | shall immediately deliver the wp_image_description_v1.failed event with | |
| 688 | - | the no_output cause. | |
| 689 | - | ||
| 690 | - | If the interface version is inadequate for the output's image | |
| 691 | - | description, meaning that the client does not support all the events | |
| 692 | - | needed to deliver the crucial information, the resulting image | |
| 693 | - | description object shall immediately deliver the | |
| 694 | - | wp_image_description_v1.failed event with the low_version cause. | |
| 695 | - | ||
| 696 | - | Otherwise the object shall immediately deliver the ready event. | |
| 697 | - | </description> | |
| 698 | - | ||
| 699 | - | <arg name="image_description" | |
| 700 | - | type="new_id" interface="wp_image_description_v1"/> | |
| 701 | - | </request> | |
| 702 | - | </interface> | |
| 703 | - | ||
| 704 | - | <interface name="wp_color_management_surface_v1" version="3"> | |
| 705 | - | <description summary="color management extension to a surface"> | |
| 706 | - | A wp_color_management_surface_v1 allows the client to set the color | |
| 707 | - | space and HDR properties of a surface. | |
| 708 | - | ||
| 709 | - | If the wl_surface associated with the wp_color_management_surface_v1 is | |
| 710 | - | destroyed, the wp_color_management_surface_v1 object becomes inert. | |
| 711 | - | </description> | |
| 712 | - | ||
| 713 | - | <request name="destroy" type="destructor"> | |
| 714 | - | <description summary="destroy the color management interface for a surface"> | |
| 715 | - | Destroy the wp_color_management_surface_v1 object and do the same as | |
| 716 | - | unset_image_description. | |
| 717 | - | </description> | |
| 718 | - | </request> | |
| 719 | - | ||
| 720 | - | <enum name="error"> | |
| 721 | - | <description summary="protocol errors"/> | |
| 722 | - | <entry name="render_intent" value="0" | |
| 723 | - | summary="unsupported rendering intent"/> | |
| 724 | - | <entry name="image_description" value="1" | |
| 725 | - | summary="invalid image description"/> | |
| 726 | - | <entry name="inert" value="2" | |
| 727 | - | summary="forbidden request on inert object"/> | |
| 728 | - | </enum> | |
| 729 | - | ||
| 730 | - | <request name="set_image_description"> | |
| 731 | - | <description summary="set the surface image description"> | |
| 732 | - | If this protocol object is inert, the protocol error inert is raised. | |
| 733 | - | ||
| 734 | - | Set the image description of the underlying surface. The image | |
| 735 | - | description and rendering intent are double-buffered state, see | |
| 736 | - | wl_surface.commit. | |
| 737 | - | ||
| 738 | - | It is the client's responsibility to understand the image description | |
| 739 | - | it sets on a surface, and to provide content that matches that image | |
| 740 | - | description. Compositors might convert images to match their own or any | |
| 741 | - | other image descriptions. | |
| 742 | - | ||
| 743 | - | Image descriptions which are not ready (see wp_image_description_v1) | |
| 744 | - | are forbidden in this request, and in such case the protocol error | |
| 745 | - | image_description is raised. | |
| 746 | - | ||
| 747 | - | All image descriptions which are ready (see wp_image_description_v1) | |
| 748 | - | are allowed and must always be accepted by the compositor. | |
| 749 | - | ||
| 750 | - | When an image description is set on a surface, it establishes an | |
| 751 | - | explicit link between surface pixel values and surface colorimetry. | |
| 752 | - | This link may be undefined for some pixel values, see the image | |
| 753 | - | description creator interfaces for the conditions. Non-finite | |
| 754 | - | floating-point values (NaN, Inf) always have an undefined colorimetry. | |
| 755 | - | ||
| 756 | - | A rendering intent provides the client's preference on how surface | |
| 757 | - | colorimetry should be mapped to each output. The render_intent value | |
| 758 | - | must be one advertised by the compositor with | |
| 759 | - | wp_color_manager_v1.render_intent event, otherwise the protocol error | |
| 760 | - | render_intent is raised. | |
| 761 | - | ||
| 762 | - | By default, a surface does not have an associated image description | |
| 763 | - | nor a rendering intent. The handling of color on such surfaces is | |
| 764 | - | compositor implementation defined. Compositors should handle such | |
| 765 | - | surfaces as sRGB, but may handle them differently if they have specific | |
| 766 | - | requirements. | |
| 767 | - | ||
| 768 | - | Setting the image description has copy semantics; after this request, | |
| 769 | - | the image description can be immediately destroyed without affecting | |
| 770 | - | the pending state of the surface. | |
| 771 | - | </description> | |
| 772 | - | ||
| 773 | - | <arg name="image_description" | |
| 774 | - | type="object" interface="wp_image_description_v1"/> | |
| 775 | - | <arg name="render_intent" | |
| 776 | - | type="uint" enum="wp_color_manager_v1.render_intent" | |
| 777 | - | summary="rendering intent"/> | |
| 778 | - | </request> | |
| 779 | - | ||
| 780 | - | <request name="unset_image_description"> | |
| 781 | - | <description summary="remove the surface image description"> | |
| 782 | - | If this protocol object is inert, the protocol error inert is raised. | |
| 783 | - | ||
| 784 | - | This request removes any image description from the surface. See | |
| 785 | - | set_image_description for how a compositor handles a surface without | |
| 786 | - | an image description. This is double-buffered state, see | |
| 787 | - | wl_surface.commit. | |
| 788 | - | </description> | |
| 789 | - | </request> | |
| 790 | - | </interface> | |
| 791 | - | ||
| 792 | - | <interface name="wp_color_management_surface_feedback_v1" version="3"> | |
| 793 | - | <description summary="color management extension to a surface"> | |
| 794 | - | A wp_color_management_surface_feedback_v1 allows the client to get the | |
| 795 | - | preferred image description of a surface. | |
| 796 | - | ||
| 797 | - | If the wl_surface associated with this object is destroyed, the | |
| 798 | - | wp_color_management_surface_feedback_v1 object becomes inert. | |
| 799 | - | </description> | |
| 800 | - | ||
| 801 | - | <request name="destroy" type="destructor"> | |
| 802 | - | <description summary="destroy the color management interface for a surface"> | |
| 803 | - | Destroy the wp_color_management_surface_feedback_v1 object. | |
| 804 | - | </description> | |
| 805 | - | </request> | |
| 806 | - | ||
| 807 | - | <enum name="error"> | |
| 808 | - | <description summary="protocol errors"/> | |
| 809 | - | <entry name="inert" value="0" | |
| 810 | - | summary="forbidden request on inert object"/> | |
| 811 | - | <entry name="unsupported_feature" value="1" | |
| 812 | - | summary="attempted to use an unsupported feature"/> | |
| 813 | - | </enum> | |
| 814 | - | ||
| 815 | - | <event name="preferred_changed" deprecated-since="2"> | |
| 816 | - | <description summary="the preferred image description changed (32-bit)"> | |
| 817 | - | Starting from interface version 2, 'preferred_changed2' is sent instead | |
| 818 | - | of this event. See the 'preferred_changed2' event for the definition. | |
| 819 | - | </description> | |
| 820 | - | ||
| 821 | - | <arg name="identity" type="uint" | |
| 822 | - | summary="the 32-bit image description id number"/> | |
| 823 | - | </event> | |
| 824 | - | ||
| 825 | - | <request name="get_preferred"> | |
| 826 | - | <description summary="get the preferred image description"> | |
| 827 | - | If this protocol object is inert, the protocol error inert is raised. | |
| 828 | - | ||
| 829 | - | The preferred image description represents the compositor's preferred | |
| 830 | - | color encoding for this wl_surface at the current time. There might be | |
| 831 | - | performance and power advantages, as well as improved color | |
| 832 | - | reproduction, if the image description of a content update matches the | |
| 833 | - | preferred image description. | |
| 834 | - | ||
| 835 | - | This creates a new wp_image_description_v1 object for the currently | |
| 836 | - | preferred image description for the wl_surface. The client should | |
| 837 | - | stop using and destroy the image descriptions created by earlier | |
| 838 | - | invocations of this request for the associated wl_surface. | |
| 839 | - | This request is usually sent as a reaction to the preferred_changed | |
| 840 | - | event or when creating a wp_color_management_surface_feedback_v1 object | |
| 841 | - | if the client is capable of adapting to image descriptions. | |
| 842 | - | ||
| 843 | - | The created wp_image_description_v1 object preserves the preferred image | |
| 844 | - | description of the wl_surface from the time the object was created. | |
| 845 | - | ||
| 846 | - | The resulting image description object allows get_information request. | |
| 847 | - | ||
| 848 | - | If the image description is parametric, the client should set it on its | |
| 849 | - | wl_surface only if the image description is an exact match with the | |
| 850 | - | client content. Particularly if everything else matches, but the target | |
| 851 | - | color volume is greater than what the client needs, the client should | |
| 852 | - | create its own parameric image description with its exact parameters. | |
| 853 | - | ||
| 854 | - | If the interface version is inadequate for the preferred image | |
| 855 | - | description, meaning that the client does not support all the | |
| 856 | - | events needed to deliver the crucial information, the resulting image | |
| 857 | - | description object shall immediately deliver the | |
| 858 | - | wp_image_description_v1.failed event with the low_version cause, | |
| 859 | - | otherwise the object shall immediately deliver the ready event. | |
| 860 | - | </description> | |
| 861 | - | ||
| 862 | - | <arg name="image_description" | |
| 863 | - | type="new_id" interface="wp_image_description_v1"/> | |
| 864 | - | </request> | |
| 865 | - | ||
| 866 | - | <request name="get_preferred_parametric"> | |
| 867 | - | <description summary="get the preferred image description"> | |
| 868 | - | The same description as for get_preferred applies, except the returned | |
| 869 | - | image description is guaranteed to be parametric. This is meant for | |
| 870 | - | clients that can only deal with parametric image descriptions. | |
| 871 | - | ||
| 872 | - | If the compositor doesn't support parametric image descriptions, the | |
| 873 | - | unsupported_feature error is emitted. | |
| 874 | - | </description> | |
| 875 | - | ||
| 876 | - | <arg name="image_description" | |
| 877 | - | type="new_id" interface="wp_image_description_v1"/> | |
| 878 | - | </request> | |
| 879 | - | ||
| 880 | - | <!-- Version 2 additions --> | |
| 881 | - | ||
| 882 | - | <event name="preferred_changed2" since="2"> | |
| 883 | - | <description summary="the preferred image description changed"> | |
| 884 | - | The preferred image description is the one which likely has the most | |
| 885 | - | performance and/or quality benefits for the compositor if used by the | |
| 886 | - | client for its wl_surface contents. This event is sent whenever the | |
| 887 | - | compositor changes the wl_surface's preferred image description. | |
| 888 | - | ||
| 889 | - | This event sends the identity of the new preferred state as the argument, | |
| 890 | - | so clients who are aware of the image description already can reuse it. | |
| 891 | - | Otherwise, if the client client wants to know what the preferred image | |
| 892 | - | description is, it shall use the get_preferred request. | |
| 893 | - | ||
| 894 | - | The preferred image description is not automatically used for anything. | |
| 895 | - | It is only a hint, and clients may set any valid image description with | |
| 896 | - | set_image_description, but there might be performance and color accuracy | |
| 897 | - | improvements by providing the wl_surface contents in the preferred | |
| 898 | - | image description. Therefore clients that can, should render according | |
| 899 | - | to the preferred image description | |
| 900 | - | </description> | |
| 901 | - | ||
| 902 | - | <arg name="identity_hi" type="uint" | |
| 903 | - | summary="high 32 bits of the 64-bit image description id number"/> | |
| 904 | - | <arg name="identity_lo" type="uint" | |
| 905 | - | summary="low 32 bits of the 64-bit image description id number"/> | |
| 906 | - | </event> | |
| 907 | - | ||
| 908 | - | </interface> | |
| 909 | - | ||
| 910 | - | <interface name="wp_image_description_creator_icc_v1" version="3"> | |
| 911 | - | <description summary="holder of image description ICC information"> | |
| 912 | - | This type of object is used for collecting all the information required | |
| 913 | - | to create a wp_image_description_v1 object from an ICC file. A complete | |
| 914 | - | set of required parameters consists of these properties: | |
| 915 | - | - ICC file | |
| 916 | - | ||
| 917 | - | Each required property must be set exactly once if the client is to create | |
| 918 | - | an image description. The set requests verify that a property was not | |
| 919 | - | already set. The create request verifies that all required properties are | |
| 920 | - | set. There may be several alternative requests for setting each property, | |
| 921 | - | and in that case the client must choose one of them. | |
| 922 | - | ||
| 923 | - | Once all properties have been set, the create request must be used to | |
| 924 | - | create the image description object, destroying the creator in the | |
| 925 | - | process. | |
| 926 | - | ||
| 927 | - | The link between a pixel value (a device value in ICC) and its respective | |
| 928 | - | colorimetry is defined by the details of the particular ICC profile. | |
| 929 | - | Those details also determine when colorimetry becomes undefined. | |
| 930 | - | </description> | |
| 931 | - | ||
| 932 | - | <enum name="error"> | |
| 933 | - | <description summary="protocol errors"/> | |
| 934 | - | ||
| 935 | - | <entry name="incomplete_set" value="0" | |
| 936 | - | summary="incomplete parameter set"/> | |
| 937 | - | <entry name="already_set" value="1" | |
| 938 | - | summary="property already set"/> | |
| 939 | - | <entry name="bad_fd" value="2" | |
| 940 | - | summary="fd not seekable and readable"/> | |
| 941 | - | <entry name="bad_size" value="3" | |
| 942 | - | summary="no or too much data"/> | |
| 943 | - | <entry name="out_of_file" value="4" | |
| 944 | - | summary="offset + length exceeds file size"/> | |
| 945 | - | </enum> | |
| 946 | - | ||
| 947 | - | <request name="create" type="destructor"> | |
| 948 | - | <description summary="Create the image description object from ICC data"> | |
| 949 | - | Create an image description object based on the ICC information | |
| 950 | - | previously set on this object. A compositor must parse the ICC data in | |
| 951 | - | some undefined but finite amount of time. | |
| 952 | - | ||
| 953 | - | The completeness of the parameter set is verified. If the set is not | |
| 954 | - | complete, the protocol error incomplete_set is raised. For the | |
| 955 | - | definition of a complete set, see the description of this interface. | |
| 956 | - | ||
| 957 | - | If the particular combination of the information is not supported | |
| 958 | - | by the compositor, the resulting image description object shall | |
| 959 | - | immediately deliver the wp_image_description_v1.failed event with the | |
| 960 | - | 'unsupported' cause. If a valid image description was created from the | |
| 961 | - | information, the wp_image_description_v1.ready event will eventually | |
| 962 | - | be sent instead. | |
| 963 | - | ||
| 964 | - | This request destroys the wp_image_description_creator_icc_v1 object. | |
| 965 | - | ||
| 966 | - | The resulting image description object does not allow get_information | |
| 967 | - | request. | |
| 968 | - | </description> | |
| 969 | - | ||
| 970 | - | <arg name="image_description" | |
| 971 | - | type="new_id" interface="wp_image_description_v1"/> | |
| 972 | - | </request> | |
| 973 | - | ||
| 974 | - | <request name="set_icc_file"> | |
| 975 | - | <description summary="set the ICC profile file"> | |
| 976 | - | Sets the ICC profile file to be used as the basis of the image | |
| 977 | - | description. | |
| 978 | - | ||
| 979 | - | The data shall be found through the given fd at the given offset, having | |
| 980 | - | the given length. The fd must be seekable and readable. Violating these | |
| 981 | - | requirements raises the bad_fd protocol error. | |
| 982 | - | ||
| 983 | - | If reading the data fails due to an error independent of the client, the | |
| 984 | - | compositor shall send the wp_image_description_v1.failed event on the | |
| 985 | - | created wp_image_description_v1 with the 'operating_system' cause. | |
| 986 | - | ||
| 987 | - | The maximum size of the ICC profile is 32 MB. If length is greater than | |
| 988 | - | that or zero, the protocol error bad_size is raised. If offset + length | |
| 989 | - | exceeds the file size, the protocol error out_of_file is raised. | |
| 990 | - | ||
| 991 | - | A compositor may read the file at any time starting from this request | |
| 992 | - | and only until whichever happens first: | |
| 993 | - | - If create request was issued, the wp_image_description_v1 object | |
| 994 | - | delivers either failed or ready event; or | |
| 995 | - | - if create request was not issued, this | |
| 996 | - | wp_image_description_creator_icc_v1 object is destroyed. | |
| 997 | - | ||
| 998 | - | A compositor shall not modify the contents of the file, and the fd may | |
| 999 | - | be sealed for writes and size changes. The client must ensure to its | |
| 1000 | - | best ability that the data does not change while the compositor is | |
| 1001 | - | reading it. | |
| 1002 | - | ||
| 1003 | - | The data must represent a valid ICC profile. The ICC profile version | |
| 1004 | - | must be 2 or 4, it must be a 3 channel profile and the class must be | |
| 1005 | - | Display or ColorSpace. Violating these requirements will not result in a | |
| 1006 | - | protocol error, but will eventually send the | |
| 1007 | - | wp_image_description_v1.failed event on the created | |
| 1008 | - | wp_image_description_v1 with the 'unsupported' cause. | |
| 1009 | - | ||
| 1010 | - | See the International Color Consortium specification ICC.1:2022 for more | |
| 1011 | - | details about ICC profiles. | |
| 1012 | - | ||
| 1013 | - | If ICC file has already been set on this object, the protocol error | |
| 1014 | - | already_set is raised. | |
| 1015 | - | </description> | |
| 1016 | - | ||
| 1017 | - | <arg name="icc_profile" type="fd" | |
| 1018 | - | summary="ICC profile"/> | |
| 1019 | - | <arg name="offset" type="uint" | |
| 1020 | - | summary="byte offset in fd to start of ICC data"/> | |
| 1021 | - | <arg name="length" type="uint" | |
| 1022 | - | summary="length of ICC data in bytes"/> | |
| 1023 | - | </request> | |
| 1024 | - | </interface> | |
| 1025 | - | ||
| 1026 | - | <interface name="wp_image_description_creator_params_v1" version="3"> | |
| 1027 | - | <description summary="holder of image description parameters"> | |
| 1028 | - | This type of object is used for collecting all the parameters required | |
| 1029 | - | to create a wp_image_description_v1 object. A complete set of required | |
| 1030 | - | parameters consists of these properties: | |
| 1031 | - | - transfer characteristic function (tf) | |
| 1032 | - | - chromaticities of primaries and white point (primary color volume) | |
| 1033 | - | ||
| 1034 | - | The following properties are optional and have a well-defined default | |
| 1035 | - | if not explicitly set: | |
| 1036 | - | - primary color volume luminance range | |
| 1037 | - | - reference white luminance level | |
| 1038 | - | - mastering display primaries and white point (target color volume) | |
| 1039 | - | - mastering luminance range | |
| 1040 | - | ||
| 1041 | - | The following properties are optional and will be ignored | |
| 1042 | - | if not explicitly set: | |
| 1043 | - | - maximum content light level | |
| 1044 | - | - maximum frame-average light level | |
| 1045 | - | ||
| 1046 | - | Each required property must be set exactly once if the client is to create | |
| 1047 | - | an image description. The set requests verify that a property was not | |
| 1048 | - | already set. The create request verifies that all required properties are | |
| 1049 | - | set. There may be several alternative requests for setting each property, | |
| 1050 | - | and in that case the client must choose one of them. | |
| 1051 | - | ||
| 1052 | - | Once all properties have been set, the create request must be used to | |
| 1053 | - | create the image description object, destroying the creator in the | |
| 1054 | - | process. | |
| 1055 | - | ||
| 1056 | - | A viewer, who is viewing the display defined by the resulting image | |
| 1057 | - | description (the viewing environment included), is assumed to be fully | |
| 1058 | - | adapted to the primary color volume's white point. | |
| 1059 | - | ||
| 1060 | - | Any of the following conditions will cause the colorimetry of a pixel | |
| 1061 | - | to become undefined: | |
| 1062 | - | - Values outside of the defined range of the transfer characteristic. | |
| 1063 | - | - Tristimulus that exceeds the target color volume. | |
| 1064 | - | - If extended_target_volume is not supported: tristimulus that exceeds | |
| 1065 | - | the primary color volume. | |
| 1066 | - | ||
| 1067 | - | The closest correspondence to an image description created through this | |
| 1068 | - | interface is the Display class of profiles in ICC. | |
| 1069 | - | </description> | |
| 1070 | - | ||
| 1071 | - | <enum name="error"> | |
| 1072 | - | <description summary="protocol errors"/> | |
| 1073 | - | ||
| 1074 | - | <entry name="incomplete_set" value="0" | |
| 1075 | - | summary="incomplete parameter set"/> | |
| 1076 | - | <entry name="already_set" value="1" | |
| 1077 | - | summary="property already set"/> | |
| 1078 | - | <entry name="unsupported_feature" value="2" | |
| 1079 | - | summary="request not supported"/> | |
| 1080 | - | <entry name="invalid_tf" value="3" | |
| 1081 | - | summary="invalid transfer characteristic"/> | |
| 1082 | - | <entry name="invalid_primaries_named" value="4" | |
| 1083 | - | summary="invalid primaries named"/> | |
| 1084 | - | <entry name="invalid_luminance" value="5" | |
| 1085 | - | summary="invalid luminance value or range"/> | |
| 1086 | - | </enum> | |
| 1087 | - | ||
| 1088 | - | <request name="create" type="destructor"> | |
| 1089 | - | <description summary="Create the image description object using params"> | |
| 1090 | - | Create an image description object based on the parameters previously | |
| 1091 | - | set on this object. | |
| 1092 | - | ||
| 1093 | - | The completeness of the parameter set is verified. If the set is not | |
| 1094 | - | complete, the protocol error incomplete_set is raised. For the | |
| 1095 | - | definition of a complete set, see the description of this interface. | |
| 1096 | - | ||
| 1097 | - | When both max_cll and max_fall are set, max_fall must be less or equal | |
| 1098 | - | to max_cll otherwise the invalid_luminance protocol error is raised. | |
| 1099 | - | ||
| 1100 | - | In version 1, these following conditions also result in the | |
| 1101 | - | invalid_luminance protocol error. Version 2 and later do not have this | |
| 1102 | - | requirement. | |
| 1103 | - | - When max_cll is set, it must be greater than min L and less or equal | |
| 1104 | - | to max L of the mastering luminance range. | |
| 1105 | - | - When max_fall is set, it must be greater than min L and less or equal | |
| 1106 | - | to max L of the mastering luminance range. | |
| 1107 | - | ||
| 1108 | - | If the particular combination of the parameter set is not supported | |
| 1109 | - | by the compositor, the resulting image description object shall | |
| 1110 | - | immediately deliver the wp_image_description_v1.failed event with the | |
| 1111 | - | 'unsupported' cause. If a valid image description was created from the | |
| 1112 | - | parameter set, the wp_image_description_v1.ready event will eventually | |
| 1113 | - | be sent instead. | |
| 1114 | - | ||
| 1115 | - | This request destroys the wp_image_description_creator_params_v1 | |
| 1116 | - | object. | |
| 1117 | - | ||
| 1118 | - | The resulting image description object does not allow get_information | |
| 1119 | - | request. | |
| 1120 | - | </description> | |
| 1121 | - | ||
| 1122 | - | <arg name="image_description" | |
| 1123 | - | type="new_id" interface="wp_image_description_v1"/> | |
| 1124 | - | </request> | |
| 1125 | - | ||
| 1126 | - | <request name="set_tf_named"> | |
| 1127 | - | <description summary="named transfer characteristic"> | |
| 1128 | - | Sets the transfer characteristic using explicitly enumerated named | |
| 1129 | - | functions. | |
| 1130 | - | ||
| 1131 | - | When the resulting image description is attached to an image, the | |
| 1132 | - | content should be decoded according to the industry standard | |
| 1133 | - | practices for the transfer characteristic. | |
| 1134 | - | ||
| 1135 | - | Only names advertised with wp_color_manager_v1 event supported_tf_named | |
| 1136 | - | are allowed. Other values shall raise the protocol error invalid_tf. | |
| 1137 | - | ||
| 1138 | - | If transfer characteristic has already been set on this object, the | |
| 1139 | - | protocol error already_set is raised. | |
| 1140 | - | </description> | |
| 1141 | - | ||
| 1142 | - | <arg name="tf" type="uint" enum="wp_color_manager_v1.transfer_function" | |
| 1143 | - | summary="named transfer function"/> | |
| 1144 | - | </request> | |
| 1145 | - | ||
| 1146 | - | <request name="set_tf_power"> | |
| 1147 | - | <description summary="transfer characteristic as a power curve"> | |
| 1148 | - | Sets the color component transfer characteristic to a power curve with | |
| 1149 | - | the given exponent. Negative values are handled by mirroring the | |
| 1150 | - | positive half of the curve through the origin. The valid domain and | |
| 1151 | - | range of the curve are all finite real numbers. This curve represents | |
| 1152 | - | the conversion from electrical to optical color channel values. | |
| 1153 | - | ||
| 1154 | - | The curve exponent shall be multiplied by 10000 to get the argument eexp | |
| 1155 | - | value to carry the precision of 4 decimals. | |
| 1156 | - | ||
| 1157 | - | The curve exponent must be at least 1.0 and at most 10.0. Otherwise the | |
| 1158 | - | protocol error invalid_tf is raised. | |
| 1159 | - | ||
| 1160 | - | If transfer characteristic has already been set on this object, the | |
| 1161 | - | protocol error already_set is raised. | |
| 1162 | - | ||
| 1163 | - | This request can be used when the compositor advertises | |
| 1164 | - | wp_color_manager_v1.feature.set_tf_power. Otherwise this request raises | |
| 1165 | - | the protocol error unsupported_feature. | |
| 1166 | - | </description> | |
| 1167 | - | ||
| 1168 | - | <arg name="eexp" type="uint" summary="the exponent * 10000"/> | |
| 1169 | - | </request> | |
| 1170 | - | ||
| 1171 | - | <request name="set_primaries_named"> | |
| 1172 | - | <description summary="named primaries"> | |
| 1173 | - | Sets the color primaries and white point using explicitly named sets. | |
| 1174 | - | This describes the primary color volume which is the basis for color | |
| 1175 | - | value encoding. | |
| 1176 | - | ||
| 1177 | - | Only names advertised with wp_color_manager_v1 event | |
| 1178 | - | supported_primaries_named are allowed. Other values shall raise the | |
| 1179 | - | protocol error invalid_primaries_named. | |
| 1180 | - | ||
| 1181 | - | If primaries have already been set on this object, the protocol error | |
| 1182 | - | already_set is raised. | |
| 1183 | - | </description> | |
| 1184 | - | ||
| 1185 | - | <arg name="primaries" type="uint" enum="wp_color_manager_v1.primaries" | |
| 1186 | - | summary="named primaries"/> | |
| 1187 | - | </request> | |
| 1188 | - | ||
| 1189 | - | <request name="set_primaries"> | |
| 1190 | - | <description summary="primaries as chromaticity coordinates"> | |
| 1191 | - | Sets the color primaries and white point using CIE 1931 xy chromaticity | |
| 1192 | - | coordinates. This describes the primary color volume which is the basis | |
| 1193 | - | for color value encoding. | |
| 1194 | - | ||
| 1195 | - | Each coordinate value is multiplied by 1 million to get the argument | |
| 1196 | - | value to carry precision of 6 decimals. | |
| 1197 | - | ||
| 1198 | - | If primaries have already been set on this object, the protocol error | |
| 1199 | - | already_set is raised. | |
| 1200 | - | ||
| 1201 | - | This request can be used if the compositor advertises | |
| 1202 | - | wp_color_manager_v1.feature.set_primaries. Otherwise this request raises | |
| 1203 | - | the protocol error unsupported_feature. | |
| 1204 | - | </description> | |
| 1205 | - | ||
| 1206 | - | <arg name="r_x" type="int" summary="Red x * 1M"/> | |
| 1207 | - | <arg name="r_y" type="int" summary="Red y * 1M"/> | |
| 1208 | - | <arg name="g_x" type="int" summary="Green x * 1M"/> | |
| 1209 | - | <arg name="g_y" type="int" summary="Green y * 1M"/> | |
| 1210 | - | <arg name="b_x" type="int" summary="Blue x * 1M"/> | |
| 1211 | - | <arg name="b_y" type="int" summary="Blue y * 1M"/> | |
| 1212 | - | <arg name="w_x" type="int" summary="White x * 1M"/> | |
| 1213 | - | <arg name="w_y" type="int" summary="White y * 1M"/> | |
| 1214 | - | </request> | |
| 1215 | - | ||
| 1216 | - | <request name="set_luminances"> | |
| 1217 | - | <description summary="primary color volume luminance range and reference white"> | |
| 1218 | - | Sets the primary color volume luminance range and the reference white | |
| 1219 | - | luminance level. These values include the minimum display emission, but | |
| 1220 | - | not external flare. The minimum display emission is assumed to have | |
| 1221 | - | the chromaticity of the primary color volume white point. | |
| 1222 | - | ||
| 1223 | - | The default luminances from | |
| 1224 | - | https://www.color.org/chardata/rgb/srgb.xalter are | |
| 1225 | - | - primary color volume minimum: 0.2 cd/m² | |
| 1226 | - | - primary color volume maximum: 80 cd/m² | |
| 1227 | - | - reference white: 80 cd/m² | |
| 1228 | - | ||
| 1229 | - | Setting a named transfer characteristic can imply other default | |
| 1230 | - | luminances. | |
| 1231 | - | ||
| 1232 | - | The default luminances get overwritten when this request is used. | |
| 1233 | - | With transfer_function.st2084_pq the given 'max_lum' value is ignored, | |
| 1234 | - | and 'max_lum' is taken as 'min_lum' + 10000 cd/m². | |
| 1235 | - | ||
| 1236 | - | 'min_lum' and 'max_lum' specify the minimum and maximum luminances of | |
| 1237 | - | the primary color volume as reproduced by the targeted display. | |
| 1238 | - | ||
| 1239 | - | 'reference_lum' specifies the luminance of the reference white as | |
| 1240 | - | reproduced by the targeted display, and reflects the targeted viewing | |
| 1241 | - | environment. | |
| 1242 | - | ||
| 1243 | - | Compositors should make sure that all content is anchored, meaning that | |
| 1244 | - | an input signal level of 'reference_lum' on one image description and | |
| 1245 | - | another input signal level of 'reference_lum' on another image | |
| 1246 | - | description should produce the same output level, even though the | |
| 1247 | - | 'reference_lum' on both image representations can be different. | |
| 1248 | - | ||
| 1249 | - | 'reference_lum' may be higher than 'max_lum'. In that case reaching | |
| 1250 | - | the reference white output level in image content requires the | |
| 1251 | - | 'extended_target_volume' feature support. | |
| 1252 | - | ||
| 1253 | - | If 'max_lum' or 'reference_lum' are less than or equal to 'min_lum', | |
| 1254 | - | the protocol error invalid_luminance is raised. | |
| 1255 | - | ||
| 1256 | - | The minimum luminance is multiplied by 10000 to get the argument | |
| 1257 | - | 'min_lum' value and carries precision of 4 decimals. The maximum | |
| 1258 | - | luminance and reference white luminance values are unscaled. | |
| 1259 | - | ||
| 1260 | - | If the primary color volume luminance range and the reference white | |
| 1261 | - | luminance level have already been set on this object, the protocol error | |
| 1262 | - | already_set is raised. | |
| 1263 | - | ||
| 1264 | - | This request can be used if the compositor advertises | |
| 1265 | - | wp_color_manager_v1.feature.set_luminances. Otherwise this request | |
| 1266 | - | raises the protocol error unsupported_feature. | |
| 1267 | - | </description> | |
| 1268 | - | ||
| 1269 | - | <arg name="min_lum" type="uint" | |
| 1270 | - | summary="minimum luminance (cd/m²) * 10000"/> | |
| 1271 | - | <arg name="max_lum" type="uint" | |
| 1272 | - | summary="maximum luminance (cd/m²)"/> | |
| 1273 | - | <arg name="reference_lum" type="uint" | |
| 1274 | - | summary="reference white luminance (cd/m²)"/> | |
| 1275 | - | </request> | |
| 1276 | - | ||
| 1277 | - | <request name="set_mastering_display_primaries"> | |
| 1278 | - | <description summary="mastering display primaries as chromaticity coordinates"> | |
| 1279 | - | Provides the color primaries and white point of the mastering display | |
| 1280 | - | using CIE 1931 xy chromaticity coordinates. This is compatible with the | |
| 1281 | - | SMPTE ST 2086 definition of HDR static metadata. | |
| 1282 | - | ||
| 1283 | - | The mastering display primaries and mastering display luminances define | |
| 1284 | - | the target color volume. | |
| 1285 | - | ||
| 1286 | - | If mastering display primaries are not explicitly set, the target color | |
| 1287 | - | volume is assumed to have the same primaries as the primary color volume. | |
| 1288 | - | ||
| 1289 | - | The target color volume is defined by all tristimulus values between 0.0 | |
| 1290 | - | and 1.0 (inclusive) of the color space defined by the given mastering | |
| 1291 | - | display primaries and white point. The colorimetry is identical between | |
| 1292 | - | the container color space and the mastering display color space, | |
| 1293 | - | including that no chromatic adaptation is applied even if the white | |
| 1294 | - | points differ. | |
| 1295 | - | ||
| 1296 | - | The target color volume can exceed the primary color volume to allow for | |
| 1297 | - | a greater color volume with an existing color space definition (for | |
| 1298 | - | example scRGB). It can be smaller than the primary color volume to | |
| 1299 | - | minimize gamut and tone mapping distances for big color spaces (HDR | |
| 1300 | - | metadata). | |
| 1301 | - | ||
| 1302 | - | To make use of the entire target color volume a suitable pixel format | |
| 1303 | - | has to be chosen (e.g. floating point to exceed the primary color | |
| 1304 | - | volume, or abusing limited quantization range as with xvYCC). | |
| 1305 | - | ||
| 1306 | - | Each coordinate value is multiplied by 1 million to get the argument | |
| 1307 | - | value to carry precision of 6 decimals. | |
| 1308 | - | ||
| 1309 | - | If mastering display primaries have already been set on this object, the | |
| 1310 | - | protocol error already_set is raised. | |
| 1311 | - | ||
| 1312 | - | This request can be used if the compositor advertises | |
| 1313 | - | wp_color_manager_v1.feature.set_mastering_display_primaries. Otherwise | |
| 1314 | - | this request raises the protocol error unsupported_feature. The | |
| 1315 | - | advertisement implies support only for target color volumes fully | |
| 1316 | - | contained within the primary color volume. | |
| 1317 | - | ||
| 1318 | - | If a compositor additionally supports target color volume exceeding the | |
| 1319 | - | primary color volume, it must advertise | |
| 1320 | - | wp_color_manager_v1.feature.extended_target_volume. If a client uses | |
| 1321 | - | target color volume exceeding the primary color volume and the | |
| 1322 | - | compositor does not support it, the result is implementation defined. | |
| 1323 | - | Compositors are recommended to detect this case and fail the image | |
| 1324 | - | description gracefully, but it may as well result in color artifacts. | |
| 1325 | - | </description> | |
| 1326 | - | ||
| 1327 | - | <arg name="r_x" type="int" summary="Red x * 1M"/> | |
| 1328 | - | <arg name="r_y" type="int" summary="Red y * 1M"/> | |
| 1329 | - | <arg name="g_x" type="int" summary="Green x * 1M"/> | |
| 1330 | - | <arg name="g_y" type="int" summary="Green y * 1M"/> | |
| 1331 | - | <arg name="b_x" type="int" summary="Blue x * 1M"/> | |
| 1332 | - | <arg name="b_y" type="int" summary="Blue y * 1M"/> | |
| 1333 | - | <arg name="w_x" type="int" summary="White x * 1M"/> | |
| 1334 | - | <arg name="w_y" type="int" summary="White y * 1M"/> | |
| 1335 | - | </request> | |
| 1336 | - | ||
| 1337 | - | <request name="set_mastering_luminance"> | |
| 1338 | - | <description summary="display mastering luminance range"> | |
| 1339 | - | Sets the luminance range that was used during the content mastering | |
| 1340 | - | process as the minimum and maximum absolute luminance L. These values | |
| 1341 | - | include the minimum display emission and ambient flare luminances, | |
| 1342 | - | assumed to be optically additive and have the chromaticity of the | |
| 1343 | - | primary color volume white point. This should be | |
| 1344 | - | compatible with the SMPTE ST 2086 definition of HDR static metadata. | |
| 1345 | - | ||
| 1346 | - | The mastering display primaries and mastering display luminances define | |
| 1347 | - | the target color volume. | |
| 1348 | - | ||
| 1349 | - | If mastering luminances are not explicitly set, the target color volume | |
| 1350 | - | is assumed to have the same min and max luminances as the primary color | |
| 1351 | - | volume. | |
| 1352 | - | ||
| 1353 | - | If max L is less than or equal to min L, the protocol error | |
| 1354 | - | invalid_luminance is raised. | |
| 1355 | - | ||
| 1356 | - | Min L value is multiplied by 10000 to get the argument min_lum value | |
| 1357 | - | and carry precision of 4 decimals. Max L value is unscaled for max_lum. | |
| 1358 | - | ||
| 1359 | - | This request can be used if the compositor advertises | |
| 1360 | - | wp_color_manager_v1.feature.set_mastering_display_primaries. Otherwise | |
| 1361 | - | this request raises the protocol error unsupported_feature. The | |
| 1362 | - | advertisement implies support only for target color volumes fully | |
| 1363 | - | contained within the primary color volume. | |
| 1364 | - | ||
| 1365 | - | If a compositor additionally supports target color volume exceeding the | |
| 1366 | - | primary color volume, it must advertise | |
| 1367 | - | wp_color_manager_v1.feature.extended_target_volume. If a client uses | |
| 1368 | - | target color volume exceeding the primary color volume and the | |
| 1369 | - | compositor does not support it, the result is implementation defined. | |
| 1370 | - | Compositors are recommended to detect this case and fail the image | |
| 1371 | - | description gracefully, but it may as well result in color artifacts. | |
| 1372 | - | </description> | |
| 1373 | - | ||
| 1374 | - | <arg name="min_lum" type="uint" summary="min L (cd/m²) * 10000"/> | |
| 1375 | - | <arg name="max_lum" type="uint" summary="max L (cd/m²)"/> | |
| 1376 | - | </request> | |
| 1377 | - | ||
| 1378 | - | <request name="set_max_cll"> | |
| 1379 | - | <description summary="maximum content light level"> | |
| 1380 | - | Sets the maximum content light level (max_cll) as defined by CTA-861-H. | |
| 1381 | - | ||
| 1382 | - | max_cll is undefined by default. | |
| 1383 | - | </description> | |
| 1384 | - | ||
| 1385 | - | <arg name="max_cll" type="uint" summary="Maximum content light level (cd/m²)"/> | |
| 1386 | - | </request> | |
| 1387 | - | ||
| 1388 | - | <request name="set_max_fall"> | |
| 1389 | - | <description summary="maximum frame-average light level"> | |
| 1390 | - | Sets the maximum frame-average light level (max_fall) as defined by | |
| 1391 | - | CTA-861-H. | |
| 1392 | - | ||
| 1393 | - | max_fall is undefined by default. | |
| 1394 | - | </description> | |
| 1395 | - | ||
| 1396 | - | <arg name="max_fall" type="uint" summary="Maximum frame-average light level (cd/m²)"/> | |
| 1397 | - | </request> | |
| 1398 | - | </interface> | |
| 1399 | - | ||
| 1400 | - | <interface name="wp_image_description_v1" version="3"> | |
| 1401 | - | <description summary="Colorimetric image description"> | |
| 1402 | - | An image description carries information about the pixel color encoding | |
| 1403 | - | and its intended display and viewing environment. The image description is | |
| 1404 | - | attached to a wl_surface via | |
| 1405 | - | wp_color_management_surface_v1.set_image_description. A compositor can use | |
| 1406 | - | this information to decode pixel values into colorimetrically meaningful | |
| 1407 | - | quantities, which allows the compositor to transform the surface contents | |
| 1408 | - | to become suitable for various displays and viewing environments. | |
| 1409 | - | ||
| 1410 | - | Note, that the wp_image_description_v1 object is not ready to be used | |
| 1411 | - | immediately after creation. The object eventually delivers either the | |
| 1412 | - | 'ready' or the 'failed' event, specified in all requests creating it. The | |
| 1413 | - | object is deemed "ready" after receiving the 'ready' event. | |
| 1414 | - | ||
| 1415 | - | An object which is not ready is illegal to use, it can only be destroyed. | |
| 1416 | - | Any other request in this interface shall result in the 'not_ready' | |
| 1417 | - | protocol error. Attempts to use an object which is not ready through other | |
| 1418 | - | interfaces shall raise protocol errors defined there. | |
| 1419 | - | ||
| 1420 | - | Once created and regardless of how it was created, a | |
| 1421 | - | wp_image_description_v1 object always refers to one fixed image | |
| 1422 | - | description. It cannot change after creation. | |
| 1423 | - | </description> | |
| 1424 | - | ||
| 1425 | - | <request name="destroy" type="destructor"> | |
| 1426 | - | <description summary="destroy the image description"> | |
| 1427 | - | Destroy this object. It is safe to destroy an object which is not ready. | |
| 1428 | - | ||
| 1429 | - | Destroying a wp_image_description_v1 object has no side-effects, not | |
| 1430 | - | even if a wp_color_management_surface_v1.set_image_description has not | |
| 1431 | - | yet been followed by a wl_surface.commit. | |
| 1432 | - | </description> | |
| 1433 | - | </request> | |
| 1434 | - | ||
| 1435 | - | <enum name="error"> | |
| 1436 | - | <description summary="protocol errors"/> | |
| 1437 | - | ||
| 1438 | - | <entry name="not_ready" value="0" | |
| 1439 | - | summary="attempted to use an object which is not ready"/> | |
| 1440 | - | <entry name="no_information" value="1" | |
| 1441 | - | summary="get_information not allowed"/> | |
| 1442 | - | </enum> | |
| 1443 | - | ||
| 1444 | - | <enum name="cause"> | |
| 1445 | - | <description summary="generic reason for failure"/> | |
| 1446 | - | ||
| 1447 | - | <entry name="low_version" value="0" | |
| 1448 | - | summary="interface version too low"/> | |
| 1449 | - | <entry name="unsupported" value="1" | |
| 1450 | - | summary="unsupported image description data"/> | |
| 1451 | - | <entry name="operating_system" value="2" | |
| 1452 | - | summary="error independent of the client"/> | |
| 1453 | - | <entry name="no_output" value="3" | |
| 1454 | - | summary="the relevant output no longer exists"/> | |
| 1455 | - | </enum> | |
| 1456 | - | ||
| 1457 | - | <event name="failed"> | |
| 1458 | - | <description summary="graceful error on creating the image description"> | |
| 1459 | - | If creating a wp_image_description_v1 object fails for a reason that is | |
| 1460 | - | not defined as a protocol error, this event is sent. | |
| 1461 | - | ||
| 1462 | - | The requests that create image description objects define whether and | |
| 1463 | - | when this can occur. Only such creation requests can trigger this event. | |
| 1464 | - | This event cannot be triggered after the image description was | |
| 1465 | - | successfully formed. | |
| 1466 | - | ||
| 1467 | - | Once this event has been sent, the wp_image_description_v1 object will | |
| 1468 | - | never become ready and it can only be destroyed. | |
| 1469 | - | </description> | |
| 1470 | - | ||
| 1471 | - | <arg name="cause" type="uint" enum="cause" | |
| 1472 | - | summary="generic reason"/> | |
| 1473 | - | <arg name="msg" type="string" | |
| 1474 | - | summary="ad hoc human-readable explanation"/> | |
| 1475 | - | </event> | |
| 1476 | - | ||
| 1477 | - | <event name="ready" deprecated-since="2"> | |
| 1478 | - | <description summary="the object is ready to be used (32-bit)"> | |
| 1479 | - | Starting from interface version 2, the 'ready2' event is sent instead | |
| 1480 | - | of this event. | |
| 1481 | - | ||
| 1482 | - | For the definition of this event, see the 'ready2' event. The | |
| 1483 | - | difference to this event is as follows. | |
| 1484 | - | ||
| 1485 | - | The id number is valid only as long as the protocol object is alive. If | |
| 1486 | - | all protocol objects referring to the same image description record are | |
| 1487 | - | destroyed, the id number may be recycled for a different image | |
| 1488 | - | description record. | |
| 1489 | - | </description> | |
| 1490 | - | ||
| 1491 | - | <arg name="identity" type="uint" | |
| 1492 | - | summary="the 32-bit image description id number"/> | |
| 1493 | - | </event> | |
| 1494 | - | ||
| 1495 | - | <request name="get_information"> | |
| 1496 | - | <description summary="get information about the image description"> | |
| 1497 | - | Creates a wp_image_description_info_v1 object which delivers the | |
| 1498 | - | information that makes up the image description. | |
| 1499 | - | ||
| 1500 | - | Not all image description protocol objects allow get_information | |
| 1501 | - | request. Whether it is allowed or not is defined by the request that | |
| 1502 | - | created the object. If get_information is not allowed, the protocol | |
| 1503 | - | error no_information is raised. | |
| 1504 | - | </description> | |
| 1505 | - | ||
| 1506 | - | <arg name="information" | |
| 1507 | - | type="new_id" interface="wp_image_description_info_v1"/> | |
| 1508 | - | </request> | |
| 1509 | - | ||
| 1510 | - | <!-- Version 2 additions --> | |
| 1511 | - | ||
| 1512 | - | <event name="ready2" since="2"> | |
| 1513 | - | <description summary="the object is ready to be used"> | |
| 1514 | - | Once this event has been sent, the wp_image_description_v1 object is | |
| 1515 | - | deemed "ready". Ready objects can be used to send requests and can be | |
| 1516 | - | used through other interfaces. | |
| 1517 | - | ||
| 1518 | - | Every ready wp_image_description_v1 protocol object refers to an | |
| 1519 | - | underlying image description record in the compositor. Multiple protocol | |
| 1520 | - | objects may end up referring to the same record. Clients may identify | |
| 1521 | - | these "copies" by comparing their id numbers: if the numbers from two | |
| 1522 | - | protocol objects are identical, the protocol objects refer to the same | |
| 1523 | - | image description record. Two different image description records | |
| 1524 | - | cannot have the same id number simultaneously. The id number does not | |
| 1525 | - | change during the lifetime of the image description record. | |
| 1526 | - | ||
| 1527 | - | Image description id number is not a protocol object id. Zero is | |
| 1528 | - | reserved as an invalid id number. It shall not be possible for a client | |
| 1529 | - | to refer to an image description by its id number in protocol. The id | |
| 1530 | - | numbers might not be portable between Wayland connections. A compositor | |
| 1531 | - | shall not send an invalid id number. | |
| 1532 | - | ||
| 1533 | - | Compositors must not recycle image description id numbers. | |
| 1534 | - | ||
| 1535 | - | This identity allows clients to de-duplicate image description records | |
| 1536 | - | and avoid get_information request if they already have the image | |
| 1537 | - | description information. | |
| 1538 | - | </description> | |
| 1539 | - | ||
| 1540 | - | <arg name="identity_hi" type="uint" | |
| 1541 | - | summary="high 32 bits of the 64-bit image description id number"/> | |
| 1542 | - | <arg name="identity_lo" type="uint" | |
| 1543 | - | summary="low 32 bits of the 64-bit image description id number"/> | |
| 1544 | - | </event> | |
| 1545 | - | </interface> | |
| 1546 | - | ||
| 1547 | - | <interface name="wp_image_description_info_v1" version="3"> | |
| 1548 | - | <description summary="Colorimetric image description information"> | |
| 1549 | - | Sends all matching events describing an image description object exactly | |
| 1550 | - | once and finally sends the 'done' event. | |
| 1551 | - | ||
| 1552 | - | This means | |
| 1553 | - | - if the image description is parametric, it must send | |
| 1554 | - | - primaries | |
| 1555 | - | - named_primaries, if applicable | |
| 1556 | - | - at least one of tf_power and tf_named, as applicable | |
| 1557 | - | - luminances | |
| 1558 | - | - target_primaries | |
| 1559 | - | - target_luminance | |
| 1560 | - | - if the image description is parametric, it may send, if applicable, | |
| 1561 | - | - target_max_cll | |
| 1562 | - | - target_max_fall | |
| 1563 | - | - if the image description contains an ICC profile, it must send the | |
| 1564 | - | icc_file event | |
| 1565 | - | ||
| 1566 | - | Once a wp_image_description_info_v1 object has delivered a 'done' event it | |
| 1567 | - | is automatically destroyed. | |
| 1568 | - | ||
| 1569 | - | Every wp_image_description_info_v1 created from the same | |
| 1570 | - | wp_image_description_v1 shall always return the exact same data. | |
| 1571 | - | </description> | |
| 1572 | - | ||
| 1573 | - | <event name="done" type="destructor"> | |
| 1574 | - | <description summary="end of information"> | |
| 1575 | - | Signals the end of information events and destroys the object. | |
| 1576 | - | </description> | |
| 1577 | - | </event> | |
| 1578 | - | ||
| 1579 | - | <event name="icc_file"> | |
| 1580 | - | <description summary="ICC profile matching the image description"> | |
| 1581 | - | The icc argument provides a file descriptor to the client which may be | |
| 1582 | - | memory-mapped to provide the ICC profile matching the image description. | |
| 1583 | - | The fd is read-only, and if mapped then it must be mapped with | |
| 1584 | - | MAP_PRIVATE by the client. | |
| 1585 | - | ||
| 1586 | - | The ICC profile version and other details are determined by the | |
| 1587 | - | compositor. There is no provision for a client to ask for a specific | |
| 1588 | - | kind of a profile. | |
| 1589 | - | </description> | |
| 1590 | - | ||
| 1591 | - | <arg name="icc" type="fd" summary="ICC profile file descriptor"/> | |
| 1592 | - | <arg name="icc_size" type="uint" summary="ICC profile size, in bytes"/> | |
| 1593 | - | <!-- Offset always 0, compositor must not expose unnecessary data. --> | |
| 1594 | - | </event> | |
| 1595 | - | ||
| 1596 | - | <event name="primaries"> | |
| 1597 | - | <description summary="primaries as chromaticity coordinates"> | |
| 1598 | - | Delivers the primary color volume primaries and white point using CIE | |
| 1599 | - | 1931 xy chromaticity coordinates. | |
| 1600 | - | ||
| 1601 | - | Each coordinate value is multiplied by 1 million to get the argument | |
| 1602 | - | value to carry precision of 6 decimals. | |
| 1603 | - | </description> | |
| 1604 | - | ||
| 1605 | - | <arg name="r_x" type="int" summary="Red x * 1M"/> | |
| 1606 | - | <arg name="r_y" type="int" summary="Red y * 1M"/> | |
| 1607 | - | <arg name="g_x" type="int" summary="Green x * 1M"/> | |
| 1608 | - | <arg name="g_y" type="int" summary="Green y * 1M"/> | |
| 1609 | - | <arg name="b_x" type="int" summary="Blue x * 1M"/> | |
| 1610 | - | <arg name="b_y" type="int" summary="Blue y * 1M"/> | |
| 1611 | - | <arg name="w_x" type="int" summary="White x * 1M"/> | |
| 1612 | - | <arg name="w_y" type="int" summary="White y * 1M"/> | |
| 1613 | - | </event> | |
| 1614 | - | ||
| 1615 | - | <event name="primaries_named"> | |
| 1616 | - | <description summary="named primaries"> | |
| 1617 | - | Delivers the primary color volume primaries and white point using an | |
| 1618 | - | explicitly enumerated named set. | |
| 1619 | - | </description> | |
| 1620 | - | ||
| 1621 | - | <arg name="primaries" type="uint" enum="wp_color_manager_v1.primaries" | |
| 1622 | - | summary="named primaries"/> | |
| 1623 | - | </event> | |
| 1624 | - | ||
| 1625 | - | <event name="tf_power"> | |
| 1626 | - | <description summary="transfer characteristic as a power curve"> | |
| 1627 | - | The color component transfer characteristic of this image description is | |
| 1628 | - | a pure power curve. This event provides the exponent of the power | |
| 1629 | - | function. This curve represents the conversion from electrical to | |
| 1630 | - | optical pixel or color values. | |
| 1631 | - | ||
| 1632 | - | The curve exponent has been multiplied by 10000 to get the argument eexp | |
| 1633 | - | value to carry the precision of 4 decimals. | |
| 1634 | - | </description> | |
| 1635 | - | ||
| 1636 | - | <arg name="eexp" type="uint" summary="the exponent * 10000"/> | |
| 1637 | - | </event> | |
| 1638 | - | ||
| 1639 | - | <event name="tf_named"> | |
| 1640 | - | <description summary="named transfer characteristic"> | |
| 1641 | - | Delivers the transfer characteristic using an explicitly enumerated | |
| 1642 | - | named function. | |
| 1643 | - | </description> | |
| 1644 | - | ||
| 1645 | - | <arg name="tf" type="uint" enum="wp_color_manager_v1.transfer_function" | |
| 1646 | - | summary="named transfer function"/> | |
| 1647 | - | </event> | |
| 1648 | - | ||
| 1649 | - | <event name="luminances"> | |
| 1650 | - | <description summary="primary color volume luminance range and reference white"> | |
| 1651 | - | Delivers the primary color volume luminance range and the reference | |
| 1652 | - | white luminance level. These values include the minimum display emission | |
| 1653 | - | and ambient flare luminances, assumed to be optically additive and have | |
| 1654 | - | the chromaticity of the primary color volume white point. | |
| 1655 | - | ||
| 1656 | - | The minimum luminance is multiplied by 10000 to get the argument | |
| 1657 | - | 'min_lum' value and carries precision of 4 decimals. The maximum | |
| 1658 | - | luminance and reference white luminance values are unscaled. | |
| 1659 | - | </description> | |
| 1660 | - | ||
| 1661 | - | <arg name="min_lum" type="uint" | |
| 1662 | - | summary="minimum luminance (cd/m²) * 10000"/> | |
| 1663 | - | <arg name="max_lum" type="uint" | |
| 1664 | - | summary="maximum luminance (cd/m²)"/> | |
| 1665 | - | <arg name="reference_lum" type="uint" | |
| 1666 | - | summary="reference white luminance (cd/m²)"/> | |
| 1667 | - | </event> | |
| 1668 | - | ||
| 1669 | - | <event name="target_primaries"> | |
| 1670 | - | <description summary="target primaries as chromaticity coordinates"> | |
| 1671 | - | Provides the color primaries and white point of the target color volume | |
| 1672 | - | using CIE 1931 xy chromaticity coordinates. This is compatible with the | |
| 1673 | - | SMPTE ST 2086 definition of HDR static metadata for mastering displays. | |
| 1674 | - | ||
| 1675 | - | While primary color volume is about how color is encoded, the target | |
| 1676 | - | color volume is the actually displayable color volume. | |
| 1677 | - | ||
| 1678 | - | Each coordinate value is multiplied by 1 million to get the argument | |
| 1679 | - | value to carry precision of 6 decimals. | |
| 1680 | - | </description> | |
| 1681 | - | ||
| 1682 | - | <arg name="r_x" type="int" summary="Red x * 1M"/> | |
| 1683 | - | <arg name="r_y" type="int" summary="Red y * 1M"/> | |
| 1684 | - | <arg name="g_x" type="int" summary="Green x * 1M"/> | |
| 1685 | - | <arg name="g_y" type="int" summary="Green y * 1M"/> | |
| 1686 | - | <arg name="b_x" type="int" summary="Blue x * 1M"/> | |
| 1687 | - | <arg name="b_y" type="int" summary="Blue y * 1M"/> | |
| 1688 | - | <arg name="w_x" type="int" summary="White x * 1M"/> | |
| 1689 | - | <arg name="w_y" type="int" summary="White y * 1M"/> | |
| 1690 | - | </event> | |
| 1691 | - | ||
| 1692 | - | <event name="target_luminance"> | |
| 1693 | - | <description summary="target luminance range"> | |
| 1694 | - | Provides the luminance range that the image description is targeting as | |
| 1695 | - | the minimum and maximum absolute luminance L. These values include the | |
| 1696 | - | minimum display emission and ambient flare luminances, assumed to be | |
| 1697 | - | optically additive and have the chromaticity of the primary color | |
| 1698 | - | volume white point. This should be compatible with the SMPTE ST 2086 | |
| 1699 | - | definition of HDR static metadata. | |
| 1700 | - | ||
| 1701 | - | This luminance range is only theoretical and may not correspond to the | |
| 1702 | - | luminance of light emitted on an actual display. | |
| 1703 | - | ||
| 1704 | - | Min L value is multiplied by 10000 to get the argument min_lum value and | |
| 1705 | - | carry precision of 4 decimals. Max L value is unscaled for max_lum. | |
| 1706 | - | </description> | |
| 1707 | - | ||
| 1708 | - | <arg name="min_lum" type="uint" summary="min L (cd/m²) * 10000"/> | |
| 1709 | - | <arg name="max_lum" type="uint" summary="max L (cd/m²)"/> | |
| 1710 | - | </event> | |
| 1711 | - | ||
| 1712 | - | <event name="target_max_cll"> | |
| 1713 | - | <description summary="target maximum content light level"> | |
| 1714 | - | Provides the targeted max_cll of the image description. max_cll is | |
| 1715 | - | defined by CTA-861-H. | |
| 1716 | - | ||
| 1717 | - | This luminance is only theoretical and may not correspond to the | |
| 1718 | - | luminance of light emitted on an actual display. | |
| 1719 | - | </description> | |
| 1720 | - | ||
| 1721 | - | <arg name="max_cll" type="uint" | |
| 1722 | - | summary="Maximum content light-level (cd/m²)"/> | |
| 1723 | - | </event> | |
| 1724 | - | ||
| 1725 | - | <event name="target_max_fall"> | |
| 1726 | - | <description summary="target maximum frame-average light level"> | |
| 1727 | - | Provides the targeted max_fall of the image description. max_fall is | |
| 1728 | - | defined by CTA-861-H. | |
| 1729 | - | ||
| 1730 | - | This luminance is only theoretical and may not correspond to the | |
| 1731 | - | luminance of light emitted on an actual display. | |
| 1732 | - | </description> | |
| 1733 | - | ||
| 1734 | - | <arg name="max_fall" type="uint" | |
| 1735 | - | summary="Maximum frame-average light level (cd/m²)"/> | |
| 1736 | - | </event> | |
| 1737 | - | </interface> | |
| 1738 | - | ||
| 1739 | - | <interface name="wp_image_description_reference_v1" version="1" frozen="true"> | |
| 1740 | - | <description summary="Reference to an image description"> | |
| 1741 | - | This object is a reference to an image description. This interface is | |
| 1742 | - | frozen at version 1 to allow other protocols to create | |
| 1743 | - | wp_image_description_v1 objects. | |
| 1744 | - | ||
| 1745 | - | The wp_color_manager_v1.get_image_description request can be used to | |
| 1746 | - | retrieve the underlying image description. | |
| 1747 | - | </description> | |
| 1748 | - | ||
| 1749 | - | <request name="destroy" type="destructor"> | |
| 1750 | - | <description summary="destroy the reference"> | |
| 1751 | - | Destroy this object. This has no effect on the referenced image | |
| 1752 | - | description. | |
| 1753 | - | </description> | |
| 1754 | - | </request> | |
| 1755 | - | </interface> | |
| 1756 | - | </protocol> | |
D protocol/colormanagement/color-management-v1_generated.go +0 -1554
| @@ -1,1554 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: color_management_v1 | |
| 3 | - | // Source: color-management-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright 2019 Sebastian Wick | |
| 7 | - | // Copyright 2019 Erwin Burema | |
| 8 | - | // Copyright 2020 AMD | |
| 9 | - | // Copyright 2020-2024 Collabora, Ltd. | |
| 10 | - | // Copyright 2024 Xaver Hugl | |
| 11 | - | // Copyright 2022-2025 Red Hat, Inc. | |
| 12 | - | // | |
| 13 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 14 | - | // copy of this software and associated documentation files (the "Software"), | |
| 15 | - | // to deal in the Software without restriction, including without limitation | |
| 16 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 17 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 18 | - | // Software is furnished to do so, subject to the following conditions: | |
| 19 | - | // | |
| 20 | - | // The above copyright notice and this permission notice (including the next | |
| 21 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 22 | - | // Software. | |
| 23 | - | // | |
| 24 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 25 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 26 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 27 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 28 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 29 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 30 | - | // DEALINGS IN THE SOFTWARE. | |
| 31 | - | ||
| 32 | - | package colormanagement | |
| 33 | - | ||
| 34 | - | import ( | |
| 35 | - | "sync" | |
| 36 | - | ||
| 37 | - | cross_wl_output "github.com/bnema/wlturbo/protocol/core" | |
| 38 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 39 | - | "github.com/bnema/wlturbo/wl" | |
| 40 | - | ) | |
| 41 | - | ||
| 42 | - | // WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE is the error unsupported_feature value. | |
| 43 | - | const WP_COLOR_MANAGER_V1_ERROR_UNSUPPORTED_FEATURE = 0 | |
| 44 | - | ||
| 45 | - | // ERROR_SURFACE_EXISTS is the error surface_exists value. | |
| 46 | - | const ERROR_SURFACE_EXISTS = 1 | |
| 47 | - | ||
| 48 | - | // RENDER_INTENT_PERCEPTUAL is the render_intent perceptual value. | |
| 49 | - | const RENDER_INTENT_PERCEPTUAL = 0 | |
| 50 | - | ||
| 51 | - | // RENDER_INTENT_RELATIVE is the render_intent relative value. | |
| 52 | - | const RENDER_INTENT_RELATIVE = 1 | |
| 53 | - | ||
| 54 | - | // RENDER_INTENT_SATURATION is the render_intent saturation value. | |
| 55 | - | const RENDER_INTENT_SATURATION = 2 | |
| 56 | - | ||
| 57 | - | // RENDER_INTENT_ABSOLUTE is the render_intent absolute value. | |
| 58 | - | const RENDER_INTENT_ABSOLUTE = 3 | |
| 59 | - | ||
| 60 | - | // RENDER_INTENT_RELATIVE_BPC is the render_intent relative_bpc value. | |
| 61 | - | const RENDER_INTENT_RELATIVE_BPC = 4 | |
| 62 | - | ||
| 63 | - | // RENDER_INTENT_ABSOLUTE_NO_ADAPTATION is the render_intent absolute_no_adaptation value. | |
| 64 | - | const RENDER_INTENT_ABSOLUTE_NO_ADAPTATION = 5 | |
| 65 | - | ||
| 66 | - | // FEATURE_ICC_V2_V4 is the feature icc_v2_v4 value. | |
| 67 | - | const FEATURE_ICC_V2_V4 = 0 | |
| 68 | - | ||
| 69 | - | // FEATURE_PARAMETRIC is the feature parametric value. | |
| 70 | - | const FEATURE_PARAMETRIC = 1 | |
| 71 | - | ||
| 72 | - | // FEATURE_SET_PRIMARIES is the feature set_primaries value. | |
| 73 | - | const FEATURE_SET_PRIMARIES = 2 | |
| 74 | - | ||
| 75 | - | // FEATURE_SET_TF_POWER is the feature set_tf_power value. | |
| 76 | - | const FEATURE_SET_TF_POWER = 3 | |
| 77 | - | ||
| 78 | - | // FEATURE_SET_LUMINANCES is the feature set_luminances value. | |
| 79 | - | const FEATURE_SET_LUMINANCES = 4 | |
| 80 | - | ||
| 81 | - | // FEATURE_SET_MASTERING_DISPLAY_PRIMARIES is the feature set_mastering_display_primaries value. | |
| 82 | - | const FEATURE_SET_MASTERING_DISPLAY_PRIMARIES = 5 | |
| 83 | - | ||
| 84 | - | // FEATURE_EXTENDED_TARGET_VOLUME is the feature extended_target_volume value. | |
| 85 | - | const FEATURE_EXTENDED_TARGET_VOLUME = 6 | |
| 86 | - | ||
| 87 | - | // FEATURE_WINDOWS_SCRGB is the feature windows_scrgb value. | |
| 88 | - | const FEATURE_WINDOWS_SCRGB = 7 | |
| 89 | - | ||
| 90 | - | // FEATURE_WINDOWS_BT2100 is the feature windows_bt2100 value. | |
| 91 | - | const FEATURE_WINDOWS_BT2100 = 8 | |
| 92 | - | ||
| 93 | - | // PRIMARIES_SRGB is the primaries srgb value. | |
| 94 | - | const PRIMARIES_SRGB = 1 | |
| 95 | - | ||
| 96 | - | // PRIMARIES_PAL_M is the primaries pal_m value. | |
| 97 | - | const PRIMARIES_PAL_M = 2 | |
| 98 | - | ||
| 99 | - | // PRIMARIES_PAL is the primaries pal value. | |
| 100 | - | const PRIMARIES_PAL = 3 | |
| 101 | - | ||
| 102 | - | // PRIMARIES_NTSC is the primaries ntsc value. | |
| 103 | - | const PRIMARIES_NTSC = 4 | |
| 104 | - | ||
| 105 | - | // PRIMARIES_GENERIC_FILM is the primaries generic_film value. | |
| 106 | - | const PRIMARIES_GENERIC_FILM = 5 | |
| 107 | - | ||
| 108 | - | // PRIMARIES_BT2020 is the primaries bt2020 value. | |
| 109 | - | const PRIMARIES_BT2020 = 6 | |
| 110 | - | ||
| 111 | - | // PRIMARIES_CIE1931_XYZ is the primaries cie1931_xyz value. | |
| 112 | - | const PRIMARIES_CIE1931_XYZ = 7 | |
| 113 | - | ||
| 114 | - | // PRIMARIES_DCI_P3 is the primaries dci_p3 value. | |
| 115 | - | const PRIMARIES_DCI_P3 = 8 | |
| 116 | - | ||
| 117 | - | // PRIMARIES_DISPLAY_P3 is the primaries display_p3 value. | |
| 118 | - | const PRIMARIES_DISPLAY_P3 = 9 | |
| 119 | - | ||
| 120 | - | // PRIMARIES_ADOBE_RGB is the primaries adobe_rgb value. | |
| 121 | - | const PRIMARIES_ADOBE_RGB = 10 | |
| 122 | - | ||
| 123 | - | // TRANSFER_FUNCTION_BT1886 is the transfer_function bt1886 value. | |
| 124 | - | const TRANSFER_FUNCTION_BT1886 = 1 | |
| 125 | - | ||
| 126 | - | // TRANSFER_FUNCTION_GAMMA22 is the transfer_function gamma22 value. | |
| 127 | - | const TRANSFER_FUNCTION_GAMMA22 = 2 | |
| 128 | - | ||
| 129 | - | // TRANSFER_FUNCTION_GAMMA28 is the transfer_function gamma28 value. | |
| 130 | - | const TRANSFER_FUNCTION_GAMMA28 = 3 | |
| 131 | - | ||
| 132 | - | // TRANSFER_FUNCTION_ST240 is the transfer_function st240 value. | |
| 133 | - | const TRANSFER_FUNCTION_ST240 = 4 | |
| 134 | - | ||
| 135 | - | // TRANSFER_FUNCTION_EXT_LINEAR is the transfer_function ext_linear value. | |
| 136 | - | const TRANSFER_FUNCTION_EXT_LINEAR = 5 | |
| 137 | - | ||
| 138 | - | // TRANSFER_FUNCTION_LOG_100 is the transfer_function log_100 value. | |
| 139 | - | const TRANSFER_FUNCTION_LOG_100 = 6 | |
| 140 | - | ||
| 141 | - | // TRANSFER_FUNCTION_LOG_316 is the transfer_function log_316 value. | |
| 142 | - | const TRANSFER_FUNCTION_LOG_316 = 7 | |
| 143 | - | ||
| 144 | - | // TRANSFER_FUNCTION_XVYCC is the transfer_function xvycc value. | |
| 145 | - | const TRANSFER_FUNCTION_XVYCC = 8 | |
| 146 | - | ||
| 147 | - | // TRANSFER_FUNCTION_SRGB is the transfer_function srgb value. | |
| 148 | - | const TRANSFER_FUNCTION_SRGB = 9 | |
| 149 | - | ||
| 150 | - | // TRANSFER_FUNCTION_EXT_SRGB is the transfer_function ext_srgb value. | |
| 151 | - | const TRANSFER_FUNCTION_EXT_SRGB = 10 | |
| 152 | - | ||
| 153 | - | // TRANSFER_FUNCTION_ST2084_PQ is the transfer_function st2084_pq value. | |
| 154 | - | const TRANSFER_FUNCTION_ST2084_PQ = 11 | |
| 155 | - | ||
| 156 | - | // TRANSFER_FUNCTION_ST428 is the transfer_function st428 value. | |
| 157 | - | const TRANSFER_FUNCTION_ST428 = 12 | |
| 158 | - | ||
| 159 | - | // TRANSFER_FUNCTION_HLG is the transfer_function hlg value. | |
| 160 | - | const TRANSFER_FUNCTION_HLG = 13 | |
| 161 | - | ||
| 162 | - | // TRANSFER_FUNCTION_COMPOUND_POWER_2_4 is the transfer_function compound_power_2_4 value. | |
| 163 | - | const TRANSFER_FUNCTION_COMPOUND_POWER_2_4 = 14 | |
| 164 | - | ||
| 165 | - | // ERROR_RENDER_INTENT is the error render_intent value. | |
| 166 | - | const ERROR_RENDER_INTENT = 0 | |
| 167 | - | ||
| 168 | - | // ERROR_IMAGE_DESCRIPTION is the error image_description value. | |
| 169 | - | const ERROR_IMAGE_DESCRIPTION = 1 | |
| 170 | - | ||
| 171 | - | // WP_COLOR_MANAGEMENT_SURFACE_V1_ERROR_INERT is the error inert value. | |
| 172 | - | const WP_COLOR_MANAGEMENT_SURFACE_V1_ERROR_INERT = 2 | |
| 173 | - | ||
| 174 | - | // WP_COLOR_MANAGEMENT_SURFACE_FEEDBACK_V1_ERROR_INERT is the error inert value. | |
| 175 | - | const WP_COLOR_MANAGEMENT_SURFACE_FEEDBACK_V1_ERROR_INERT = 0 | |
| 176 | - | ||
| 177 | - | // WP_COLOR_MANAGEMENT_SURFACE_FEEDBACK_V1_ERROR_UNSUPPORTED_FEATURE is the error unsupported_feature value. | |
| 178 | - | const WP_COLOR_MANAGEMENT_SURFACE_FEEDBACK_V1_ERROR_UNSUPPORTED_FEATURE = 1 | |
| 179 | - | ||
| 180 | - | // WP_IMAGE_DESCRIPTION_CREATOR_ICC_V1_ERROR_INCOMPLETE_SET is the error incomplete_set value. | |
| 181 | - | const WP_IMAGE_DESCRIPTION_CREATOR_ICC_V1_ERROR_INCOMPLETE_SET = 0 | |
| 182 | - | ||
| 183 | - | // WP_IMAGE_DESCRIPTION_CREATOR_ICC_V1_ERROR_ALREADY_SET is the error already_set value. | |
| 184 | - | const WP_IMAGE_DESCRIPTION_CREATOR_ICC_V1_ERROR_ALREADY_SET = 1 | |
| 185 | - | ||
| 186 | - | // ERROR_BAD_FD is the error bad_fd value. | |
| 187 | - | const ERROR_BAD_FD = 2 | |
| 188 | - | ||
| 189 | - | // ERROR_BAD_SIZE is the error bad_size value. | |
| 190 | - | const ERROR_BAD_SIZE = 3 | |
| 191 | - | ||
| 192 | - | // ERROR_OUT_OF_FILE is the error out_of_file value. | |
| 193 | - | const ERROR_OUT_OF_FILE = 4 | |
| 194 | - | ||
| 195 | - | // WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INCOMPLETE_SET is the error incomplete_set value. | |
| 196 | - | const WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_INCOMPLETE_SET = 0 | |
| 197 | - | ||
| 198 | - | // WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET is the error already_set value. | |
| 199 | - | const WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET = 1 | |
| 200 | - | ||
| 201 | - | // WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_UNSUPPORTED_FEATURE is the error unsupported_feature value. | |
| 202 | - | const WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_UNSUPPORTED_FEATURE = 2 | |
| 203 | - | ||
| 204 | - | // ERROR_INVALID_TF is the error invalid_tf value. | |
| 205 | - | const ERROR_INVALID_TF = 3 | |
| 206 | - | ||
| 207 | - | // ERROR_INVALID_PRIMARIES_NAMED is the error invalid_primaries_named value. | |
| 208 | - | const ERROR_INVALID_PRIMARIES_NAMED = 4 | |
| 209 | - | ||
| 210 | - | // ERROR_INVALID_LUMINANCE is the error invalid_luminance value. | |
| 211 | - | const ERROR_INVALID_LUMINANCE = 5 | |
| 212 | - | ||
| 213 | - | // ERROR_NOT_READY is the error not_ready value. | |
| 214 | - | const ERROR_NOT_READY = 0 | |
| 215 | - | ||
| 216 | - | // ERROR_NO_INFORMATION is the error no_information value. | |
| 217 | - | const ERROR_NO_INFORMATION = 1 | |
| 218 | - | ||
| 219 | - | // CAUSE_LOW_VERSION is the cause low_version value. | |
| 220 | - | const CAUSE_LOW_VERSION = 0 | |
| 221 | - | ||
| 222 | - | // CAUSE_UNSUPPORTED is the cause unsupported value. | |
| 223 | - | const CAUSE_UNSUPPORTED = 1 | |
| 224 | - | ||
| 225 | - | // CAUSE_OPERATING_SYSTEM is the cause operating_system value. | |
| 226 | - | const CAUSE_OPERATING_SYSTEM = 2 | |
| 227 | - | ||
| 228 | - | // CAUSE_NO_OUTPUT is the cause no_output value. | |
| 229 | - | const CAUSE_NO_OUTPUT = 3 | |
| 230 | - | ||
| 231 | - | // WpColorManagerInterface is the protocol interface name. | |
| 232 | - | const WpColorManagerInterface = "wp_color_manager_v1" | |
| 233 | - | ||
| 234 | - | // WpColorManager is the generated binding for wp_color_manager_v1 version 3. | |
| 235 | - | type WpColorManager struct { | |
| 236 | - | wl.BaseProxy | |
| 237 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 238 | - | // handlers while another goroutine dispatches events. | |
| 239 | - | handlersMu sync.Mutex | |
| 240 | - | onSupportedIntent []func(renderIntent uint32) | |
| 241 | - | onSupportedFeature []func(feature uint32) | |
| 242 | - | onSupportedTfNamed []func(tf uint32) | |
| 243 | - | onSupportedPrimariesNamed []func(primaries uint32) | |
| 244 | - | onDone []func() | |
| 245 | - | } | |
| 246 | - | ||
| 247 | - | // NewWpColorManager returns an unbound WpColorManager. | |
| 248 | - | func NewWpColorManager(ctx *wl.Context) *WpColorManager { | |
| 249 | - | obj := &WpColorManager{} | |
| 250 | - | obj.SetContext(ctx) | |
| 251 | - | ctx.Register(obj) | |
| 252 | - | return obj | |
| 253 | - | } | |
| 254 | - | ||
| 255 | - | // Destroy the wp_color_manager_v1 object. This does not affect any other objects in any way. | |
| 256 | - | func (o *WpColorManager) Destroy() error { | |
| 257 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_color_manager_v1.destroy", Destructor: true}); err != nil { | |
| 258 | - | return err | |
| 259 | - | } | |
| 260 | - | return nil | |
| 261 | - | } | |
| 262 | - | ||
| 263 | - | // This creates a new wp_color_management_output_v1 object for the given wl_output. See the wp_color_management_output_v1 interface for more details. | |
| 264 | - | func (o *WpColorManager) GetOutput(output *cross_wl_output.Output) (*WpColorManagementOutput, error) { | |
| 265 | - | var arg1 wl.Object | |
| 266 | - | if output != nil { | |
| 267 | - | arg1 = output | |
| 268 | - | } | |
| 269 | - | child := &WpColorManagementOutput{} | |
| 270 | - | child.SetContext(o.Context()) | |
| 271 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_color_manager_v1.get_output", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 272 | - | return nil, err | |
| 273 | - | } | |
| 274 | - | return child, nil | |
| 275 | - | } | |
| 276 | - | ||
| 277 | - | // If a wp_color_management_surface_v1 object already exists for the given wl_surface, the protocol error surface_exists is raised. This creates a new color wp_color_management_surface_v1 object for the given wl_surface. See the wp_color_management_surface_v1 interface for more details. | |
| 278 | - | func (o *WpColorManager) GetSurface(surface *cross_wl_surface.Surface) (*WpColorManagementSurface, error) { | |
| 279 | - | var arg1 wl.Object | |
| 280 | - | if surface != nil { | |
| 281 | - | arg1 = surface | |
| 282 | - | } | |
| 283 | - | child := &WpColorManagementSurface{} | |
| 284 | - | child.SetContext(o.Context()) | |
| 285 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_color_manager_v1.get_surface", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 286 | - | return nil, err | |
| 287 | - | } | |
| 288 | - | return child, nil | |
| 289 | - | } | |
| 290 | - | ||
| 291 | - | // This creates a new color wp_color_management_surface_feedback_v1 object for the given wl_surface. See the wp_color_management_surface_feedback_v1 interface for more details. | |
| 292 | - | func (o *WpColorManager) GetSurfaceFeedback(surface *cross_wl_surface.Surface) (*WpColorManagementSurfaceFeedback, error) { | |
| 293 | - | var arg1 wl.Object | |
| 294 | - | if surface != nil { | |
| 295 | - | arg1 = surface | |
| 296 | - | } | |
| 297 | - | child := &WpColorManagementSurfaceFeedback{} | |
| 298 | - | child.SetContext(o.Context()) | |
| 299 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 3, Name: "wp_color_manager_v1.get_surface_feedback", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 300 | - | return nil, err | |
| 301 | - | } | |
| 302 | - | return child, nil | |
| 303 | - | } | |
| 304 | - | ||
| 305 | - | // Makes a new ICC-based image description creator object with all properties initially unset. The client can then use the object's interface to define all the required properties for an image description and finally create a wp_image_description_v1 object. This request can be used when the compositor advertises wp_color_manager_v1.feature.icc_v2_v4. Otherwise this request raises the protocol error unsupported_feature. | |
| 306 | - | func (o *WpColorManager) CreateIccCreator() (*WpImageDescriptionCreatorIcc, error) { | |
| 307 | - | child := &WpImageDescriptionCreatorIcc{} | |
| 308 | - | child.SetContext(o.Context()) | |
| 309 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 4, Name: "wp_color_manager_v1.create_icc_creator", Child: child}, wl.ArgObject(child)); err != nil { | |
| 310 | - | return nil, err | |
| 311 | - | } | |
| 312 | - | return child, nil | |
| 313 | - | } | |
| 314 | - | ||
| 315 | - | // Makes a new parametric image description creator object with all properties initially unset. The client can then use the object's interface to define all the required properties for an image description and finally create a wp_image_description_v1 object. This request can be used when the compositor advertises wp_color_manager_v1.feature.parametric. Otherwise this request raises the protocol error unsupported_feature. | |
| 316 | - | func (o *WpColorManager) CreateParametricCreator() (*WpImageDescriptionCreatorParams, error) { | |
| 317 | - | child := &WpImageDescriptionCreatorParams{} | |
| 318 | - | child.SetContext(o.Context()) | |
| 319 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 5, Name: "wp_color_manager_v1.create_parametric_creator", Child: child}, wl.ArgObject(child)); err != nil { | |
| 320 | - | return nil, err | |
| 321 | - | } | |
| 322 | - | return child, nil | |
| 323 | - | } | |
| 324 | - | ||
| 325 | - | // This creates a pre-defined image description for the so-called Windows-scRGB stimulus encoding. This comes from the Windows 10 handling of its own definition of an scRGB color space for an HDR screen driven in BT.2100/PQ signalling mode. Windows-scRGB uses sRGB (BT.709) color primaries and white point. The transfer characteristic is extended linear. The nominal color channel value range is extended, meaning it includes negative and greater than 1.0 values. Negative values are used to escape the sRGB color gamut boundaries. To make use of the extended range, the client needs to use a pixel format that can represent those values, e.g. floating-point 16 bits per channel. Nominal color value R=G=B=0.0 corresponds to BT.2100/PQ system 0 cd/m², and R=G=B=1.0 corresponds to BT.2100/PQ system 80 cd/m². The maximum is R=G=B=125.0 corresponding to 10k cd/m². Windows-scRGB is displayed by Windows 10 by converting it to BT.2100/PQ, maintaining the CIE 1931 chromaticity and mapping the luminance as above. No adjustment is made to the signal to account for the viewing conditions. The reference white level of Windows-scRGB is unknown. If a reference white level must be assumed for compositor processing, it should be R=G=B=2.5375 corresponding to 203 cd/m² of Report ITU-R BT.2408-7. The target color volume of Windows-scRGB is unknown. The color gamut may be anything between sRGB and BT.2100. Note: EGL_EXT_gl_colorspace_scrgb_linear definition differs from Windows-scRGB by using R=G=B=1.0 as the reference white level, while Windows-scRGB reference white level is unknown or varies. However, it seems probable that Windows implements both EGL_EXT_gl_colorspace_scrgb_linear and Vulkan VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT as Windows-scRGB. This request can be used when the compositor advertises wp_color_manager_v1.feature.windows_scrgb. Otherwise this request raises the protocol error unsupported_feature. The resulting image description object does not allow get_information request. The wp_image_description_v1.ready event shall be sent. | |
| 326 | - | func (o *WpColorManager) CreateWindowsScrgb() (*WpImageDescription, error) { | |
| 327 | - | child := &WpImageDescription{} | |
| 328 | - | child.SetContext(o.Context()) | |
| 329 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 6, Name: "wp_color_manager_v1.create_windows_scrgb", Child: child}, wl.ArgObject(child)); err != nil { | |
| 330 | - | return nil, err | |
| 331 | - | } | |
| 332 | - | return child, nil | |
| 333 | - | } | |
| 334 | - | ||
| 335 | - | // This request retrieves the image description backing a reference. The get_information request can be used if and only if the request that creates the reference allows it. | |
| 336 | - | func (o *WpColorManager) GetImageDescription(reference *WpImageDescriptionReference) (*WpImageDescription, error) { | |
| 337 | - | var arg1 wl.Object | |
| 338 | - | if reference != nil { | |
| 339 | - | arg1 = reference | |
| 340 | - | } | |
| 341 | - | child := &WpImageDescription{} | |
| 342 | - | child.SetContext(o.Context()) | |
| 343 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 7, Name: "wp_color_manager_v1.get_image_description", Since: 2, Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 344 | - | return nil, err | |
| 345 | - | } | |
| 346 | - | return child, nil | |
| 347 | - | } | |
| 348 | - | ||
| 349 | - | // This creates a pre-defined image description for the so-called Windows-BT.2100 stimulus encoding. This comes from the Windows 10 handling of its own definition of a BT.2100 color space for an HDR screen driven in BT.2100/PQ signalling mode. Windows-BT.2100 uses BT.2020 color primaries and white point. The transfer characteristic is st2084_pq. Windows-BT.2100 is generally displayed by Windows 10 without any adjustments to the signal to account for viewing conditions. The reference white level of Windows-BT.2100 is unknown. If a reference white level must be assumed for compositor processing, it should be 203 cd/m² of Report ITU-R BT.2408-7. The target color volume of Windows-BT.2100 is unknown. The color gamut may be anything up to BT.2100. This request can be used when the compositor advertises wp_color_manager_v1.feature.windows_bt2100. Otherwise this request raises the protocol error unsupported_feature. The resulting image description object does not allow get_information request. The wp_image_description_v1.ready event shall be sent. | |
| 350 | - | func (o *WpColorManager) CreateWindowsBt2100() (*WpImageDescription, error) { | |
| 351 | - | child := &WpImageDescription{} | |
| 352 | - | child.SetContext(o.Context()) | |
| 353 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 8, Name: "wp_color_manager_v1.create_windows_bt2100", Since: 3, Child: child}, wl.ArgObject(child)); err != nil { | |
| 354 | - | return nil, err | |
| 355 | - | } | |
| 356 | - | return child, nil | |
| 357 | - | } | |
| 358 | - | ||
| 359 | - | // OnSupportedIntent registers a handler for the supported_intent event. | |
| 360 | - | // | |
| 361 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 362 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 363 | - | func (o *WpColorManager) OnSupportedIntent(handler func(renderIntent uint32)) { | |
| 364 | - | if handler == nil { | |
| 365 | - | return | |
| 366 | - | } | |
| 367 | - | o.handlersMu.Lock() | |
| 368 | - | defer o.handlersMu.Unlock() | |
| 369 | - | o.onSupportedIntent = append(o.onSupportedIntent, handler) | |
| 370 | - | } | |
| 371 | - | ||
| 372 | - | // handlersForSupportedIntent returns the handlers registered for supported_intent, taken | |
| 373 | - | // under the lock so a handler may register another handler while events are | |
| 374 | - | // being dispatched. | |
| 375 | - | func (o *WpColorManager) handlersForSupportedIntent() []func(renderIntent uint32) { | |
| 376 | - | o.handlersMu.Lock() | |
| 377 | - | defer o.handlersMu.Unlock() | |
| 378 | - | return o.onSupportedIntent | |
| 379 | - | } | |
| 380 | - | ||
| 381 | - | // OnSupportedFeature registers a handler for the supported_feature event. | |
| 382 | - | // | |
| 383 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 384 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 385 | - | func (o *WpColorManager) OnSupportedFeature(handler func(feature uint32)) { | |
| 386 | - | if handler == nil { | |
| 387 | - | return | |
| 388 | - | } | |
| 389 | - | o.handlersMu.Lock() | |
| 390 | - | defer o.handlersMu.Unlock() | |
| 391 | - | o.onSupportedFeature = append(o.onSupportedFeature, handler) | |
| 392 | - | } | |
| 393 | - | ||
| 394 | - | // handlersForSupportedFeature returns the handlers registered for supported_feature, taken | |
| 395 | - | // under the lock so a handler may register another handler while events are | |
| 396 | - | // being dispatched. | |
| 397 | - | func (o *WpColorManager) handlersForSupportedFeature() []func(feature uint32) { | |
| 398 | - | o.handlersMu.Lock() | |
| 399 | - | defer o.handlersMu.Unlock() | |
| 400 | - | return o.onSupportedFeature | |
| 401 | - | } | |
| 402 | - | ||
| 403 | - | // OnSupportedTfNamed registers a handler for the supported_tf_named event. | |
| 404 | - | // | |
| 405 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 406 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 407 | - | func (o *WpColorManager) OnSupportedTfNamed(handler func(tf uint32)) { | |
| 408 | - | if handler == nil { | |
| 409 | - | return | |
| 410 | - | } | |
| 411 | - | o.handlersMu.Lock() | |
| 412 | - | defer o.handlersMu.Unlock() | |
| 413 | - | o.onSupportedTfNamed = append(o.onSupportedTfNamed, handler) | |
| 414 | - | } | |
| 415 | - | ||
| 416 | - | // handlersForSupportedTfNamed returns the handlers registered for supported_tf_named, taken | |
| 417 | - | // under the lock so a handler may register another handler while events are | |
| 418 | - | // being dispatched. | |
| 419 | - | func (o *WpColorManager) handlersForSupportedTfNamed() []func(tf uint32) { | |
| 420 | - | o.handlersMu.Lock() | |
| 421 | - | defer o.handlersMu.Unlock() | |
| 422 | - | return o.onSupportedTfNamed | |
| 423 | - | } | |
| 424 | - | ||
| 425 | - | // OnSupportedPrimariesNamed registers a handler for the supported_primaries_named event. | |
| 426 | - | // | |
| 427 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 428 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 429 | - | func (o *WpColorManager) OnSupportedPrimariesNamed(handler func(primaries uint32)) { | |
| 430 | - | if handler == nil { | |
| 431 | - | return | |
| 432 | - | } | |
| 433 | - | o.handlersMu.Lock() | |
| 434 | - | defer o.handlersMu.Unlock() | |
| 435 | - | o.onSupportedPrimariesNamed = append(o.onSupportedPrimariesNamed, handler) | |
| 436 | - | } | |
| 437 | - | ||
| 438 | - | // handlersForSupportedPrimariesNamed returns the handlers registered for supported_primaries_named, taken | |
| 439 | - | // under the lock so a handler may register another handler while events are | |
| 440 | - | // being dispatched. | |
| 441 | - | func (o *WpColorManager) handlersForSupportedPrimariesNamed() []func(primaries uint32) { | |
| 442 | - | o.handlersMu.Lock() | |
| 443 | - | defer o.handlersMu.Unlock() | |
| 444 | - | return o.onSupportedPrimariesNamed | |
| 445 | - | } | |
| 446 | - | ||
| 447 | - | // OnDone registers a handler for the done event. | |
| 448 | - | // | |
| 449 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 450 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 451 | - | func (o *WpColorManager) OnDone(handler func()) { | |
| 452 | - | if handler == nil { | |
| 453 | - | return | |
| 454 | - | } | |
| 455 | - | o.handlersMu.Lock() | |
| 456 | - | defer o.handlersMu.Unlock() | |
| 457 | - | o.onDone = append(o.onDone, handler) | |
| 458 | - | } | |
| 459 | - | ||
| 460 | - | // handlersForDone returns the handlers registered for done, taken | |
| 461 | - | // under the lock so a handler may register another handler while events are | |
| 462 | - | // being dispatched. | |
| 463 | - | func (o *WpColorManager) handlersForDone() []func() { | |
| 464 | - | o.handlersMu.Lock() | |
| 465 | - | defer o.handlersMu.Unlock() | |
| 466 | - | return o.onDone | |
| 467 | - | } | |
| 468 | - | ||
| 469 | - | // EventSignature returns the declared event argument types in wire order. | |
| 470 | - | func (o *WpColorManager) EventSignature(opcode uint16) (string, bool) { | |
| 471 | - | switch opcode { | |
| 472 | - | case 0: | |
| 473 | - | return "uint,", true | |
| 474 | - | case 1: | |
| 475 | - | return "uint,", true | |
| 476 | - | case 2: | |
| 477 | - | return "uint,", true | |
| 478 | - | case 3: | |
| 479 | - | return "uint,", true | |
| 480 | - | case 4: | |
| 481 | - | return "", true | |
| 482 | - | default: | |
| 483 | - | return "", false | |
| 484 | - | } | |
| 485 | - | } | |
| 486 | - | ||
| 487 | - | // Dispatch decodes one event on wp_color_manager_v1 and calls the registered handlers. | |
| 488 | - | func (o *WpColorManager) Dispatch(event *wl.Event) { | |
| 489 | - | switch event.Opcode { | |
| 490 | - | case 0: // supported_intent | |
| 491 | - | renderIntent := event.Uint32() | |
| 492 | - | ||
| 493 | - | for i, handler := range o.handlersForSupportedIntent() { | |
| 494 | - | _ = i | |
| 495 | - | handler(renderIntent) | |
| 496 | - | } | |
| 497 | - | case 1: // supported_feature | |
| 498 | - | feature := event.Uint32() | |
| 499 | - | ||
| 500 | - | for i, handler := range o.handlersForSupportedFeature() { | |
| 501 | - | _ = i | |
| 502 | - | handler(feature) | |
| 503 | - | } | |
| 504 | - | case 2: // supported_tf_named | |
| 505 | - | tf := event.Uint32() | |
| 506 | - | ||
| 507 | - | for i, handler := range o.handlersForSupportedTfNamed() { | |
| 508 | - | _ = i | |
| 509 | - | handler(tf) | |
| 510 | - | } | |
| 511 | - | case 3: // supported_primaries_named | |
| 512 | - | primaries := event.Uint32() | |
| 513 | - | ||
| 514 | - | for i, handler := range o.handlersForSupportedPrimariesNamed() { | |
| 515 | - | _ = i | |
| 516 | - | handler(primaries) | |
| 517 | - | } | |
| 518 | - | case 4: // done | |
| 519 | - | ||
| 520 | - | for i, handler := range o.handlersForDone() { | |
| 521 | - | _ = i | |
| 522 | - | handler() | |
| 523 | - | } | |
| 524 | - | default: | |
| 525 | - | } | |
| 526 | - | } | |
| 527 | - | ||
| 528 | - | // WpColorManagementOutputInterface is the protocol interface name. | |
| 529 | - | const WpColorManagementOutputInterface = "wp_color_management_output_v1" | |
| 530 | - | ||
| 531 | - | // WpColorManagementOutput is the generated binding for wp_color_management_output_v1 version 3. | |
| 532 | - | type WpColorManagementOutput struct { | |
| 533 | - | wl.BaseProxy | |
| 534 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 535 | - | // handlers while another goroutine dispatches events. | |
| 536 | - | handlersMu sync.Mutex | |
| 537 | - | onImageDescriptionChanged []func() | |
| 538 | - | } | |
| 539 | - | ||
| 540 | - | // NewWpColorManagementOutput returns an unbound WpColorManagementOutput. | |
| 541 | - | func NewWpColorManagementOutput(ctx *wl.Context) *WpColorManagementOutput { | |
| 542 | - | obj := &WpColorManagementOutput{} | |
| 543 | - | obj.SetContext(ctx) | |
| 544 | - | ctx.Register(obj) | |
| 545 | - | return obj | |
| 546 | - | } | |
| 547 | - | ||
| 548 | - | // Destroy the color wp_color_management_output_v1 object. This does not affect any remaining protocol objects. | |
| 549 | - | func (o *WpColorManagementOutput) Destroy() error { | |
| 550 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_color_management_output_v1.destroy", Destructor: true}); err != nil { | |
| 551 | - | return err | |
| 552 | - | } | |
| 553 | - | return nil | |
| 554 | - | } | |
| 555 | - | ||
| 556 | - | // This creates a new wp_image_description_v1 object for the current image description of the output. There always is exactly one image description active for an output so the client should destroy the image description created by earlier invocations of this request. This request is usually sent as a reaction to the image_description_changed event or when creating a wp_color_management_output_v1 object. The image description of an output represents the color encoding the output expects. There might be performance and power advantages, as well as improved color reproduction, if a content update matches the image description of the output it is being shown on. If a content update is shown on any other output than the one it matches the image description of, then the color reproduction on those outputs might be considerably worse. The created wp_image_description_v1 object preserves the image description of the output from the time the object was created. The resulting image description object allows get_information request. If this protocol object is inert, the resulting image description object shall immediately deliver the wp_image_description_v1.failed event with the no_output cause. If the interface version is inadequate for the output's image description, meaning that the client does not support all the events needed to deliver the crucial information, the resulting image description object shall immediately deliver the wp_image_description_v1.failed event with the low_version cause. Otherwise the object shall immediately deliver the ready event. | |
| 557 | - | func (o *WpColorManagementOutput) GetImageDescription() (*WpImageDescription, error) { | |
| 558 | - | child := &WpImageDescription{} | |
| 559 | - | child.SetContext(o.Context()) | |
| 560 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_color_management_output_v1.get_image_description", Child: child}, wl.ArgObject(child)); err != nil { | |
| 561 | - | return nil, err | |
| 562 | - | } | |
| 563 | - | return child, nil | |
| 564 | - | } | |
| 565 | - | ||
| 566 | - | // OnImageDescriptionChanged registers a handler for the image_description_changed event. | |
| 567 | - | // | |
| 568 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 569 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 570 | - | func (o *WpColorManagementOutput) OnImageDescriptionChanged(handler func()) { | |
| 571 | - | if handler == nil { | |
| 572 | - | return | |
| 573 | - | } | |
| 574 | - | o.handlersMu.Lock() | |
| 575 | - | defer o.handlersMu.Unlock() | |
| 576 | - | o.onImageDescriptionChanged = append(o.onImageDescriptionChanged, handler) | |
| 577 | - | } | |
| 578 | - | ||
| 579 | - | // handlersForImageDescriptionChanged returns the handlers registered for image_description_changed, taken | |
| 580 | - | // under the lock so a handler may register another handler while events are | |
| 581 | - | // being dispatched. | |
| 582 | - | func (o *WpColorManagementOutput) handlersForImageDescriptionChanged() []func() { | |
| 583 | - | o.handlersMu.Lock() | |
| 584 | - | defer o.handlersMu.Unlock() | |
| 585 | - | return o.onImageDescriptionChanged | |
| 586 | - | } | |
| 587 | - | ||
| 588 | - | // EventSignature returns the declared event argument types in wire order. | |
| 589 | - | func (o *WpColorManagementOutput) EventSignature(opcode uint16) (string, bool) { | |
| 590 | - | switch opcode { | |
| 591 | - | case 0: | |
| 592 | - | return "", true | |
| 593 | - | default: | |
| 594 | - | return "", false | |
| 595 | - | } | |
| 596 | - | } | |
| 597 | - | ||
| 598 | - | // Dispatch decodes one event on wp_color_management_output_v1 and calls the registered handlers. | |
| 599 | - | func (o *WpColorManagementOutput) Dispatch(event *wl.Event) { | |
| 600 | - | switch event.Opcode { | |
| 601 | - | case 0: // image_description_changed | |
| 602 | - | ||
| 603 | - | for i, handler := range o.handlersForImageDescriptionChanged() { | |
| 604 | - | _ = i | |
| 605 | - | handler() | |
| 606 | - | } | |
| 607 | - | default: | |
| 608 | - | } | |
| 609 | - | } | |
| 610 | - | ||
| 611 | - | // WpColorManagementSurfaceInterface is the protocol interface name. | |
| 612 | - | const WpColorManagementSurfaceInterface = "wp_color_management_surface_v1" | |
| 613 | - | ||
| 614 | - | // WpColorManagementSurface is the generated binding for wp_color_management_surface_v1 version 3. | |
| 615 | - | type WpColorManagementSurface struct { | |
| 616 | - | wl.BaseProxy | |
| 617 | - | } | |
| 618 | - | ||
| 619 | - | // NewWpColorManagementSurface returns an unbound WpColorManagementSurface. | |
| 620 | - | func NewWpColorManagementSurface(ctx *wl.Context) *WpColorManagementSurface { | |
| 621 | - | obj := &WpColorManagementSurface{} | |
| 622 | - | obj.SetContext(ctx) | |
| 623 | - | ctx.Register(obj) | |
| 624 | - | return obj | |
| 625 | - | } | |
| 626 | - | ||
| 627 | - | // Destroy the wp_color_management_surface_v1 object and do the same as unset_image_description. | |
| 628 | - | func (o *WpColorManagementSurface) Destroy() error { | |
| 629 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_color_management_surface_v1.destroy", Destructor: true}); err != nil { | |
| 630 | - | return err | |
| 631 | - | } | |
| 632 | - | return nil | |
| 633 | - | } | |
| 634 | - | ||
| 635 | - | // If this protocol object is inert, the protocol error inert is raised. Set the image description of the underlying surface. The image description and rendering intent are double-buffered state, see wl_surface.commit. It is the client's responsibility to understand the image description it sets on a surface, and to provide content that matches that image description. Compositors might convert images to match their own or any other image descriptions. Image descriptions which are not ready (see wp_image_description_v1) are forbidden in this request, and in such case the protocol error image_description is raised. All image descriptions which are ready (see wp_image_description_v1) are allowed and must always be accepted by the compositor. When an image description is set on a surface, it establishes an explicit link between surface pixel values and surface colorimetry. This link may be undefined for some pixel values, see the image description creator interfaces for the conditions. Non-finite floating-point values (NaN, Inf) always have an undefined colorimetry. A rendering intent provides the client's preference on how surface colorimetry should be mapped to each output. The render_intent value must be one advertised by the compositor with wp_color_manager_v1.render_intent event, otherwise the protocol error render_intent is raised. By default, a surface does not have an associated image description nor a rendering intent. The handling of color on such surfaces is compositor implementation defined. Compositors should handle such surfaces as sRGB, but may handle them differently if they have specific requirements. Setting the image description has copy semantics; after this request, the image description can be immediately destroyed without affecting the pending state of the surface. | |
| 636 | - | func (o *WpColorManagementSurface) SetImageDescription(imageDescription *WpImageDescription, renderIntent uint32) error { | |
| 637 | - | var arg0 wl.Object | |
| 638 | - | if imageDescription != nil { | |
| 639 | - | arg0 = imageDescription | |
| 640 | - | } | |
| 641 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_color_management_surface_v1.set_image_description"}, wl.ArgObject(arg0), wl.ArgUint(renderIntent)); err != nil { | |
| 642 | - | return err | |
| 643 | - | } | |
| 644 | - | return nil | |
| 645 | - | } | |
| 646 | - | ||
| 647 | - | // If this protocol object is inert, the protocol error inert is raised. This request removes any image description from the surface. See set_image_description for how a compositor handles a surface without an image description. This is double-buffered state, see wl_surface.commit. | |
| 648 | - | func (o *WpColorManagementSurface) UnsetImageDescription() error { | |
| 649 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_color_management_surface_v1.unset_image_description"}); err != nil { | |
| 650 | - | return err | |
| 651 | - | } | |
| 652 | - | return nil | |
| 653 | - | } | |
| 654 | - | ||
| 655 | - | // EventSignature returns the declared event argument types in wire order. | |
| 656 | - | func (o *WpColorManagementSurface) EventSignature(opcode uint16) (string, bool) { | |
| 657 | - | switch opcode { | |
| 658 | - | default: | |
| 659 | - | return "", false | |
| 660 | - | } | |
| 661 | - | } | |
| 662 | - | ||
| 663 | - | // Dispatch decodes one event on wp_color_management_surface_v1 and calls the registered handlers. | |
| 664 | - | func (o *WpColorManagementSurface) Dispatch(event *wl.Event) { | |
| 665 | - | switch event.Opcode { | |
| 666 | - | default: | |
| 667 | - | } | |
| 668 | - | } | |
| 669 | - | ||
| 670 | - | // WpColorManagementSurfaceFeedbackInterface is the protocol interface name. | |
| 671 | - | const WpColorManagementSurfaceFeedbackInterface = "wp_color_management_surface_feedback_v1" | |
| 672 | - | ||
| 673 | - | // WpColorManagementSurfaceFeedback is the generated binding for wp_color_management_surface_feedback_v1 version 3. | |
| 674 | - | type WpColorManagementSurfaceFeedback struct { | |
| 675 | - | wl.BaseProxy | |
| 676 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 677 | - | // handlers while another goroutine dispatches events. | |
| 678 | - | handlersMu sync.Mutex | |
| 679 | - | onPreferredChanged []func(identity uint32) | |
| 680 | - | onPreferredChanged2 []func(identityHi uint32, identityLo uint32) | |
| 681 | - | } | |
| 682 | - | ||
| 683 | - | // NewWpColorManagementSurfaceFeedback returns an unbound WpColorManagementSurfaceFeedback. | |
| 684 | - | func NewWpColorManagementSurfaceFeedback(ctx *wl.Context) *WpColorManagementSurfaceFeedback { | |
| 685 | - | obj := &WpColorManagementSurfaceFeedback{} | |
| 686 | - | obj.SetContext(ctx) | |
| 687 | - | ctx.Register(obj) | |
| 688 | - | return obj | |
| 689 | - | } | |
| 690 | - | ||
| 691 | - | // Destroy the wp_color_management_surface_feedback_v1 object. | |
| 692 | - | func (o *WpColorManagementSurfaceFeedback) Destroy() error { | |
| 693 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_color_management_surface_feedback_v1.destroy", Destructor: true}); err != nil { | |
| 694 | - | return err | |
| 695 | - | } | |
| 696 | - | return nil | |
| 697 | - | } | |
| 698 | - | ||
| 699 | - | // If this protocol object is inert, the protocol error inert is raised. The preferred image description represents the compositor's preferred color encoding for this wl_surface at the current time. There might be performance and power advantages, as well as improved color reproduction, if the image description of a content update matches the preferred image description. This creates a new wp_image_description_v1 object for the currently preferred image description for the wl_surface. The client should stop using and destroy the image descriptions created by earlier invocations of this request for the associated wl_surface. This request is usually sent as a reaction to the preferred_changed event or when creating a wp_color_management_surface_feedback_v1 object if the client is capable of adapting to image descriptions. The created wp_image_description_v1 object preserves the preferred image description of the wl_surface from the time the object was created. The resulting image description object allows get_information request. If the image description is parametric, the client should set it on its wl_surface only if the image description is an exact match with the client content. Particularly if everything else matches, but the target color volume is greater than what the client needs, the client should create its own parameric image description with its exact parameters. If the interface version is inadequate for the preferred image description, meaning that the client does not support all the events needed to deliver the crucial information, the resulting image description object shall immediately deliver the wp_image_description_v1.failed event with the low_version cause, otherwise the object shall immediately deliver the ready event. | |
| 700 | - | func (o *WpColorManagementSurfaceFeedback) GetPreferred() (*WpImageDescription, error) { | |
| 701 | - | child := &WpImageDescription{} | |
| 702 | - | child.SetContext(o.Context()) | |
| 703 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_color_management_surface_feedback_v1.get_preferred", Child: child}, wl.ArgObject(child)); err != nil { | |
| 704 | - | return nil, err | |
| 705 | - | } | |
| 706 | - | return child, nil | |
| 707 | - | } | |
| 708 | - | ||
| 709 | - | // The same description as for get_preferred applies, except the returned image description is guaranteed to be parametric. This is meant for clients that can only deal with parametric image descriptions. If the compositor doesn't support parametric image descriptions, the unsupported_feature error is emitted. | |
| 710 | - | func (o *WpColorManagementSurfaceFeedback) GetPreferredParametric() (*WpImageDescription, error) { | |
| 711 | - | child := &WpImageDescription{} | |
| 712 | - | child.SetContext(o.Context()) | |
| 713 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_color_management_surface_feedback_v1.get_preferred_parametric", Child: child}, wl.ArgObject(child)); err != nil { | |
| 714 | - | return nil, err | |
| 715 | - | } | |
| 716 | - | return child, nil | |
| 717 | - | } | |
| 718 | - | ||
| 719 | - | // OnPreferredChanged registers a handler for the preferred_changed event. | |
| 720 | - | // | |
| 721 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 722 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 723 | - | func (o *WpColorManagementSurfaceFeedback) OnPreferredChanged(handler func(identity uint32)) { | |
| 724 | - | if handler == nil { | |
| 725 | - | return | |
| 726 | - | } | |
| 727 | - | o.handlersMu.Lock() | |
| 728 | - | defer o.handlersMu.Unlock() | |
| 729 | - | o.onPreferredChanged = append(o.onPreferredChanged, handler) | |
| 730 | - | } | |
| 731 | - | ||
| 732 | - | // handlersForPreferredChanged returns the handlers registered for preferred_changed, taken | |
| 733 | - | // under the lock so a handler may register another handler while events are | |
| 734 | - | // being dispatched. | |
| 735 | - | func (o *WpColorManagementSurfaceFeedback) handlersForPreferredChanged() []func(identity uint32) { | |
| 736 | - | o.handlersMu.Lock() | |
| 737 | - | defer o.handlersMu.Unlock() | |
| 738 | - | return o.onPreferredChanged | |
| 739 | - | } | |
| 740 | - | ||
| 741 | - | // OnPreferredChanged2 registers a handler for the preferred_changed2 event. | |
| 742 | - | // | |
| 743 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 744 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 745 | - | func (o *WpColorManagementSurfaceFeedback) OnPreferredChanged2(handler func(identityHi uint32, identityLo uint32)) { | |
| 746 | - | if handler == nil { | |
| 747 | - | return | |
| 748 | - | } | |
| 749 | - | o.handlersMu.Lock() | |
| 750 | - | defer o.handlersMu.Unlock() | |
| 751 | - | o.onPreferredChanged2 = append(o.onPreferredChanged2, handler) | |
| 752 | - | } | |
| 753 | - | ||
| 754 | - | // handlersForPreferredChanged2 returns the handlers registered for preferred_changed2, taken | |
| 755 | - | // under the lock so a handler may register another handler while events are | |
| 756 | - | // being dispatched. | |
| 757 | - | func (o *WpColorManagementSurfaceFeedback) handlersForPreferredChanged2() []func(identityHi uint32, identityLo uint32) { | |
| 758 | - | o.handlersMu.Lock() | |
| 759 | - | defer o.handlersMu.Unlock() | |
| 760 | - | return o.onPreferredChanged2 | |
| 761 | - | } | |
| 762 | - | ||
| 763 | - | // EventSignature returns the declared event argument types in wire order. | |
| 764 | - | func (o *WpColorManagementSurfaceFeedback) EventSignature(opcode uint16) (string, bool) { | |
| 765 | - | switch opcode { | |
| 766 | - | case 0: | |
| 767 | - | return "uint,", true | |
| 768 | - | case 1: | |
| 769 | - | return "uint,uint,", true | |
| 770 | - | default: | |
| 771 | - | return "", false | |
| 772 | - | } | |
| 773 | - | } | |
| 774 | - | ||
| 775 | - | // Dispatch decodes one event on wp_color_management_surface_feedback_v1 and calls the registered handlers. | |
| 776 | - | func (o *WpColorManagementSurfaceFeedback) Dispatch(event *wl.Event) { | |
| 777 | - | switch event.Opcode { | |
| 778 | - | case 0: // preferred_changed | |
| 779 | - | identity := event.Uint32() | |
| 780 | - | ||
| 781 | - | for i, handler := range o.handlersForPreferredChanged() { | |
| 782 | - | _ = i | |
| 783 | - | handler(identity) | |
| 784 | - | } | |
| 785 | - | case 1: // preferred_changed2 | |
| 786 | - | identityHi := event.Uint32() | |
| 787 | - | identityLo := event.Uint32() | |
| 788 | - | ||
| 789 | - | for i, handler := range o.handlersForPreferredChanged2() { | |
| 790 | - | _ = i | |
| 791 | - | handler(identityHi, identityLo) | |
| 792 | - | } | |
| 793 | - | default: | |
| 794 | - | } | |
| 795 | - | } | |
| 796 | - | ||
| 797 | - | // WpImageDescriptionCreatorIccInterface is the protocol interface name. | |
| 798 | - | const WpImageDescriptionCreatorIccInterface = "wp_image_description_creator_icc_v1" | |
| 799 | - | ||
| 800 | - | // WpImageDescriptionCreatorIcc is the generated binding for wp_image_description_creator_icc_v1 version 3. | |
| 801 | - | type WpImageDescriptionCreatorIcc struct { | |
| 802 | - | wl.BaseProxy | |
| 803 | - | } | |
| 804 | - | ||
| 805 | - | // NewWpImageDescriptionCreatorIcc returns an unbound WpImageDescriptionCreatorIcc. | |
| 806 | - | func NewWpImageDescriptionCreatorIcc(ctx *wl.Context) *WpImageDescriptionCreatorIcc { | |
| 807 | - | obj := &WpImageDescriptionCreatorIcc{} | |
| 808 | - | obj.SetContext(ctx) | |
| 809 | - | ctx.Register(obj) | |
| 810 | - | return obj | |
| 811 | - | } | |
| 812 | - | ||
| 813 | - | // Create an image description object based on the ICC information previously set on this object. A compositor must parse the ICC data in some undefined but finite amount of time. The completeness of the parameter set is verified. If the set is not complete, the protocol error incomplete_set is raised. For the definition of a complete set, see the description of this interface. If the particular combination of the information is not supported by the compositor, the resulting image description object shall immediately deliver the wp_image_description_v1.failed event with the 'unsupported' cause. If a valid image description was created from the information, the wp_image_description_v1.ready event will eventually be sent instead. This request destroys the wp_image_description_creator_icc_v1 object. The resulting image description object does not allow get_information request. | |
| 814 | - | func (o *WpImageDescriptionCreatorIcc) Create() (*WpImageDescription, error) { | |
| 815 | - | child := &WpImageDescription{} | |
| 816 | - | child.SetContext(o.Context()) | |
| 817 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_image_description_creator_icc_v1.create", Destructor: true, Child: child}, wl.ArgObject(child)); err != nil { | |
| 818 | - | return nil, err | |
| 819 | - | } | |
| 820 | - | return child, nil | |
| 821 | - | } | |
| 822 | - | ||
| 823 | - | // Sets the ICC profile file to be used as the basis of the image description. The data shall be found through the given fd at the given offset, having the given length. The fd must be seekable and readable. Violating these requirements raises the bad_fd protocol error. If reading the data fails due to an error independent of the client, the compositor shall send the wp_image_description_v1.failed event on the created wp_image_description_v1 with the 'operating_system' cause. The maximum size of the ICC profile is 32 MB. If length is greater than that or zero, the protocol error bad_size is raised. If offset + length exceeds the file size, the protocol error out_of_file is raised. A compositor may read the file at any time starting from this request and only until whichever happens first: - If create request was issued, the wp_image_description_v1 object delivers either failed or ready event; or - if create request was not issued, this wp_image_description_creator_icc_v1 object is destroyed. A compositor shall not modify the contents of the file, and the fd may be sealed for writes and size changes. The client must ensure to its best ability that the data does not change while the compositor is reading it. The data must represent a valid ICC profile. The ICC profile version must be 2 or 4, it must be a 3 channel profile and the class must be Display or ColorSpace. Violating these requirements will not result in a protocol error, but will eventually send the wp_image_description_v1.failed event on the created wp_image_description_v1 with the 'unsupported' cause. See the International Color Consortium specification ICC.1:2022 for more details about ICC profiles. If ICC file has already been set on this object, the protocol error already_set is raised. | |
| 824 | - | func (o *WpImageDescriptionCreatorIcc) SetIccFile(iccProfile int, offset uint32, length uint32) error { | |
| 825 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_image_description_creator_icc_v1.set_icc_file", FDs: []int{iccProfile}}, wl.ArgFD(), wl.ArgUint(offset), wl.ArgUint(length)); err != nil { | |
| 826 | - | return err | |
| 827 | - | } | |
| 828 | - | return nil | |
| 829 | - | } | |
| 830 | - | ||
| 831 | - | // EventSignature returns the declared event argument types in wire order. | |
| 832 | - | func (o *WpImageDescriptionCreatorIcc) EventSignature(opcode uint16) (string, bool) { | |
| 833 | - | switch opcode { | |
| 834 | - | default: | |
| 835 | - | return "", false | |
| 836 | - | } | |
| 837 | - | } | |
| 838 | - | ||
| 839 | - | // Dispatch decodes one event on wp_image_description_creator_icc_v1 and calls the registered handlers. | |
| 840 | - | func (o *WpImageDescriptionCreatorIcc) Dispatch(event *wl.Event) { | |
| 841 | - | switch event.Opcode { | |
| 842 | - | default: | |
| 843 | - | } | |
| 844 | - | } | |
| 845 | - | ||
| 846 | - | // WpImageDescriptionCreatorParamsInterface is the protocol interface name. | |
| 847 | - | const WpImageDescriptionCreatorParamsInterface = "wp_image_description_creator_params_v1" | |
| 848 | - | ||
| 849 | - | // WpImageDescriptionCreatorParams is the generated binding for wp_image_description_creator_params_v1 version 3. | |
| 850 | - | type WpImageDescriptionCreatorParams struct { | |
| 851 | - | wl.BaseProxy | |
| 852 | - | } | |
| 853 | - | ||
| 854 | - | // NewWpImageDescriptionCreatorParams returns an unbound WpImageDescriptionCreatorParams. | |
| 855 | - | func NewWpImageDescriptionCreatorParams(ctx *wl.Context) *WpImageDescriptionCreatorParams { | |
| 856 | - | obj := &WpImageDescriptionCreatorParams{} | |
| 857 | - | obj.SetContext(ctx) | |
| 858 | - | ctx.Register(obj) | |
| 859 | - | return obj | |
| 860 | - | } | |
| 861 | - | ||
| 862 | - | // Create an image description object based on the parameters previously set on this object. The completeness of the parameter set is verified. If the set is not complete, the protocol error incomplete_set is raised. For the definition of a complete set, see the description of this interface. When both max_cll and max_fall are set, max_fall must be less or equal to max_cll otherwise the invalid_luminance protocol error is raised. In version 1, these following conditions also result in the invalid_luminance protocol error. Version 2 and later do not have this requirement. - When max_cll is set, it must be greater than min L and less or equal to max L of the mastering luminance range. - When max_fall is set, it must be greater than min L and less or equal to max L of the mastering luminance range. If the particular combination of the parameter set is not supported by the compositor, the resulting image description object shall immediately deliver the wp_image_description_v1.failed event with the 'unsupported' cause. If a valid image description was created from the parameter set, the wp_image_description_v1.ready event will eventually be sent instead. This request destroys the wp_image_description_creator_params_v1 object. The resulting image description object does not allow get_information request. | |
| 863 | - | func (o *WpImageDescriptionCreatorParams) Create() (*WpImageDescription, error) { | |
| 864 | - | child := &WpImageDescription{} | |
| 865 | - | child.SetContext(o.Context()) | |
| 866 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_image_description_creator_params_v1.create", Destructor: true, Child: child}, wl.ArgObject(child)); err != nil { | |
| 867 | - | return nil, err | |
| 868 | - | } | |
| 869 | - | return child, nil | |
| 870 | - | } | |
| 871 | - | ||
| 872 | - | // Sets the transfer characteristic using explicitly enumerated named functions. When the resulting image description is attached to an image, the content should be decoded according to the industry standard practices for the transfer characteristic. Only names advertised with wp_color_manager_v1 event supported_tf_named are allowed. Other values shall raise the protocol error invalid_tf. If transfer characteristic has already been set on this object, the protocol error already_set is raised. | |
| 873 | - | func (o *WpImageDescriptionCreatorParams) SetTfNamed(tf uint32) error { | |
| 874 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_image_description_creator_params_v1.set_tf_named"}, wl.ArgUint(tf)); err != nil { | |
| 875 | - | return err | |
| 876 | - | } | |
| 877 | - | return nil | |
| 878 | - | } | |
| 879 | - | ||
| 880 | - | // Sets the color component transfer characteristic to a power curve with the given exponent. Negative values are handled by mirroring the positive half of the curve through the origin. The valid domain and range of the curve are all finite real numbers. This curve represents the conversion from electrical to optical color channel values. The curve exponent shall be multiplied by 10000 to get the argument eexp value to carry the precision of 4 decimals. The curve exponent must be at least 1.0 and at most 10.0. Otherwise the protocol error invalid_tf is raised. If transfer characteristic has already been set on this object, the protocol error already_set is raised. This request can be used when the compositor advertises wp_color_manager_v1.feature.set_tf_power. Otherwise this request raises the protocol error unsupported_feature. | |
| 881 | - | func (o *WpImageDescriptionCreatorParams) SetTfPower(eexp uint32) error { | |
| 882 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_image_description_creator_params_v1.set_tf_power"}, wl.ArgUint(eexp)); err != nil { | |
| 883 | - | return err | |
| 884 | - | } | |
| 885 | - | return nil | |
| 886 | - | } | |
| 887 | - | ||
| 888 | - | // Sets the color primaries and white point using explicitly named sets. This describes the primary color volume which is the basis for color value encoding. Only names advertised with wp_color_manager_v1 event supported_primaries_named are allowed. Other values shall raise the protocol error invalid_primaries_named. If primaries have already been set on this object, the protocol error already_set is raised. | |
| 889 | - | func (o *WpImageDescriptionCreatorParams) SetPrimariesNamed(primaries uint32) error { | |
| 890 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 3, Name: "wp_image_description_creator_params_v1.set_primaries_named"}, wl.ArgUint(primaries)); err != nil { | |
| 891 | - | return err | |
| 892 | - | } | |
| 893 | - | return nil | |
| 894 | - | } | |
| 895 | - | ||
| 896 | - | // Sets the color primaries and white point using CIE 1931 xy chromaticity coordinates. This describes the primary color volume which is the basis for color value encoding. Each coordinate value is multiplied by 1 million to get the argument value to carry precision of 6 decimals. If primaries have already been set on this object, the protocol error already_set is raised. This request can be used if the compositor advertises wp_color_manager_v1.feature.set_primaries. Otherwise this request raises the protocol error unsupported_feature. | |
| 897 | - | func (o *WpImageDescriptionCreatorParams) SetPrimaries(rX int32, rY int32, gX int32, gY int32, bX int32, bY int32, wX int32, wY int32) error { | |
| 898 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 4, Name: "wp_image_description_creator_params_v1.set_primaries"}, wl.ArgInt(rX), wl.ArgInt(rY), wl.ArgInt(gX), wl.ArgInt(gY), wl.ArgInt(bX), wl.ArgInt(bY), wl.ArgInt(wX), wl.ArgInt(wY)); err != nil { | |
| 899 | - | return err | |
| 900 | - | } | |
| 901 | - | return nil | |
| 902 | - | } | |
| 903 | - | ||
| 904 | - | // Sets the primary color volume luminance range and the reference white luminance level. These values include the minimum display emission, but not external flare. The minimum display emission is assumed to have the chromaticity of the primary color volume white point. The default luminances from https://www.color.org/chardata/rgb/srgb.xalter are - primary color volume minimum: 0.2 cd/m² - primary color volume maximum: 80 cd/m² - reference white: 80 cd/m² Setting a named transfer characteristic can imply other default luminances. The default luminances get overwritten when this request is used. With transfer_function.st2084_pq the given 'max_lum' value is ignored, and 'max_lum' is taken as 'min_lum' + 10000 cd/m². 'min_lum' and 'max_lum' specify the minimum and maximum luminances of the primary color volume as reproduced by the targeted display. 'reference_lum' specifies the luminance of the reference white as reproduced by the targeted display, and reflects the targeted viewing environment. Compositors should make sure that all content is anchored, meaning that an input signal level of 'reference_lum' on one image description and another input signal level of 'reference_lum' on another image description should produce the same output level, even though the 'reference_lum' on both image representations can be different. 'reference_lum' may be higher than 'max_lum'. In that case reaching the reference white output level in image content requires the 'extended_target_volume' feature support. If 'max_lum' or 'reference_lum' are less than or equal to 'min_lum', the protocol error invalid_luminance is raised. The minimum luminance is multiplied by 10000 to get the argument 'min_lum' value and carries precision of 4 decimals. The maximum luminance and reference white luminance values are unscaled. If the primary color volume luminance range and the reference white luminance level have already been set on this object, the protocol error already_set is raised. This request can be used if the compositor advertises wp_color_manager_v1.feature.set_luminances. Otherwise this request raises the protocol error unsupported_feature. | |
| 905 | - | func (o *WpImageDescriptionCreatorParams) SetLuminances(minLum uint32, maxLum uint32, referenceLum uint32) error { | |
| 906 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 5, Name: "wp_image_description_creator_params_v1.set_luminances"}, wl.ArgUint(minLum), wl.ArgUint(maxLum), wl.ArgUint(referenceLum)); err != nil { | |
| 907 | - | return err | |
| 908 | - | } | |
| 909 | - | return nil | |
| 910 | - | } | |
| 911 | - | ||
| 912 | - | // Provides the color primaries and white point of the mastering display using CIE 1931 xy chromaticity coordinates. This is compatible with the SMPTE ST 2086 definition of HDR static metadata. The mastering display primaries and mastering display luminances define the target color volume. If mastering display primaries are not explicitly set, the target color volume is assumed to have the same primaries as the primary color volume. The target color volume is defined by all tristimulus values between 0.0 and 1.0 (inclusive) of the color space defined by the given mastering display primaries and white point. The colorimetry is identical between the container color space and the mastering display color space, including that no chromatic adaptation is applied even if the white points differ. The target color volume can exceed the primary color volume to allow for a greater color volume with an existing color space definition (for example scRGB). It can be smaller than the primary color volume to minimize gamut and tone mapping distances for big color spaces (HDR metadata). To make use of the entire target color volume a suitable pixel format has to be chosen (e.g. floating point to exceed the primary color volume, or abusing limited quantization range as with xvYCC). Each coordinate value is multiplied by 1 million to get the argument value to carry precision of 6 decimals. If mastering display primaries have already been set on this object, the protocol error already_set is raised. This request can be used if the compositor advertises wp_color_manager_v1.feature.set_mastering_display_primaries. Otherwise this request raises the protocol error unsupported_feature. The advertisement implies support only for target color volumes fully contained within the primary color volume. If a compositor additionally supports target color volume exceeding the primary color volume, it must advertise wp_color_manager_v1.feature.extended_target_volume. If a client uses target color volume exceeding the primary color volume and the compositor does not support it, the result is implementation defined. Compositors are recommended to detect this case and fail the image description gracefully, but it may as well result in color artifacts. | |
| 913 | - | func (o *WpImageDescriptionCreatorParams) SetMasteringDisplayPrimaries(rX int32, rY int32, gX int32, gY int32, bX int32, bY int32, wX int32, wY int32) error { | |
| 914 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 6, Name: "wp_image_description_creator_params_v1.set_mastering_display_primaries"}, wl.ArgInt(rX), wl.ArgInt(rY), wl.ArgInt(gX), wl.ArgInt(gY), wl.ArgInt(bX), wl.ArgInt(bY), wl.ArgInt(wX), wl.ArgInt(wY)); err != nil { | |
| 915 | - | return err | |
| 916 | - | } | |
| 917 | - | return nil | |
| 918 | - | } | |
| 919 | - | ||
| 920 | - | // Sets the luminance range that was used during the content mastering process as the minimum and maximum absolute luminance L. These values include the minimum display emission and ambient flare luminances, assumed to be optically additive and have the chromaticity of the primary color volume white point. This should be compatible with the SMPTE ST 2086 definition of HDR static metadata. The mastering display primaries and mastering display luminances define the target color volume. If mastering luminances are not explicitly set, the target color volume is assumed to have the same min and max luminances as the primary color volume. If max L is less than or equal to min L, the protocol error invalid_luminance is raised. Min L value is multiplied by 10000 to get the argument min_lum value and carry precision of 4 decimals. Max L value is unscaled for max_lum. This request can be used if the compositor advertises wp_color_manager_v1.feature.set_mastering_display_primaries. Otherwise this request raises the protocol error unsupported_feature. The advertisement implies support only for target color volumes fully contained within the primary color volume. If a compositor additionally supports target color volume exceeding the primary color volume, it must advertise wp_color_manager_v1.feature.extended_target_volume. If a client uses target color volume exceeding the primary color volume and the compositor does not support it, the result is implementation defined. Compositors are recommended to detect this case and fail the image description gracefully, but it may as well result in color artifacts. | |
| 921 | - | func (o *WpImageDescriptionCreatorParams) SetMasteringLuminance(minLum uint32, maxLum uint32) error { | |
| 922 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 7, Name: "wp_image_description_creator_params_v1.set_mastering_luminance"}, wl.ArgUint(minLum), wl.ArgUint(maxLum)); err != nil { | |
| 923 | - | return err | |
| 924 | - | } | |
| 925 | - | return nil | |
| 926 | - | } | |
| 927 | - | ||
| 928 | - | // Sets the maximum content light level (max_cll) as defined by CTA-861-H. max_cll is undefined by default. | |
| 929 | - | func (o *WpImageDescriptionCreatorParams) SetMaxCll(maxCll uint32) error { | |
| 930 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 8, Name: "wp_image_description_creator_params_v1.set_max_cll"}, wl.ArgUint(maxCll)); err != nil { | |
| 931 | - | return err | |
| 932 | - | } | |
| 933 | - | return nil | |
| 934 | - | } | |
| 935 | - | ||
| 936 | - | // Sets the maximum frame-average light level (max_fall) as defined by CTA-861-H. max_fall is undefined by default. | |
| 937 | - | func (o *WpImageDescriptionCreatorParams) SetMaxFall(maxFall uint32) error { | |
| 938 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 9, Name: "wp_image_description_creator_params_v1.set_max_fall"}, wl.ArgUint(maxFall)); err != nil { | |
| 939 | - | return err | |
| 940 | - | } | |
| 941 | - | return nil | |
| 942 | - | } | |
| 943 | - | ||
| 944 | - | // EventSignature returns the declared event argument types in wire order. | |
| 945 | - | func (o *WpImageDescriptionCreatorParams) EventSignature(opcode uint16) (string, bool) { | |
| 946 | - | switch opcode { | |
| 947 | - | default: | |
| 948 | - | return "", false | |
| 949 | - | } | |
| 950 | - | } | |
| 951 | - | ||
| 952 | - | // Dispatch decodes one event on wp_image_description_creator_params_v1 and calls the registered handlers. | |
| 953 | - | func (o *WpImageDescriptionCreatorParams) Dispatch(event *wl.Event) { | |
| 954 | - | switch event.Opcode { | |
| 955 | - | default: | |
| 956 | - | } | |
| 957 | - | } | |
| 958 | - | ||
| 959 | - | // WpImageDescriptionInterface is the protocol interface name. | |
| 960 | - | const WpImageDescriptionInterface = "wp_image_description_v1" | |
| 961 | - | ||
| 962 | - | // WpImageDescription is the generated binding for wp_image_description_v1 version 3. | |
| 963 | - | type WpImageDescription struct { | |
| 964 | - | wl.BaseProxy | |
| 965 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 966 | - | // handlers while another goroutine dispatches events. | |
| 967 | - | handlersMu sync.Mutex | |
| 968 | - | onFailed []func(cause uint32, msg string) | |
| 969 | - | onReady []func(identity uint32) | |
| 970 | - | onReady2 []func(identityHi uint32, identityLo uint32) | |
| 971 | - | } | |
| 972 | - | ||
| 973 | - | // NewWpImageDescription returns an unbound WpImageDescription. | |
| 974 | - | func NewWpImageDescription(ctx *wl.Context) *WpImageDescription { | |
| 975 | - | obj := &WpImageDescription{} | |
| 976 | - | obj.SetContext(ctx) | |
| 977 | - | ctx.Register(obj) | |
| 978 | - | return obj | |
| 979 | - | } | |
| 980 | - | ||
| 981 | - | // Destroy this object. It is safe to destroy an object which is not ready. Destroying a wp_image_description_v1 object has no side-effects, not even if a wp_color_management_surface_v1.set_image_description has not yet been followed by a wl_surface.commit. | |
| 982 | - | func (o *WpImageDescription) Destroy() error { | |
| 983 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_image_description_v1.destroy", Destructor: true}); err != nil { | |
| 984 | - | return err | |
| 985 | - | } | |
| 986 | - | return nil | |
| 987 | - | } | |
| 988 | - | ||
| 989 | - | // Creates a wp_image_description_info_v1 object which delivers the information that makes up the image description. Not all image description protocol objects allow get_information request. Whether it is allowed or not is defined by the request that created the object. If get_information is not allowed, the protocol error no_information is raised. | |
| 990 | - | func (o *WpImageDescription) GetInformation() (*WpImageDescriptionInfo, error) { | |
| 991 | - | child := &WpImageDescriptionInfo{} | |
| 992 | - | child.SetContext(o.Context()) | |
| 993 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_image_description_v1.get_information", Child: child}, wl.ArgObject(child)); err != nil { | |
| 994 | - | return nil, err | |
| 995 | - | } | |
| 996 | - | return child, nil | |
| 997 | - | } | |
| 998 | - | ||
| 999 | - | // OnFailed registers a handler for the failed event. | |
| 1000 | - | // | |
| 1001 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1002 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1003 | - | func (o *WpImageDescription) OnFailed(handler func(cause uint32, msg string)) { | |
| 1004 | - | if handler == nil { | |
| 1005 | - | return | |
| 1006 | - | } | |
| 1007 | - | o.handlersMu.Lock() | |
| 1008 | - | defer o.handlersMu.Unlock() | |
| 1009 | - | o.onFailed = append(o.onFailed, handler) | |
| 1010 | - | } | |
| 1011 | - | ||
| 1012 | - | // handlersForFailed returns the handlers registered for failed, taken | |
| 1013 | - | // under the lock so a handler may register another handler while events are | |
| 1014 | - | // being dispatched. | |
| 1015 | - | func (o *WpImageDescription) handlersForFailed() []func(cause uint32, msg string) { | |
| 1016 | - | o.handlersMu.Lock() | |
| 1017 | - | defer o.handlersMu.Unlock() | |
| 1018 | - | return o.onFailed | |
| 1019 | - | } | |
| 1020 | - | ||
| 1021 | - | // OnReady registers a handler for the ready event. | |
| 1022 | - | // | |
| 1023 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1024 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1025 | - | func (o *WpImageDescription) OnReady(handler func(identity uint32)) { | |
| 1026 | - | if handler == nil { | |
| 1027 | - | return | |
| 1028 | - | } | |
| 1029 | - | o.handlersMu.Lock() | |
| 1030 | - | defer o.handlersMu.Unlock() | |
| 1031 | - | o.onReady = append(o.onReady, handler) | |
| 1032 | - | } | |
| 1033 | - | ||
| 1034 | - | // handlersForReady returns the handlers registered for ready, taken | |
| 1035 | - | // under the lock so a handler may register another handler while events are | |
| 1036 | - | // being dispatched. | |
| 1037 | - | func (o *WpImageDescription) handlersForReady() []func(identity uint32) { | |
| 1038 | - | o.handlersMu.Lock() | |
| 1039 | - | defer o.handlersMu.Unlock() | |
| 1040 | - | return o.onReady | |
| 1041 | - | } | |
| 1042 | - | ||
| 1043 | - | // OnReady2 registers a handler for the ready2 event. | |
| 1044 | - | // | |
| 1045 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1046 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1047 | - | func (o *WpImageDescription) OnReady2(handler func(identityHi uint32, identityLo uint32)) { | |
| 1048 | - | if handler == nil { | |
| 1049 | - | return | |
| 1050 | - | } | |
| 1051 | - | o.handlersMu.Lock() | |
| 1052 | - | defer o.handlersMu.Unlock() | |
| 1053 | - | o.onReady2 = append(o.onReady2, handler) | |
| 1054 | - | } | |
| 1055 | - | ||
| 1056 | - | // handlersForReady2 returns the handlers registered for ready2, taken | |
| 1057 | - | // under the lock so a handler may register another handler while events are | |
| 1058 | - | // being dispatched. | |
| 1059 | - | func (o *WpImageDescription) handlersForReady2() []func(identityHi uint32, identityLo uint32) { | |
| 1060 | - | o.handlersMu.Lock() | |
| 1061 | - | defer o.handlersMu.Unlock() | |
| 1062 | - | return o.onReady2 | |
| 1063 | - | } | |
| 1064 | - | ||
| 1065 | - | // EventSignature returns the declared event argument types in wire order. | |
| 1066 | - | func (o *WpImageDescription) EventSignature(opcode uint16) (string, bool) { | |
| 1067 | - | switch opcode { | |
| 1068 | - | case 0: | |
| 1069 | - | return "uint,string,", true | |
| 1070 | - | case 1: | |
| 1071 | - | return "uint,", true | |
| 1072 | - | case 2: | |
| 1073 | - | return "uint,uint,", true | |
| 1074 | - | default: | |
| 1075 | - | return "", false | |
| 1076 | - | } | |
| 1077 | - | } | |
| 1078 | - | ||
| 1079 | - | // Dispatch decodes one event on wp_image_description_v1 and calls the registered handlers. | |
| 1080 | - | func (o *WpImageDescription) Dispatch(event *wl.Event) { | |
| 1081 | - | switch event.Opcode { | |
| 1082 | - | case 0: // failed | |
| 1083 | - | cause := event.Uint32() | |
| 1084 | - | msg := event.String() | |
| 1085 | - | ||
| 1086 | - | for i, handler := range o.handlersForFailed() { | |
| 1087 | - | _ = i | |
| 1088 | - | handler(cause, msg) | |
| 1089 | - | } | |
| 1090 | - | case 1: // ready | |
| 1091 | - | identity := event.Uint32() | |
| 1092 | - | ||
| 1093 | - | for i, handler := range o.handlersForReady() { | |
| 1094 | - | _ = i | |
| 1095 | - | handler(identity) | |
| 1096 | - | } | |
| 1097 | - | case 2: // ready2 | |
| 1098 | - | identityHi := event.Uint32() | |
| 1099 | - | identityLo := event.Uint32() | |
| 1100 | - | ||
| 1101 | - | for i, handler := range o.handlersForReady2() { | |
| 1102 | - | _ = i | |
| 1103 | - | handler(identityHi, identityLo) | |
| 1104 | - | } | |
| 1105 | - | default: | |
| 1106 | - | } | |
| 1107 | - | } | |
| 1108 | - | ||
| 1109 | - | // WpImageDescriptionInfoInterface is the protocol interface name. | |
| 1110 | - | const WpImageDescriptionInfoInterface = "wp_image_description_info_v1" | |
| 1111 | - | ||
| 1112 | - | // WpImageDescriptionInfo is the generated binding for wp_image_description_info_v1 version 3. | |
| 1113 | - | type WpImageDescriptionInfo struct { | |
| 1114 | - | wl.BaseProxy | |
| 1115 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 1116 | - | // handlers while another goroutine dispatches events. | |
| 1117 | - | handlersMu sync.Mutex | |
| 1118 | - | onDone []func() | |
| 1119 | - | onIccFile []func(icc *wl.OwnedFD, iccSize uint32) | |
| 1120 | - | onPrimaries []func(rX int32, rY int32, gX int32, gY int32, bX int32, bY int32, wX int32, wY int32) | |
| 1121 | - | onPrimariesNamed []func(primaries uint32) | |
| 1122 | - | onTfPower []func(eexp uint32) | |
| 1123 | - | onTfNamed []func(tf uint32) | |
| 1124 | - | onLuminances []func(minLum uint32, maxLum uint32, referenceLum uint32) | |
| 1125 | - | onTargetPrimaries []func(rX int32, rY int32, gX int32, gY int32, bX int32, bY int32, wX int32, wY int32) | |
| 1126 | - | onTargetLuminance []func(minLum uint32, maxLum uint32) | |
| 1127 | - | onTargetMaxCll []func(maxCll uint32) | |
| 1128 | - | onTargetMaxFall []func(maxFall uint32) | |
| 1129 | - | } | |
| 1130 | - | ||
| 1131 | - | // NewWpImageDescriptionInfo returns an unbound WpImageDescriptionInfo. | |
| 1132 | - | func NewWpImageDescriptionInfo(ctx *wl.Context) *WpImageDescriptionInfo { | |
| 1133 | - | obj := &WpImageDescriptionInfo{} | |
| 1134 | - | obj.SetContext(ctx) | |
| 1135 | - | ctx.Register(obj) | |
| 1136 | - | return obj | |
| 1137 | - | } | |
| 1138 | - | ||
| 1139 | - | // OnDone registers a handler for the done event. | |
| 1140 | - | // | |
| 1141 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1142 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1143 | - | func (o *WpImageDescriptionInfo) OnDone(handler func()) { | |
| 1144 | - | if handler == nil { | |
| 1145 | - | return | |
| 1146 | - | } | |
| 1147 | - | o.handlersMu.Lock() | |
| 1148 | - | defer o.handlersMu.Unlock() | |
| 1149 | - | o.onDone = append(o.onDone, handler) | |
| 1150 | - | } | |
| 1151 | - | ||
| 1152 | - | // handlersForDone returns the handlers registered for done, taken | |
| 1153 | - | // under the lock so a handler may register another handler while events are | |
| 1154 | - | // being dispatched. | |
| 1155 | - | func (o *WpImageDescriptionInfo) handlersForDone() []func() { | |
| 1156 | - | o.handlersMu.Lock() | |
| 1157 | - | defer o.handlersMu.Unlock() | |
| 1158 | - | return o.onDone | |
| 1159 | - | } | |
| 1160 | - | ||
| 1161 | - | // OnIccFile registers a handler for the icc_file event. | |
| 1162 | - | // | |
| 1163 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1164 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1165 | - | func (o *WpImageDescriptionInfo) OnIccFile(handler func(icc *wl.OwnedFD, iccSize uint32)) { | |
| 1166 | - | if handler == nil { | |
| 1167 | - | return | |
| 1168 | - | } | |
| 1169 | - | o.handlersMu.Lock() | |
| 1170 | - | defer o.handlersMu.Unlock() | |
| 1171 | - | o.onIccFile = append(o.onIccFile, handler) | |
| 1172 | - | } | |
| 1173 | - | ||
| 1174 | - | // handlersForIccFile returns the handlers registered for icc_file, taken | |
| 1175 | - | // under the lock so a handler may register another handler while events are | |
| 1176 | - | // being dispatched. | |
| 1177 | - | func (o *WpImageDescriptionInfo) handlersForIccFile() []func(icc *wl.OwnedFD, iccSize uint32) { | |
| 1178 | - | o.handlersMu.Lock() | |
| 1179 | - | defer o.handlersMu.Unlock() | |
| 1180 | - | return o.onIccFile | |
| 1181 | - | } | |
| 1182 | - | ||
| 1183 | - | // OnPrimaries registers a handler for the primaries event. | |
| 1184 | - | // | |
| 1185 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1186 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1187 | - | func (o *WpImageDescriptionInfo) OnPrimaries(handler func(rX int32, rY int32, gX int32, gY int32, bX int32, bY int32, wX int32, wY int32)) { | |
| 1188 | - | if handler == nil { | |
| 1189 | - | return | |
| 1190 | - | } | |
| 1191 | - | o.handlersMu.Lock() | |
| 1192 | - | defer o.handlersMu.Unlock() | |
| 1193 | - | o.onPrimaries = append(o.onPrimaries, handler) | |
| 1194 | - | } | |
| 1195 | - | ||
| 1196 | - | // handlersForPrimaries returns the handlers registered for primaries, taken | |
| 1197 | - | // under the lock so a handler may register another handler while events are | |
| 1198 | - | // being dispatched. | |
| 1199 | - | func (o *WpImageDescriptionInfo) handlersForPrimaries() []func(rX int32, rY int32, gX int32, gY int32, bX int32, bY int32, wX int32, wY int32) { | |
| 1200 | - | o.handlersMu.Lock() | |
| 1201 | - | defer o.handlersMu.Unlock() | |
| 1202 | - | return o.onPrimaries | |
| 1203 | - | } | |
| 1204 | - | ||
| 1205 | - | // OnPrimariesNamed registers a handler for the primaries_named event. | |
| 1206 | - | // | |
| 1207 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1208 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1209 | - | func (o *WpImageDescriptionInfo) OnPrimariesNamed(handler func(primaries uint32)) { | |
| 1210 | - | if handler == nil { | |
| 1211 | - | return | |
| 1212 | - | } | |
| 1213 | - | o.handlersMu.Lock() | |
| 1214 | - | defer o.handlersMu.Unlock() | |
| 1215 | - | o.onPrimariesNamed = append(o.onPrimariesNamed, handler) | |
| 1216 | - | } | |
| 1217 | - | ||
| 1218 | - | // handlersForPrimariesNamed returns the handlers registered for primaries_named, taken | |
| 1219 | - | // under the lock so a handler may register another handler while events are | |
| 1220 | - | // being dispatched. | |
| 1221 | - | func (o *WpImageDescriptionInfo) handlersForPrimariesNamed() []func(primaries uint32) { | |
| 1222 | - | o.handlersMu.Lock() | |
| 1223 | - | defer o.handlersMu.Unlock() | |
| 1224 | - | return o.onPrimariesNamed | |
| 1225 | - | } | |
| 1226 | - | ||
| 1227 | - | // OnTfPower registers a handler for the tf_power event. | |
| 1228 | - | // | |
| 1229 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1230 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1231 | - | func (o *WpImageDescriptionInfo) OnTfPower(handler func(eexp uint32)) { | |
| 1232 | - | if handler == nil { | |
| 1233 | - | return | |
| 1234 | - | } | |
| 1235 | - | o.handlersMu.Lock() | |
| 1236 | - | defer o.handlersMu.Unlock() | |
| 1237 | - | o.onTfPower = append(o.onTfPower, handler) | |
| 1238 | - | } | |
| 1239 | - | ||
| 1240 | - | // handlersForTfPower returns the handlers registered for tf_power, taken | |
| 1241 | - | // under the lock so a handler may register another handler while events are | |
| 1242 | - | // being dispatched. | |
| 1243 | - | func (o *WpImageDescriptionInfo) handlersForTfPower() []func(eexp uint32) { | |
| 1244 | - | o.handlersMu.Lock() | |
| 1245 | - | defer o.handlersMu.Unlock() | |
| 1246 | - | return o.onTfPower | |
| 1247 | - | } | |
| 1248 | - | ||
| 1249 | - | // OnTfNamed registers a handler for the tf_named event. | |
| 1250 | - | // | |
| 1251 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1252 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1253 | - | func (o *WpImageDescriptionInfo) OnTfNamed(handler func(tf uint32)) { | |
| 1254 | - | if handler == nil { | |
| 1255 | - | return | |
| 1256 | - | } | |
| 1257 | - | o.handlersMu.Lock() | |
| 1258 | - | defer o.handlersMu.Unlock() | |
| 1259 | - | o.onTfNamed = append(o.onTfNamed, handler) | |
| 1260 | - | } | |
| 1261 | - | ||
| 1262 | - | // handlersForTfNamed returns the handlers registered for tf_named, taken | |
| 1263 | - | // under the lock so a handler may register another handler while events are | |
| 1264 | - | // being dispatched. | |
| 1265 | - | func (o *WpImageDescriptionInfo) handlersForTfNamed() []func(tf uint32) { | |
| 1266 | - | o.handlersMu.Lock() | |
| 1267 | - | defer o.handlersMu.Unlock() | |
| 1268 | - | return o.onTfNamed | |
| 1269 | - | } | |
| 1270 | - | ||
| 1271 | - | // OnLuminances registers a handler for the luminances event. | |
| 1272 | - | // | |
| 1273 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1274 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1275 | - | func (o *WpImageDescriptionInfo) OnLuminances(handler func(minLum uint32, maxLum uint32, referenceLum uint32)) { | |
| 1276 | - | if handler == nil { | |
| 1277 | - | return | |
| 1278 | - | } | |
| 1279 | - | o.handlersMu.Lock() | |
| 1280 | - | defer o.handlersMu.Unlock() | |
| 1281 | - | o.onLuminances = append(o.onLuminances, handler) | |
| 1282 | - | } | |
| 1283 | - | ||
| 1284 | - | // handlersForLuminances returns the handlers registered for luminances, taken | |
| 1285 | - | // under the lock so a handler may register another handler while events are | |
| 1286 | - | // being dispatched. | |
| 1287 | - | func (o *WpImageDescriptionInfo) handlersForLuminances() []func(minLum uint32, maxLum uint32, referenceLum uint32) { | |
| 1288 | - | o.handlersMu.Lock() | |
| 1289 | - | defer o.handlersMu.Unlock() | |
| 1290 | - | return o.onLuminances | |
| 1291 | - | } | |
| 1292 | - | ||
| 1293 | - | // OnTargetPrimaries registers a handler for the target_primaries event. | |
| 1294 | - | // | |
| 1295 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1296 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1297 | - | func (o *WpImageDescriptionInfo) OnTargetPrimaries(handler func(rX int32, rY int32, gX int32, gY int32, bX int32, bY int32, wX int32, wY int32)) { | |
| 1298 | - | if handler == nil { | |
| 1299 | - | return | |
| 1300 | - | } | |
| 1301 | - | o.handlersMu.Lock() | |
| 1302 | - | defer o.handlersMu.Unlock() | |
| 1303 | - | o.onTargetPrimaries = append(o.onTargetPrimaries, handler) | |
| 1304 | - | } | |
| 1305 | - | ||
| 1306 | - | // handlersForTargetPrimaries returns the handlers registered for target_primaries, taken | |
| 1307 | - | // under the lock so a handler may register another handler while events are | |
| 1308 | - | // being dispatched. | |
| 1309 | - | func (o *WpImageDescriptionInfo) handlersForTargetPrimaries() []func(rX int32, rY int32, gX int32, gY int32, bX int32, bY int32, wX int32, wY int32) { | |
| 1310 | - | o.handlersMu.Lock() | |
| 1311 | - | defer o.handlersMu.Unlock() | |
| 1312 | - | return o.onTargetPrimaries | |
| 1313 | - | } | |
| 1314 | - | ||
| 1315 | - | // OnTargetLuminance registers a handler for the target_luminance event. | |
| 1316 | - | // | |
| 1317 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1318 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1319 | - | func (o *WpImageDescriptionInfo) OnTargetLuminance(handler func(minLum uint32, maxLum uint32)) { | |
| 1320 | - | if handler == nil { | |
| 1321 | - | return | |
| 1322 | - | } | |
| 1323 | - | o.handlersMu.Lock() | |
| 1324 | - | defer o.handlersMu.Unlock() | |
| 1325 | - | o.onTargetLuminance = append(o.onTargetLuminance, handler) | |
| 1326 | - | } | |
| 1327 | - | ||
| 1328 | - | // handlersForTargetLuminance returns the handlers registered for target_luminance, taken | |
| 1329 | - | // under the lock so a handler may register another handler while events are | |
| 1330 | - | // being dispatched. | |
| 1331 | - | func (o *WpImageDescriptionInfo) handlersForTargetLuminance() []func(minLum uint32, maxLum uint32) { | |
| 1332 | - | o.handlersMu.Lock() | |
| 1333 | - | defer o.handlersMu.Unlock() | |
| 1334 | - | return o.onTargetLuminance | |
| 1335 | - | } | |
| 1336 | - | ||
| 1337 | - | // OnTargetMaxCll registers a handler for the target_max_cll event. | |
| 1338 | - | // | |
| 1339 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1340 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1341 | - | func (o *WpImageDescriptionInfo) OnTargetMaxCll(handler func(maxCll uint32)) { | |
| 1342 | - | if handler == nil { | |
| 1343 | - | return | |
| 1344 | - | } | |
| 1345 | - | o.handlersMu.Lock() | |
| 1346 | - | defer o.handlersMu.Unlock() | |
| 1347 | - | o.onTargetMaxCll = append(o.onTargetMaxCll, handler) | |
| 1348 | - | } | |
| 1349 | - | ||
| 1350 | - | // handlersForTargetMaxCll returns the handlers registered for target_max_cll, taken | |
| 1351 | - | // under the lock so a handler may register another handler while events are | |
| 1352 | - | // being dispatched. | |
| 1353 | - | func (o *WpImageDescriptionInfo) handlersForTargetMaxCll() []func(maxCll uint32) { | |
| 1354 | - | o.handlersMu.Lock() | |
| 1355 | - | defer o.handlersMu.Unlock() | |
| 1356 | - | return o.onTargetMaxCll | |
| 1357 | - | } | |
| 1358 | - | ||
| 1359 | - | // OnTargetMaxFall registers a handler for the target_max_fall event. | |
| 1360 | - | // | |
| 1361 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 1362 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 1363 | - | func (o *WpImageDescriptionInfo) OnTargetMaxFall(handler func(maxFall uint32)) { | |
| 1364 | - | if handler == nil { | |
| 1365 | - | return | |
| 1366 | - | } | |
| 1367 | - | o.handlersMu.Lock() | |
| 1368 | - | defer o.handlersMu.Unlock() | |
| 1369 | - | o.onTargetMaxFall = append(o.onTargetMaxFall, handler) | |
| 1370 | - | } | |
| 1371 | - | ||
| 1372 | - | // handlersForTargetMaxFall returns the handlers registered for target_max_fall, taken | |
| 1373 | - | // under the lock so a handler may register another handler while events are | |
| 1374 | - | // being dispatched. | |
| 1375 | - | func (o *WpImageDescriptionInfo) handlersForTargetMaxFall() []func(maxFall uint32) { | |
| 1376 | - | o.handlersMu.Lock() | |
| 1377 | - | defer o.handlersMu.Unlock() | |
| 1378 | - | return o.onTargetMaxFall | |
| 1379 | - | } | |
| 1380 | - | ||
| 1381 | - | // EventSignature returns the declared event argument types in wire order. | |
| 1382 | - | func (o *WpImageDescriptionInfo) EventSignature(opcode uint16) (string, bool) { | |
| 1383 | - | switch opcode { | |
| 1384 | - | case 0: | |
| 1385 | - | return "", true | |
| 1386 | - | case 1: | |
| 1387 | - | return "fd,uint,", true | |
| 1388 | - | case 2: | |
| 1389 | - | return "int,int,int,int,int,int,int,int,", true | |
| 1390 | - | case 3: | |
| 1391 | - | return "uint,", true | |
| 1392 | - | case 4: | |
| 1393 | - | return "uint,", true | |
| 1394 | - | case 5: | |
| 1395 | - | return "uint,", true | |
| 1396 | - | case 6: | |
| 1397 | - | return "uint,uint,uint,", true | |
| 1398 | - | case 7: | |
| 1399 | - | return "int,int,int,int,int,int,int,int,", true | |
| 1400 | - | case 8: | |
| 1401 | - | return "uint,uint,", true | |
| 1402 | - | case 9: | |
| 1403 | - | return "uint,", true | |
| 1404 | - | case 10: | |
| 1405 | - | return "uint,", true | |
| 1406 | - | default: | |
| 1407 | - | return "", false | |
| 1408 | - | } | |
| 1409 | - | } | |
| 1410 | - | ||
| 1411 | - | // Dispatch decodes one event on wp_image_description_info_v1 and calls the registered handlers. | |
| 1412 | - | func (o *WpImageDescriptionInfo) Dispatch(event *wl.Event) { | |
| 1413 | - | switch event.Opcode { | |
| 1414 | - | case 0: // done | |
| 1415 | - | ||
| 1416 | - | for i, handler := range o.handlersForDone() { | |
| 1417 | - | _ = i | |
| 1418 | - | handler() | |
| 1419 | - | } | |
| 1420 | - | o.Context().Unregister(o) | |
| 1421 | - | case 1: // icc_file | |
| 1422 | - | icc := event.FD() | |
| 1423 | - | iccSize := event.Uint32() | |
| 1424 | - | ownedicc := icc | |
| 1425 | - | defer ownedicc.Close() | |
| 1426 | - | ||
| 1427 | - | for i, handler := range o.handlersForIccFile() { | |
| 1428 | - | if i > 0 { | |
| 1429 | - | icc = nil | |
| 1430 | - | } | |
| 1431 | - | handler(icc, iccSize) | |
| 1432 | - | } | |
| 1433 | - | case 2: // primaries | |
| 1434 | - | rX := event.Int32() | |
| 1435 | - | rY := event.Int32() | |
| 1436 | - | gX := event.Int32() | |
| 1437 | - | gY := event.Int32() | |
| 1438 | - | bX := event.Int32() | |
| 1439 | - | bY := event.Int32() | |
| 1440 | - | wX := event.Int32() | |
| 1441 | - | wY := event.Int32() | |
| 1442 | - | ||
| 1443 | - | for i, handler := range o.handlersForPrimaries() { | |
| 1444 | - | _ = i | |
| 1445 | - | handler(rX, rY, gX, gY, bX, bY, wX, wY) | |
| 1446 | - | } | |
| 1447 | - | case 3: // primaries_named | |
| 1448 | - | primaries := event.Uint32() | |
| 1449 | - | ||
| 1450 | - | for i, handler := range o.handlersForPrimariesNamed() { | |
| 1451 | - | _ = i | |
| 1452 | - | handler(primaries) | |
| 1453 | - | } | |
| 1454 | - | case 4: // tf_power | |
| 1455 | - | eexp := event.Uint32() | |
| 1456 | - | ||
| 1457 | - | for i, handler := range o.handlersForTfPower() { | |
| 1458 | - | _ = i | |
| 1459 | - | handler(eexp) | |
| 1460 | - | } | |
| 1461 | - | case 5: // tf_named | |
| 1462 | - | tf := event.Uint32() | |
| 1463 | - | ||
| 1464 | - | for i, handler := range o.handlersForTfNamed() { | |
| 1465 | - | _ = i | |
| 1466 | - | handler(tf) | |
| 1467 | - | } | |
| 1468 | - | case 6: // luminances | |
| 1469 | - | minLum := event.Uint32() | |
| 1470 | - | maxLum := event.Uint32() | |
| 1471 | - | referenceLum := event.Uint32() | |
| 1472 | - | ||
| 1473 | - | for i, handler := range o.handlersForLuminances() { | |
| 1474 | - | _ = i | |
| 1475 | - | handler(minLum, maxLum, referenceLum) | |
| 1476 | - | } | |
| 1477 | - | case 7: // target_primaries | |
| 1478 | - | rX := event.Int32() | |
| 1479 | - | rY := event.Int32() | |
| 1480 | - | gX := event.Int32() | |
| 1481 | - | gY := event.Int32() | |
| 1482 | - | bX := event.Int32() | |
| 1483 | - | bY := event.Int32() | |
| 1484 | - | wX := event.Int32() | |
| 1485 | - | wY := event.Int32() | |
| 1486 | - | ||
| 1487 | - | for i, handler := range o.handlersForTargetPrimaries() { | |
| 1488 | - | _ = i | |
| 1489 | - | handler(rX, rY, gX, gY, bX, bY, wX, wY) | |
| 1490 | - | } | |
| 1491 | - | case 8: // target_luminance | |
| 1492 | - | minLum := event.Uint32() | |
| 1493 | - | maxLum := event.Uint32() | |
| 1494 | - | ||
| 1495 | - | for i, handler := range o.handlersForTargetLuminance() { | |
| 1496 | - | _ = i | |
| 1497 | - | handler(minLum, maxLum) | |
| 1498 | - | } | |
| 1499 | - | case 9: // target_max_cll | |
| 1500 | - | maxCll := event.Uint32() | |
| 1501 | - | ||
| 1502 | - | for i, handler := range o.handlersForTargetMaxCll() { | |
| 1503 | - | _ = i | |
| 1504 | - | handler(maxCll) | |
| 1505 | - | } | |
| 1506 | - | case 10: // target_max_fall | |
| 1507 | - | maxFall := event.Uint32() | |
| 1508 | - | ||
| 1509 | - | for i, handler := range o.handlersForTargetMaxFall() { | |
| 1510 | - | _ = i | |
| 1511 | - | handler(maxFall) | |
| 1512 | - | } | |
| 1513 | - | default: | |
| 1514 | - | } | |
| 1515 | - | } | |
| 1516 | - | ||
| 1517 | - | // WpImageDescriptionReferenceInterface is the protocol interface name. | |
| 1518 | - | const WpImageDescriptionReferenceInterface = "wp_image_description_reference_v1" | |
| 1519 | - | ||
| 1520 | - | // WpImageDescriptionReference is the generated binding for wp_image_description_reference_v1 version 1. | |
| 1521 | - | type WpImageDescriptionReference struct { | |
| 1522 | - | wl.BaseProxy | |
| 1523 | - | } | |
| 1524 | - | ||
| 1525 | - | // NewWpImageDescriptionReference returns an unbound WpImageDescriptionReference. | |
| 1526 | - | func NewWpImageDescriptionReference(ctx *wl.Context) *WpImageDescriptionReference { | |
| 1527 | - | obj := &WpImageDescriptionReference{} | |
| 1528 | - | obj.SetContext(ctx) | |
| 1529 | - | ctx.Register(obj) | |
| 1530 | - | return obj | |
| 1531 | - | } | |
| 1532 | - | ||
| 1533 | - | // Destroy this object. This has no effect on the referenced image description. | |
| 1534 | - | func (o *WpImageDescriptionReference) Destroy() error { | |
| 1535 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_image_description_reference_v1.destroy", Destructor: true}); err != nil { | |
| 1536 | - | return err | |
| 1537 | - | } | |
| 1538 | - | return nil | |
| 1539 | - | } | |
| 1540 | - | ||
| 1541 | - | // EventSignature returns the declared event argument types in wire order. | |
| 1542 | - | func (o *WpImageDescriptionReference) EventSignature(opcode uint16) (string, bool) { | |
| 1543 | - | switch opcode { | |
| 1544 | - | default: | |
| 1545 | - | return "", false | |
| 1546 | - | } | |
| 1547 | - | } | |
| 1548 | - | ||
| 1549 | - | // Dispatch decodes one event on wp_image_description_reference_v1 and calls the registered handlers. | |
| 1550 | - | func (o *WpImageDescriptionReference) Dispatch(event *wl.Event) { | |
| 1551 | - | switch event.Opcode { | |
| 1552 | - | default: | |
| 1553 | - | } | |
| 1554 | - | } | |
D protocol/colormanagement/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package colormanagement | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p colormanagement -o color-management-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_output=github.com/bnema/wlturbo/protocol/core color-management-v1.xml | |
D protocol/colorrepresentation/color-representation-v1.xml +0 -433
| @@ -1,433 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="color_representation_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright 2022 Simon Ser | |
| 5 | - | Copyright 2022 Red Hat, Inc. | |
| 6 | - | Copyright 2022 Collabora, Ltd. | |
| 7 | - | Copyright 2022-2025 Red Hat, Inc. | |
| 8 | - | ||
| 9 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 | - | copy of this software and associated documentation files (the "Software"), | |
| 11 | - | to deal in the Software without restriction, including without limitation | |
| 12 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 14 | - | Software is furnished to do so, subject to the following conditions: | |
| 15 | - | ||
| 16 | - | The above copyright notice and this permission notice (including the next | |
| 17 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 18 | - | Software. | |
| 19 | - | ||
| 20 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 23 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 25 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 26 | - | DEALINGS IN THE SOFTWARE. | |
| 27 | - | </copyright> | |
| 28 | - | ||
| 29 | - | <description summary="color representation protocol extension"> | |
| 30 | - | This protocol extension delivers the metadata required to define alpha mode, | |
| 31 | - | the color model, sub-sampling and quantization range used when interpreting | |
| 32 | - | buffer contents. The main use case is defining how the YCbCr family of pixel | |
| 33 | - | formats convert to RGB. | |
| 34 | - | ||
| 35 | - | Note that this protocol does not define the colorimetry of the resulting RGB | |
| 36 | - | channels / tristimulus values. Without the help of other extensions the | |
| 37 | - | resulting colorimetry is therefore implementation defined. | |
| 38 | - | ||
| 39 | - | If this extension is not used, the color representation used is compositor | |
| 40 | - | implementation defined. | |
| 41 | - | ||
| 42 | - | Recommendation ITU-T H.273 | |
| 43 | - | "Coding-independent code points for video signal type identification" | |
| 44 | - | shall be referred to as simply H.273 here. | |
| 45 | - | </description> | |
| 46 | - | ||
| 47 | - | <interface name="wp_color_representation_manager_v1" version="1"> | |
| 48 | - | <description summary="color representation manager singleton"> | |
| 49 | - | A singleton global interface used for getting color representation | |
| 50 | - | extensions for wl_surface. The extension interfaces allow setting the | |
| 51 | - | color representation of surfaces. | |
| 52 | - | ||
| 53 | - | Compositors should never remove this global. | |
| 54 | - | </description> | |
| 55 | - | ||
| 56 | - | <enum name="error"> | |
| 57 | - | <description summary="protocol errors"/> | |
| 58 | - | <entry name="surface_exists" value="1" | |
| 59 | - | summary="color representation surface exists already"/> | |
| 60 | - | </enum> | |
| 61 | - | ||
| 62 | - | <request name="destroy" type="destructor"> | |
| 63 | - | <description summary="destroy the manager"> | |
| 64 | - | Destroy the wp_color_representation_manager_v1 object. This does not | |
| 65 | - | affect any other objects in any way. | |
| 66 | - | </description> | |
| 67 | - | ||
| 68 | - | </request> | |
| 69 | - | ||
| 70 | - | <request name="get_surface"> | |
| 71 | - | <description summary="create a color representation interface for a wl_surface"> | |
| 72 | - | If a wp_color_representation_surface_v1 object already exists for the | |
| 73 | - | given wl_surface, the protocol error surface_exists is raised. | |
| 74 | - | ||
| 75 | - | This creates a new color wp_color_representation_surface_v1 object for | |
| 76 | - | the given wl_surface. | |
| 77 | - | ||
| 78 | - | See the wp_color_representation_surface_v1 interface for more details. | |
| 79 | - | </description> | |
| 80 | - | <arg name="id" | |
| 81 | - | type="new_id" interface="wp_color_representation_surface_v1"/> | |
| 82 | - | <arg name="surface" | |
| 83 | - | type="object" interface="wl_surface"/> | |
| 84 | - | </request> | |
| 85 | - | ||
| 86 | - | <event name="supported_alpha_mode"> | |
| 87 | - | <description summary="supported alpha modes"> | |
| 88 | - | When this object is created, it shall immediately send this event once | |
| 89 | - | for each alpha mode the compositor supports. | |
| 90 | - | ||
| 91 | - | For the definition of the supported values, see the | |
| 92 | - | wp_color_representation_surface_v1::alpha_mode enum. | |
| 93 | - | </description> | |
| 94 | - | <arg name="alpha_mode" | |
| 95 | - | type="uint" enum="wp_color_representation_surface_v1.alpha_mode" | |
| 96 | - | summary="supported alpha mode"/> | |
| 97 | - | </event> | |
| 98 | - | ||
| 99 | - | <event name="supported_coefficients_and_ranges"> | |
| 100 | - | <description summary="supported matrix coefficients and ranges"> | |
| 101 | - | When this object is created, it shall immediately send this event once | |
| 102 | - | for each matrix coefficient and color range combination the compositor | |
| 103 | - | supports. | |
| 104 | - | ||
| 105 | - | For the definition of the supported values, see the | |
| 106 | - | wp_color_representation_surface_v1::coefficients and | |
| 107 | - | wp_color_representation_surface_v1::range enums. | |
| 108 | - | </description> | |
| 109 | - | <arg name="coefficients" | |
| 110 | - | type="uint" enum="wp_color_representation_surface_v1.coefficients" | |
| 111 | - | summary="supported matrix coefficients"/> | |
| 112 | - | <arg name="range" | |
| 113 | - | type="uint" enum="wp_color_representation_surface_v1.range" | |
| 114 | - | summary="full range flag"/> | |
| 115 | - | </event> | |
| 116 | - | ||
| 117 | - | <event name="done"> | |
| 118 | - | <description summary="all features have been sent"> | |
| 119 | - | This event is sent when all supported features have been sent. | |
| 120 | - | </description> | |
| 121 | - | </event> | |
| 122 | - | </interface> | |
| 123 | - | ||
| 124 | - | <interface name="wp_color_representation_surface_v1" version="1"> | |
| 125 | - | <description summary="color representation extension to a surface"> | |
| 126 | - | A wp_color_representation_surface_v1 allows the client to set the color | |
| 127 | - | representation metadata of a surface. | |
| 128 | - | ||
| 129 | - | By default, a surface does not have any color representation metadata set. | |
| 130 | - | The reconstruction of R, G, B signals on such surfaces is compositor | |
| 131 | - | implementation defined. The alpha mode is assumed to be | |
| 132 | - | premultiplied_electrical when the alpha mode is unset. | |
| 133 | - | ||
| 134 | - | If the wl_surface associated with the wp_color_representation_surface_v1 | |
| 135 | - | is destroyed, the wp_color_representation_surface_v1 object becomes inert. | |
| 136 | - | </description> | |
| 137 | - | ||
| 138 | - | <enum name="error"> | |
| 139 | - | <description summary="protocol errors"/> | |
| 140 | - | <entry name="alpha_mode" value="1" | |
| 141 | - | summary="unsupported alpha mode"/> | |
| 142 | - | <entry name="coefficients" value="2" | |
| 143 | - | summary="unsupported coefficients"/> | |
| 144 | - | <entry name="pixel_format" value="3" | |
| 145 | - | summary="the pixel format and a set value are incompatible"/> | |
| 146 | - | <entry name="inert" value="4" | |
| 147 | - | summary="forbidden request on inert object"/> | |
| 148 | - | <entry name="chroma_location" value="5" | |
| 149 | - | summary="invalid chroma location"/> | |
| 150 | - | </enum> | |
| 151 | - | ||
| 152 | - | <request name="destroy" type="destructor"> | |
| 153 | - | <description summary="destroy the color representation"> | |
| 154 | - | Destroy the wp_color_representation_surface_v1 object. | |
| 155 | - | ||
| 156 | - | Destroying this object unsets all the color representation metadata from | |
| 157 | - | the surface. See the wp_color_representation_surface_v1 interface | |
| 158 | - | description for how a compositor handles a surface without color | |
| 159 | - | representation metadata. Unsetting is double-buffered state, see | |
| 160 | - | wl_surface.commit. | |
| 161 | - | </description> | |
| 162 | - | </request> | |
| 163 | - | ||
| 164 | - | <enum name="alpha_mode"> | |
| 165 | - | <description summary="alpha mode"> | |
| 166 | - | Specifies how the alpha channel affects the color channels. | |
| 167 | - | </description> | |
| 168 | - | <entry name="premultiplied_electrical" value="0"> | |
| 169 | - | <description summary="premultiplied alpha in electrical values"> | |
| 170 | - | Electrical color channel values (after transfer function encoding) | |
| 171 | - | are already multiplied with the alpha channel value. | |
| 172 | - | </description> | |
| 173 | - | </entry> | |
| 174 | - | <entry name="premultiplied_optical" value="1"> | |
| 175 | - | <description summary="premultiplied alpha in optical values"> | |
| 176 | - | Optical color channel values (before transfer function encoding) | |
| 177 | - | are already multiplied with the alpha channel value. | |
| 178 | - | </description> | |
| 179 | - | </entry> | |
| 180 | - | <entry name="straight" value="2"> | |
| 181 | - | <description summary="straight alpha"> | |
| 182 | - | Alpha channel has not been pre-multiplied into color channels. | |
| 183 | - | </description> | |
| 184 | - | </entry> | |
| 185 | - | </enum> | |
| 186 | - | ||
| 187 | - | <enum name="coefficients"> | |
| 188 | - | <description summary="named coefficients"> | |
| 189 | - | Named matrix coefficients used to encode well-known sets of | |
| 190 | - | coefficients. H.273 is the authority, when it comes to the exact values | |
| 191 | - | of coefficients and authoritative specifications, where an equivalent | |
| 192 | - | code point exists. | |
| 193 | - | ||
| 194 | - | A value of 0 is invalid and will never be present in the list of enums. | |
| 195 | - | ||
| 196 | - | Descriptions do list the specifications for convenience. | |
| 197 | - | </description> | |
| 198 | - | <entry name="identity" value="1"> | |
| 199 | - | <description summary="The identity matrix"> | |
| 200 | - | Coefficients as defined by | |
| 201 | - | - IEC 61966-2-1 sRGB | |
| 202 | - | - SMPTE ST 428-1 (2019) | |
| 203 | - | ||
| 204 | - | Equivalent to H.273 MatrixCoefficients code point 0. | |
| 205 | - | Compatible with pixel formats of the RGB family. | |
| 206 | - | </description> | |
| 207 | - | </entry> | |
| 208 | - | <entry name="bt709" value="2"> | |
| 209 | - | <description summary="BT.709 matrix coefficients"> | |
| 210 | - | Coefficients as defined by | |
| 211 | - | - Rec. ITU-R BT.709-6 | |
| 212 | - | - Rec. ITU-R BT.1361-0 conventional colour gamut system (historical) | |
| 213 | - | - Rec. ITU-R BT.1361-0 conventional colour gamut system and extended | |
| 214 | - | colour gamut system (historical) | |
| 215 | - | - IEC 61966-2-4 xvYCC709 | |
| 216 | - | - SMPTE RP 177 (1993) Annex B | |
| 217 | - | ||
| 218 | - | Equivalent to H.273 MatrixCoefficients code point 1. | |
| 219 | - | Compatible with pixel formats of the YCbCr family. | |
| 220 | - | </description> | |
| 221 | - | </entry> | |
| 222 | - | <entry name="fcc" value="3"> | |
| 223 | - | <description summary="FCC matrix coefficients"> | |
| 224 | - | Coefficients as defined by | |
| 225 | - | - United States Federal Communications Commission (2003) Title 47 | |
| 226 | - | Code of Federal Regulations 73.682 (a) (20) | |
| 227 | - | ||
| 228 | - | Equivalent to H.273 MatrixCoefficients code point 4. | |
| 229 | - | Compatible with pixel formats of the YCbCr family. | |
| 230 | - | </description> | |
| 231 | - | </entry> | |
| 232 | - | <entry name="bt601" value="4"> | |
| 233 | - | <description summary="BT.601-7 matrix coefficients"> | |
| 234 | - | Coefficients as defined by | |
| 235 | - | - Rec. ITU-R BT.470-6 System B, G (historical) | |
| 236 | - | - Rec. ITU-R BT.601-7 625 | |
| 237 | - | - Rec. ITU-R BT.601-7 525 | |
| 238 | - | - Rec. ITU-R BT.1358-0 625 (historical) | |
| 239 | - | - Rec. ITU-R BT.1358-1 525 or 625 (historical) | |
| 240 | - | - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM | |
| 241 | - | - Rec. ITU-R BT.1700-0 NTSC | |
| 242 | - | - IEC 61966-2-1 sYCC | |
| 243 | - | - IEC 61966-2-4 xvYCC601 | |
| 244 | - | - SMPTE ST 170 (2004) | |
| 245 | - | ||
| 246 | - | Equivalent to H.273 MatrixCoefficients code point 5, 6. | |
| 247 | - | Compatible with pixel formats of the YCbCr family. | |
| 248 | - | </description> | |
| 249 | - | </entry> | |
| 250 | - | <entry name="smpte240" value="5"> | |
| 251 | - | <description summary="SMPTE ST 240 matrix coefficients"> | |
| 252 | - | Coefficients as defined by | |
| 253 | - | - SMPTE ST 240 (1999) | |
| 254 | - | ||
| 255 | - | Equivalent to H.273 MatrixCoefficients code point 7. | |
| 256 | - | Compatible with pixel formats of the YCbCr family. | |
| 257 | - | </description> | |
| 258 | - | </entry> | |
| 259 | - | <entry name="bt2020" value="6"> | |
| 260 | - | <description summary="BT.2020 and BT.2100 YCbCr matrix coefficients"> | |
| 261 | - | Coefficients as defined by | |
| 262 | - | - Rec. ITU-R BT.2020-2 (non-constant luminance) | |
| 263 | - | - Rec. ITU-R BT.2100-2 Y′CbCr | |
| 264 | - | ||
| 265 | - | Equivalent to H.273 MatrixCoefficients code point 9. | |
| 266 | - | Compatible with pixel formats of the YCbCr family. | |
| 267 | - | </description> | |
| 268 | - | </entry> | |
| 269 | - | <entry name="bt2020_cl" value="7"> | |
| 270 | - | <description summary="BT.2020 matrix coefficients for constant luminance"> | |
| 271 | - | Coefficients as defined by | |
| 272 | - | - Rec. ITU-R BT.2020-2 (constant luminance) | |
| 273 | - | ||
| 274 | - | Equivalent to H.273 MatrixCoefficients code point 10. | |
| 275 | - | Compatible with pixel formats of the YCbCr family. | |
| 276 | - | </description> | |
| 277 | - | </entry> | |
| 278 | - | <entry name="ictcp" value="8"> | |
| 279 | - | <description summary="BT.2100 ICtCp matrix coefficients"> | |
| 280 | - | Coefficients as defined by | |
| 281 | - | - Rec. ITU-R BT.2100-2 ICTCP | |
| 282 | - | ||
| 283 | - | Equivalent to H.273 MatrixCoefficients code point 14. | |
| 284 | - | Compatible with pixel formats of the YCbCr family. | |
| 285 | - | </description> | |
| 286 | - | </entry> | |
| 287 | - | </enum> | |
| 288 | - | ||
| 289 | - | <enum name="range"> | |
| 290 | - | <description summary="Color range values"> | |
| 291 | - | Possible color range values. | |
| 292 | - | ||
| 293 | - | A value of 0 is invalid and will never be present in the list of enums. | |
| 294 | - | </description> | |
| 295 | - | <entry name="full" value="1" summary="Full color range"/> | |
| 296 | - | <entry name="limited" value="2" summary="Limited color range"/> | |
| 297 | - | </enum> | |
| 298 | - | ||
| 299 | - | <enum name="chroma_location"> | |
| 300 | - | <description summary="Chroma sample location for 4:2:0 YCbCr"> | |
| 301 | - | Chroma sample location as defined by H.273 Chroma420SampleLocType. | |
| 302 | - | ||
| 303 | - | A value of 0 is invalid and will never be present in the list of enums. | |
| 304 | - | ||
| 305 | - | The descriptions list the matching Vulkan VkChromaLocation combinations | |
| 306 | - | for convenience. | |
| 307 | - | </description> | |
| 308 | - | <entry name="type_0" value="1"> | |
| 309 | - | <description summary="Horizontal offset of 0, vertical offset of 0.5"> | |
| 310 | - | Corresponding to VkChromaLocations: | |
| 311 | - | - xChromaOffset: VK_CHROMA_LOCATION_COSITED_EVEN | |
| 312 | - | - yChromaOffset: VK_CHROMA_LOCATION_MIDPOINT | |
| 313 | - | ||
| 314 | - | Equivalent to H.273 Chroma420SampleLocType 0. | |
| 315 | - | </description> | |
| 316 | - | </entry> | |
| 317 | - | <entry name="type_1" value="2"> | |
| 318 | - | <description summary="Horizontal offset of 0.5, vertical offset of 0.5"> | |
| 319 | - | Corresponding to VkChromaLocations: | |
| 320 | - | - xChromaOffset: VK_CHROMA_LOCATION_MIDPOINT | |
| 321 | - | - yChromaOffset: VK_CHROMA_LOCATION_MIDPOINT | |
| 322 | - | ||
| 323 | - | Equivalent to H.273 Chroma420SampleLocType 1. | |
| 324 | - | </description> | |
| 325 | - | </entry> | |
| 326 | - | <entry name="type_2" value="3"> | |
| 327 | - | <description summary="Horizontal offset of 0, vertical offset of 0"> | |
| 328 | - | Corresponding to VkChromaLocations: | |
| 329 | - | - xChromaOffset: VK_CHROMA_LOCATION_COSITED_EVEN | |
| 330 | - | - yChromaOffset: VK_CHROMA_LOCATION_COSITED_EVEN | |
| 331 | - | ||
| 332 | - | Equivalent to H.273 Chroma420SampleLocType 2. | |
| 333 | - | </description> | |
| 334 | - | </entry> | |
| 335 | - | <entry name="type_3" value="4"> | |
| 336 | - | <description summary="Horizontal offset of 0.5, vertical offset of 0"> | |
| 337 | - | Corresponding to VkChromaLocations: | |
| 338 | - | - xChromaOffset: VK_CHROMA_LOCATION_MIDPOINT | |
| 339 | - | - yChromaOffset: VK_CHROMA_LOCATION_COSITED_EVEN | |
| 340 | - | ||
| 341 | - | Equivalent to H.273 Chroma420SampleLocType 3. | |
| 342 | - | </description> | |
| 343 | - | </entry> | |
| 344 | - | <entry name="type_4" value="5"> | |
| 345 | - | <description summary="Horizontal offset of 0, vertical offset of 1"> | |
| 346 | - | Equivalent to H.273 Chroma420SampleLocType 4. | |
| 347 | - | </description> | |
| 348 | - | </entry> | |
| 349 | - | <entry name="type_5" value="6"> | |
| 350 | - | <description summary="Horizontal offset of 0.5, vertical offset of 1"> | |
| 351 | - | Equivalent to H.273 Chroma420SampleLocType 5. | |
| 352 | - | </description> | |
| 353 | - | </entry> | |
| 354 | - | </enum> | |
| 355 | - | ||
| 356 | - | <request name="set_alpha_mode"> | |
| 357 | - | <description summary="set the surface alpha mode"> | |
| 358 | - | If this protocol object is inert, the protocol error inert is raised. | |
| 359 | - | ||
| 360 | - | Assuming an alpha channel exists, it is always linear. The alpha mode | |
| 361 | - | determines whether and how the color channels include pre-multiplied | |
| 362 | - | alpha. Using straight alpha might have performance benefits. | |
| 363 | - | ||
| 364 | - | Only alpha modes advertised by the compositor are allowed to be used as | |
| 365 | - | argument for this request. The "alpha_mode" protocol error is raised | |
| 366 | - | otherwise. | |
| 367 | - | ||
| 368 | - | Alpha mode is double buffered, see wl_surface.commit. | |
| 369 | - | </description> | |
| 370 | - | <arg name="alpha_mode" type="uint" enum="alpha_mode" | |
| 371 | - | summary="alpha mode"/> | |
| 372 | - | </request> | |
| 373 | - | ||
| 374 | - | <request name="set_coefficients_and_range"> | |
| 375 | - | <description summary="set the matrix coefficients and range"> | |
| 376 | - | If this protocol object is inert, the protocol error inert is raised. | |
| 377 | - | ||
| 378 | - | Set the matrix coefficients and video range which defines the formula | |
| 379 | - | and the related constants used to derive red, green and blue signals. | |
| 380 | - | Usually coefficients correspond to MatrixCoefficients code points in | |
| 381 | - | H.273. | |
| 382 | - | ||
| 383 | - | Only combinations advertised by the compositor are allowed to be used as | |
| 384 | - | argument for this request. The "coefficients" protocol error is raised | |
| 385 | - | otherwise. | |
| 386 | - | ||
| 387 | - | A call to wl_surface.commit verifies that the pixel format and the | |
| 388 | - | coefficients-range combination in the committed surface contents are | |
| 389 | - | compatible, if contents exist. The "pixel_format" protocol error is | |
| 390 | - | raised otherwise. | |
| 391 | - | ||
| 392 | - | A pixel format is compatible with the coefficients-range combination if | |
| 393 | - | the related equations and conventions as defined in H.273 can produce | |
| 394 | - | the color channels (RGB or YCbCr) of the pixel format. | |
| 395 | - | ||
| 396 | - | For the definition of the supported combination, see the | |
| 397 | - | wp_color_representation_surface_v1::coefficients and | |
| 398 | - | wp_color_representation_surface_v1::range enums. | |
| 399 | - | ||
| 400 | - | The coefficients-range combination is double-buffered, see | |
| 401 | - | wl_surface.commit. | |
| 402 | - | </description> | |
| 403 | - | <arg name="coefficients" type="uint" enum="coefficients" | |
| 404 | - | summary="matrix coefficients"/> | |
| 405 | - | <arg name="range" type="uint" enum="range" | |
| 406 | - | summary="range"/> | |
| 407 | - | </request> | |
| 408 | - | ||
| 409 | - | <request name="set_chroma_location"> | |
| 410 | - | <description summary="set the chroma location"> | |
| 411 | - | If this protocol object is inert, the protocol error inert is raised. | |
| 412 | - | ||
| 413 | - | Set the chroma location type which defines the position of downsampled | |
| 414 | - | chroma samples, corresponding to Chroma420SampleLocType code points in | |
| 415 | - | H.273. | |
| 416 | - | ||
| 417 | - | An invalid chroma location enum value raises the "chroma_location" | |
| 418 | - | protocol error. | |
| 419 | - | ||
| 420 | - | A call to wl_surface.commit verifies that the pixel format and chroma | |
| 421 | - | location type in the committed surface contents are compatible, if | |
| 422 | - | contents exist. The "pixel_format" protocol error is raised otherwise. | |
| 423 | - | ||
| 424 | - | For the definition of the supported chroma location types, see the | |
| 425 | - | wp_color_representation_surface_v1::chroma_location enum. | |
| 426 | - | ||
| 427 | - | The chroma location type is double-buffered, see wl_surface.commit. | |
| 428 | - | </description> | |
| 429 | - | <arg name="chroma_location" type="uint" enum="chroma_location" | |
| 430 | - | summary="chroma sample location"/> | |
| 431 | - | </request> | |
| 432 | - | </interface> | |
| 433 | - | </protocol> | |
D protocol/colorrepresentation/color-representation-v1_generated.go +0 -327
| @@ -1,327 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: color_representation_v1 | |
| 3 | - | // Source: color-representation-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright 2022 Simon Ser | |
| 7 | - | // Copyright 2022 Red Hat, Inc. | |
| 8 | - | // Copyright 2022 Collabora, Ltd. | |
| 9 | - | // Copyright 2022-2025 Red Hat, Inc. | |
| 10 | - | // | |
| 11 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 12 | - | // copy of this software and associated documentation files (the "Software"), | |
| 13 | - | // to deal in the Software without restriction, including without limitation | |
| 14 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 15 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 16 | - | // Software is furnished to do so, subject to the following conditions: | |
| 17 | - | // | |
| 18 | - | // The above copyright notice and this permission notice (including the next | |
| 19 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 20 | - | // Software. | |
| 21 | - | // | |
| 22 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 23 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 24 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 25 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 26 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 27 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 28 | - | // DEALINGS IN THE SOFTWARE. | |
| 29 | - | ||
| 30 | - | package colorrepresentation | |
| 31 | - | ||
| 32 | - | import ( | |
| 33 | - | "sync" | |
| 34 | - | ||
| 35 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 36 | - | "github.com/bnema/wlturbo/wl" | |
| 37 | - | ) | |
| 38 | - | ||
| 39 | - | // ERROR_SURFACE_EXISTS is the error surface_exists value. | |
| 40 | - | const ERROR_SURFACE_EXISTS = 1 | |
| 41 | - | ||
| 42 | - | // ERROR_ALPHA_MODE is the error alpha_mode value. | |
| 43 | - | const ERROR_ALPHA_MODE = 1 | |
| 44 | - | ||
| 45 | - | // ERROR_COEFFICIENTS is the error coefficients value. | |
| 46 | - | const ERROR_COEFFICIENTS = 2 | |
| 47 | - | ||
| 48 | - | // ERROR_PIXEL_FORMAT is the error pixel_format value. | |
| 49 | - | const ERROR_PIXEL_FORMAT = 3 | |
| 50 | - | ||
| 51 | - | // ERROR_INERT is the error inert value. | |
| 52 | - | const ERROR_INERT = 4 | |
| 53 | - | ||
| 54 | - | // ERROR_CHROMA_LOCATION is the error chroma_location value. | |
| 55 | - | const ERROR_CHROMA_LOCATION = 5 | |
| 56 | - | ||
| 57 | - | // ALPHA_MODE_PREMULTIPLIED_ELECTRICAL is the alpha_mode premultiplied_electrical value. | |
| 58 | - | const ALPHA_MODE_PREMULTIPLIED_ELECTRICAL = 0 | |
| 59 | - | ||
| 60 | - | // ALPHA_MODE_PREMULTIPLIED_OPTICAL is the alpha_mode premultiplied_optical value. | |
| 61 | - | const ALPHA_MODE_PREMULTIPLIED_OPTICAL = 1 | |
| 62 | - | ||
| 63 | - | // ALPHA_MODE_STRAIGHT is the alpha_mode straight value. | |
| 64 | - | const ALPHA_MODE_STRAIGHT = 2 | |
| 65 | - | ||
| 66 | - | // COEFFICIENTS_IDENTITY is the coefficients identity value. | |
| 67 | - | const COEFFICIENTS_IDENTITY = 1 | |
| 68 | - | ||
| 69 | - | // COEFFICIENTS_BT709 is the coefficients bt709 value. | |
| 70 | - | const COEFFICIENTS_BT709 = 2 | |
| 71 | - | ||
| 72 | - | // COEFFICIENTS_FCC is the coefficients fcc value. | |
| 73 | - | const COEFFICIENTS_FCC = 3 | |
| 74 | - | ||
| 75 | - | // COEFFICIENTS_BT601 is the coefficients bt601 value. | |
| 76 | - | const COEFFICIENTS_BT601 = 4 | |
| 77 | - | ||
| 78 | - | // COEFFICIENTS_SMPTE240 is the coefficients smpte240 value. | |
| 79 | - | const COEFFICIENTS_SMPTE240 = 5 | |
| 80 | - | ||
| 81 | - | // COEFFICIENTS_BT2020 is the coefficients bt2020 value. | |
| 82 | - | const COEFFICIENTS_BT2020 = 6 | |
| 83 | - | ||
| 84 | - | // COEFFICIENTS_BT2020_CL is the coefficients bt2020_cl value. | |
| 85 | - | const COEFFICIENTS_BT2020_CL = 7 | |
| 86 | - | ||
| 87 | - | // COEFFICIENTS_ICTCP is the coefficients ictcp value. | |
| 88 | - | const COEFFICIENTS_ICTCP = 8 | |
| 89 | - | ||
| 90 | - | // RANGE_FULL is the range full value. | |
| 91 | - | const RANGE_FULL = 1 | |
| 92 | - | ||
| 93 | - | // RANGE_LIMITED is the range limited value. | |
| 94 | - | const RANGE_LIMITED = 2 | |
| 95 | - | ||
| 96 | - | // CHROMA_LOCATION_TYPE_0 is the chroma_location type_0 value. | |
| 97 | - | const CHROMA_LOCATION_TYPE_0 = 1 | |
| 98 | - | ||
| 99 | - | // CHROMA_LOCATION_TYPE_1 is the chroma_location type_1 value. | |
| 100 | - | const CHROMA_LOCATION_TYPE_1 = 2 | |
| 101 | - | ||
| 102 | - | // CHROMA_LOCATION_TYPE_2 is the chroma_location type_2 value. | |
| 103 | - | const CHROMA_LOCATION_TYPE_2 = 3 | |
| 104 | - | ||
| 105 | - | // CHROMA_LOCATION_TYPE_3 is the chroma_location type_3 value. | |
| 106 | - | const CHROMA_LOCATION_TYPE_3 = 4 | |
| 107 | - | ||
| 108 | - | // CHROMA_LOCATION_TYPE_4 is the chroma_location type_4 value. | |
| 109 | - | const CHROMA_LOCATION_TYPE_4 = 5 | |
| 110 | - | ||
| 111 | - | // CHROMA_LOCATION_TYPE_5 is the chroma_location type_5 value. | |
| 112 | - | const CHROMA_LOCATION_TYPE_5 = 6 | |
| 113 | - | ||
| 114 | - | // WpColorRepresentationManagerInterface is the protocol interface name. | |
| 115 | - | const WpColorRepresentationManagerInterface = "wp_color_representation_manager_v1" | |
| 116 | - | ||
| 117 | - | // WpColorRepresentationManager is the generated binding for wp_color_representation_manager_v1 version 1. | |
| 118 | - | type WpColorRepresentationManager struct { | |
| 119 | - | wl.BaseProxy | |
| 120 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 121 | - | // handlers while another goroutine dispatches events. | |
| 122 | - | handlersMu sync.Mutex | |
| 123 | - | onSupportedAlphaMode []func(alphaMode uint32) | |
| 124 | - | onSupportedCoefficientsAndRanges []func(coefficients uint32, rangeArg uint32) | |
| 125 | - | onDone []func() | |
| 126 | - | } | |
| 127 | - | ||
| 128 | - | // NewWpColorRepresentationManager returns an unbound WpColorRepresentationManager. | |
| 129 | - | func NewWpColorRepresentationManager(ctx *wl.Context) *WpColorRepresentationManager { | |
| 130 | - | obj := &WpColorRepresentationManager{} | |
| 131 | - | obj.SetContext(ctx) | |
| 132 | - | ctx.Register(obj) | |
| 133 | - | return obj | |
| 134 | - | } | |
| 135 | - | ||
| 136 | - | // Destroy the wp_color_representation_manager_v1 object. This does not affect any other objects in any way. | |
| 137 | - | func (o *WpColorRepresentationManager) Destroy() error { | |
| 138 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_color_representation_manager_v1.destroy", Destructor: true}); err != nil { | |
| 139 | - | return err | |
| 140 | - | } | |
| 141 | - | return nil | |
| 142 | - | } | |
| 143 | - | ||
| 144 | - | // If a wp_color_representation_surface_v1 object already exists for the given wl_surface, the protocol error surface_exists is raised. This creates a new color wp_color_representation_surface_v1 object for the given wl_surface. See the wp_color_representation_surface_v1 interface for more details. | |
| 145 | - | func (o *WpColorRepresentationManager) GetSurface(surface *cross_wl_surface.Surface) (*WpColorRepresentationSurface, error) { | |
| 146 | - | var arg1 wl.Object | |
| 147 | - | if surface != nil { | |
| 148 | - | arg1 = surface | |
| 149 | - | } | |
| 150 | - | child := &WpColorRepresentationSurface{} | |
| 151 | - | child.SetContext(o.Context()) | |
| 152 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_color_representation_manager_v1.get_surface", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 153 | - | return nil, err | |
| 154 | - | } | |
| 155 | - | return child, nil | |
| 156 | - | } | |
| 157 | - | ||
| 158 | - | // OnSupportedAlphaMode registers a handler for the supported_alpha_mode event. | |
| 159 | - | // | |
| 160 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 161 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 162 | - | func (o *WpColorRepresentationManager) OnSupportedAlphaMode(handler func(alphaMode uint32)) { | |
| 163 | - | if handler == nil { | |
| 164 | - | return | |
| 165 | - | } | |
| 166 | - | o.handlersMu.Lock() | |
| 167 | - | defer o.handlersMu.Unlock() | |
| 168 | - | o.onSupportedAlphaMode = append(o.onSupportedAlphaMode, handler) | |
| 169 | - | } | |
| 170 | - | ||
| 171 | - | // handlersForSupportedAlphaMode returns the handlers registered for supported_alpha_mode, taken | |
| 172 | - | // under the lock so a handler may register another handler while events are | |
| 173 | - | // being dispatched. | |
| 174 | - | func (o *WpColorRepresentationManager) handlersForSupportedAlphaMode() []func(alphaMode uint32) { | |
| 175 | - | o.handlersMu.Lock() | |
| 176 | - | defer o.handlersMu.Unlock() | |
| 177 | - | return o.onSupportedAlphaMode | |
| 178 | - | } | |
| 179 | - | ||
| 180 | - | // OnSupportedCoefficientsAndRanges registers a handler for the supported_coefficients_and_ranges event. | |
| 181 | - | // | |
| 182 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 183 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 184 | - | func (o *WpColorRepresentationManager) OnSupportedCoefficientsAndRanges(handler func(coefficients uint32, rangeArg uint32)) { | |
| 185 | - | if handler == nil { | |
| 186 | - | return | |
| 187 | - | } | |
| 188 | - | o.handlersMu.Lock() | |
| 189 | - | defer o.handlersMu.Unlock() | |
| 190 | - | o.onSupportedCoefficientsAndRanges = append(o.onSupportedCoefficientsAndRanges, handler) | |
| 191 | - | } | |
| 192 | - | ||
| 193 | - | // handlersForSupportedCoefficientsAndRanges returns the handlers registered for supported_coefficients_and_ranges, taken | |
| 194 | - | // under the lock so a handler may register another handler while events are | |
| 195 | - | // being dispatched. | |
| 196 | - | func (o *WpColorRepresentationManager) handlersForSupportedCoefficientsAndRanges() []func(coefficients uint32, rangeArg uint32) { | |
| 197 | - | o.handlersMu.Lock() | |
| 198 | - | defer o.handlersMu.Unlock() | |
| 199 | - | return o.onSupportedCoefficientsAndRanges | |
| 200 | - | } | |
| 201 | - | ||
| 202 | - | // OnDone registers a handler for the done event. | |
| 203 | - | // | |
| 204 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 205 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 206 | - | func (o *WpColorRepresentationManager) OnDone(handler func()) { | |
| 207 | - | if handler == nil { | |
| 208 | - | return | |
| 209 | - | } | |
| 210 | - | o.handlersMu.Lock() | |
| 211 | - | defer o.handlersMu.Unlock() | |
| 212 | - | o.onDone = append(o.onDone, handler) | |
| 213 | - | } | |
| 214 | - | ||
| 215 | - | // handlersForDone returns the handlers registered for done, taken | |
| 216 | - | // under the lock so a handler may register another handler while events are | |
| 217 | - | // being dispatched. | |
| 218 | - | func (o *WpColorRepresentationManager) handlersForDone() []func() { | |
| 219 | - | o.handlersMu.Lock() | |
| 220 | - | defer o.handlersMu.Unlock() | |
| 221 | - | return o.onDone | |
| 222 | - | } | |
| 223 | - | ||
| 224 | - | // EventSignature returns the declared event argument types in wire order. | |
| 225 | - | func (o *WpColorRepresentationManager) EventSignature(opcode uint16) (string, bool) { | |
| 226 | - | switch opcode { | |
| 227 | - | case 0: | |
| 228 | - | return "uint,", true | |
| 229 | - | case 1: | |
| 230 | - | return "uint,uint,", true | |
| 231 | - | case 2: | |
| 232 | - | return "", true | |
| 233 | - | default: | |
| 234 | - | return "", false | |
| 235 | - | } | |
| 236 | - | } | |
| 237 | - | ||
| 238 | - | // Dispatch decodes one event on wp_color_representation_manager_v1 and calls the registered handlers. | |
| 239 | - | func (o *WpColorRepresentationManager) Dispatch(event *wl.Event) { | |
| 240 | - | switch event.Opcode { | |
| 241 | - | case 0: // supported_alpha_mode | |
| 242 | - | alphaMode := event.Uint32() | |
| 243 | - | ||
| 244 | - | for i, handler := range o.handlersForSupportedAlphaMode() { | |
| 245 | - | _ = i | |
| 246 | - | handler(alphaMode) | |
| 247 | - | } | |
| 248 | - | case 1: // supported_coefficients_and_ranges | |
| 249 | - | coefficients := event.Uint32() | |
| 250 | - | rangeArg := event.Uint32() | |
| 251 | - | ||
| 252 | - | for i, handler := range o.handlersForSupportedCoefficientsAndRanges() { | |
| 253 | - | _ = i | |
| 254 | - | handler(coefficients, rangeArg) | |
| 255 | - | } | |
| 256 | - | case 2: // done | |
| 257 | - | ||
| 258 | - | for i, handler := range o.handlersForDone() { | |
| 259 | - | _ = i | |
| 260 | - | handler() | |
| 261 | - | } | |
| 262 | - | default: | |
| 263 | - | } | |
| 264 | - | } | |
| 265 | - | ||
| 266 | - | // WpColorRepresentationSurfaceInterface is the protocol interface name. | |
| 267 | - | const WpColorRepresentationSurfaceInterface = "wp_color_representation_surface_v1" | |
| 268 | - | ||
| 269 | - | // WpColorRepresentationSurface is the generated binding for wp_color_representation_surface_v1 version 1. | |
| 270 | - | type WpColorRepresentationSurface struct { | |
| 271 | - | wl.BaseProxy | |
| 272 | - | } | |
| 273 | - | ||
| 274 | - | // NewWpColorRepresentationSurface returns an unbound WpColorRepresentationSurface. | |
| 275 | - | func NewWpColorRepresentationSurface(ctx *wl.Context) *WpColorRepresentationSurface { | |
| 276 | - | obj := &WpColorRepresentationSurface{} | |
| 277 | - | obj.SetContext(ctx) | |
| 278 | - | ctx.Register(obj) | |
| 279 | - | return obj | |
| 280 | - | } | |
| 281 | - | ||
| 282 | - | // Destroy the wp_color_representation_surface_v1 object. Destroying this object unsets all the color representation metadata from the surface. See the wp_color_representation_surface_v1 interface description for how a compositor handles a surface without color representation metadata. Unsetting is double-buffered state, see wl_surface.commit. | |
| 283 | - | func (o *WpColorRepresentationSurface) Destroy() error { | |
| 284 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_color_representation_surface_v1.destroy", Destructor: true}); err != nil { | |
| 285 | - | return err | |
| 286 | - | } | |
| 287 | - | return nil | |
| 288 | - | } | |
| 289 | - | ||
| 290 | - | // If this protocol object is inert, the protocol error inert is raised. Assuming an alpha channel exists, it is always linear. The alpha mode determines whether and how the color channels include pre-multiplied alpha. Using straight alpha might have performance benefits. Only alpha modes advertised by the compositor are allowed to be used as argument for this request. The "alpha_mode" protocol error is raised otherwise. Alpha mode is double buffered, see wl_surface.commit. | |
| 291 | - | func (o *WpColorRepresentationSurface) SetAlphaMode(alphaMode uint32) error { | |
| 292 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_color_representation_surface_v1.set_alpha_mode"}, wl.ArgUint(alphaMode)); err != nil { | |
| 293 | - | return err | |
| 294 | - | } | |
| 295 | - | return nil | |
| 296 | - | } | |
| 297 | - | ||
| 298 | - | // If this protocol object is inert, the protocol error inert is raised. Set the matrix coefficients and video range which defines the formula and the related constants used to derive red, green and blue signals. Usually coefficients correspond to MatrixCoefficients code points in H.273. Only combinations advertised by the compositor are allowed to be used as argument for this request. The "coefficients" protocol error is raised otherwise. A call to wl_surface.commit verifies that the pixel format and the coefficients-range combination in the committed surface contents are compatible, if contents exist. The "pixel_format" protocol error is raised otherwise. A pixel format is compatible with the coefficients-range combination if the related equations and conventions as defined in H.273 can produce the color channels (RGB or YCbCr) of the pixel format. For the definition of the supported combination, see the wp_color_representation_surface_v1::coefficients and wp_color_representation_surface_v1::range enums. The coefficients-range combination is double-buffered, see wl_surface.commit. | |
| 299 | - | func (o *WpColorRepresentationSurface) SetCoefficientsAndRange(coefficients uint32, rangeArg uint32) error { | |
| 300 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_color_representation_surface_v1.set_coefficients_and_range"}, wl.ArgUint(coefficients), wl.ArgUint(rangeArg)); err != nil { | |
| 301 | - | return err | |
| 302 | - | } | |
| 303 | - | return nil | |
| 304 | - | } | |
| 305 | - | ||
| 306 | - | // If this protocol object is inert, the protocol error inert is raised. Set the chroma location type which defines the position of downsampled chroma samples, corresponding to Chroma420SampleLocType code points in H.273. An invalid chroma location enum value raises the "chroma_location" protocol error. A call to wl_surface.commit verifies that the pixel format and chroma location type in the committed surface contents are compatible, if contents exist. The "pixel_format" protocol error is raised otherwise. For the definition of the supported chroma location types, see the wp_color_representation_surface_v1::chroma_location enum. The chroma location type is double-buffered, see wl_surface.commit. | |
| 307 | - | func (o *WpColorRepresentationSurface) SetChromaLocation(chromaLocation uint32) error { | |
| 308 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 3, Name: "wp_color_representation_surface_v1.set_chroma_location"}, wl.ArgUint(chromaLocation)); err != nil { | |
| 309 | - | return err | |
| 310 | - | } | |
| 311 | - | return nil | |
| 312 | - | } | |
| 313 | - | ||
| 314 | - | // EventSignature returns the declared event argument types in wire order. | |
| 315 | - | func (o *WpColorRepresentationSurface) EventSignature(opcode uint16) (string, bool) { | |
| 316 | - | switch opcode { | |
| 317 | - | default: | |
| 318 | - | return "", false | |
| 319 | - | } | |
| 320 | - | } | |
| 321 | - | ||
| 322 | - | // Dispatch decodes one event on wp_color_representation_surface_v1 and calls the registered handlers. | |
| 323 | - | func (o *WpColorRepresentationSurface) Dispatch(event *wl.Event) { | |
| 324 | - | switch event.Opcode { | |
| 325 | - | default: | |
| 326 | - | } | |
| 327 | - | } | |
D protocol/colorrepresentation/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package colorrepresentation | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p colorrepresentation -o color-representation-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core color-representation-v1.xml | |
D protocol/committiming/commit-timing-v1.xml +0 -124
| @@ -1,124 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="commit_timing_v1"> | |
| 3 | - | ||
| 4 | - | <copyright> | |
| 5 | - | Copyright © 2023 Valve Corporation | |
| 6 | - | ||
| 7 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 8 | - | copy of this software and associated documentation files (the "Software"), | |
| 9 | - | to deal in the Software without restriction, including without limitation | |
| 10 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 11 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 12 | - | Software is furnished to do so, subject to the following conditions: | |
| 13 | - | ||
| 14 | - | The above copyright notice and this permission notice (including the next | |
| 15 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 16 | - | Software. | |
| 17 | - | ||
| 18 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 23 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 24 | - | DEALINGS IN THE SOFTWARE. | |
| 25 | - | </copyright> | |
| 26 | - | ||
| 27 | - | <interface name="wp_commit_timing_manager_v1" version="1"> | |
| 28 | - | <description summary="commit timing"> | |
| 29 | - | When a compositor latches on to new content updates it will check for | |
| 30 | - | any number of requirements of the available content updates (such as | |
| 31 | - | fences of all buffers being signalled) to consider the update ready. | |
| 32 | - | ||
| 33 | - | This protocol provides a method for adding a time constraint to surface | |
| 34 | - | content. This constraint indicates to the compositor that a content | |
| 35 | - | update should be presented as closely as possible to, but not before, | |
| 36 | - | a specified time. | |
| 37 | - | ||
| 38 | - | This protocol does not change the Wayland property that content | |
| 39 | - | updates are applied in the order they are received, even when some | |
| 40 | - | content updates contain timestamps and others do not. | |
| 41 | - | ||
| 42 | - | To provide timestamps, this global factory interface must be used to | |
| 43 | - | acquire a wp_commit_timing_v1 object for a surface, which may then be | |
| 44 | - | used to provide timestamp information for commits. | |
| 45 | - | ||
| 46 | - | Warning! The protocol described in this file is currently in the testing | |
| 47 | - | phase. Backward compatible changes may be added together with the | |
| 48 | - | corresponding interface version bump. Backward incompatible changes can | |
| 49 | - | only be done by creating a new major version of the extension. | |
| 50 | - | </description> | |
| 51 | - | <enum name="error"> | |
| 52 | - | <entry name="commit_timer_exists" value="0" | |
| 53 | - | summary="commit timer already exists for surface"/> | |
| 54 | - | </enum> | |
| 55 | - | ||
| 56 | - | <request name="destroy" type="destructor"> | |
| 57 | - | <description summary="unbind from the commit timing interface"> | |
| 58 | - | Informs the server that the client will no longer be using | |
| 59 | - | this protocol object. Existing objects created by this object | |
| 60 | - | are not affected. | |
| 61 | - | </description> | |
| 62 | - | </request> | |
| 63 | - | ||
| 64 | - | <request name="get_timer"> | |
| 65 | - | <description summary="request commit timer interface for surface"> | |
| 66 | - | Establish a timing controller for a surface. | |
| 67 | - | ||
| 68 | - | Only one commit timer can be created for a surface, or a | |
| 69 | - | commit_timer_exists protocol error will be generated. | |
| 70 | - | </description> | |
| 71 | - | <arg name="id" type="new_id" interface="wp_commit_timer_v1"/> | |
| 72 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 73 | - | </request> | |
| 74 | - | </interface> | |
| 75 | - | ||
| 76 | - | <interface name="wp_commit_timer_v1" version="1"> | |
| 77 | - | <description summary="Surface commit timer"> | |
| 78 | - | An object to set a time constraint for a content update on a surface. | |
| 79 | - | </description> | |
| 80 | - | ||
| 81 | - | <enum name="error"> | |
| 82 | - | <entry name="invalid_timestamp" value="0" | |
| 83 | - | summary="timestamp contains an invalid value"/> | |
| 84 | - | <entry name="timestamp_exists" value="1" | |
| 85 | - | summary="timestamp exists"/> | |
| 86 | - | <entry name="surface_destroyed" value="2" | |
| 87 | - | summary="the associated surface no longer exists"/> | |
| 88 | - | </enum> | |
| 89 | - | ||
| 90 | - | <request name="set_timestamp"> | |
| 91 | - | <description summary="Specify time the following commit takes effect"> | |
| 92 | - | Provide a timing constraint for a surface content update. | |
| 93 | - | ||
| 94 | - | A set_timestamp request may be made before a wl_surface.commit to | |
| 95 | - | tell the compositor that the content is intended to be presented | |
| 96 | - | as closely as possible to, but not before, the specified time. | |
| 97 | - | The time is in the domain of the compositor's presentation clock. | |
| 98 | - | ||
| 99 | - | An invalid_timestamp error will be generated for invalid tv_nsec. | |
| 100 | - | ||
| 101 | - | If a timestamp already exists on the surface, a timestamp_exists | |
| 102 | - | error is generated. | |
| 103 | - | ||
| 104 | - | Requesting set_timestamp after the commit_timer object's surface is | |
| 105 | - | destroyed will generate a "surface_destroyed" error. | |
| 106 | - | </description> | |
| 107 | - | <arg name="tv_sec_hi" type="uint" | |
| 108 | - | summary="high 32 bits of the seconds part of target time"/> | |
| 109 | - | <arg name="tv_sec_lo" type="uint" | |
| 110 | - | summary="low 32 bits of the seconds part of target time"/> | |
| 111 | - | <arg name="tv_nsec" type="uint" | |
| 112 | - | summary="nanoseconds part of target time"/> | |
| 113 | - | </request> | |
| 114 | - | ||
| 115 | - | <request name="destroy" type="destructor"> | |
| 116 | - | <description summary="Destroy the timer"> | |
| 117 | - | Informs the server that the client will no longer be using | |
| 118 | - | this protocol object. | |
| 119 | - | ||
| 120 | - | Existing timing constraints are not affected by the destruction. | |
| 121 | - | </description> | |
| 122 | - | </request> | |
| 123 | - | </interface> | |
| 124 | - | </protocol> | |
D protocol/committiming/commit-timing-v1_generated.go +0 -144
| @@ -1,144 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: commit_timing_v1 | |
| 3 | - | // Source: commit-timing-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2023 Valve Corporation | |
| 7 | - | // | |
| 8 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 9 | - | // copy of this software and associated documentation files (the "Software"), | |
| 10 | - | // to deal in the Software without restriction, including without limitation | |
| 11 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 12 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 13 | - | // Software is furnished to do so, subject to the following conditions: | |
| 14 | - | // | |
| 15 | - | // The above copyright notice and this permission notice (including the next | |
| 16 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | // Software. | |
| 18 | - | // | |
| 19 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 22 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 24 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 25 | - | // DEALINGS IN THE SOFTWARE. | |
| 26 | - | ||
| 27 | - | package committiming | |
| 28 | - | ||
| 29 | - | import ( | |
| 30 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 31 | - | "github.com/bnema/wlturbo/wl" | |
| 32 | - | ) | |
| 33 | - | ||
| 34 | - | // ERROR_COMMIT_TIMER_EXISTS is the error commit_timer_exists value. | |
| 35 | - | const ERROR_COMMIT_TIMER_EXISTS = 0 | |
| 36 | - | ||
| 37 | - | // ERROR_INVALID_TIMESTAMP is the error invalid_timestamp value. | |
| 38 | - | const ERROR_INVALID_TIMESTAMP = 0 | |
| 39 | - | ||
| 40 | - | // ERROR_TIMESTAMP_EXISTS is the error timestamp_exists value. | |
| 41 | - | const ERROR_TIMESTAMP_EXISTS = 1 | |
| 42 | - | ||
| 43 | - | // ERROR_SURFACE_DESTROYED is the error surface_destroyed value. | |
| 44 | - | const ERROR_SURFACE_DESTROYED = 2 | |
| 45 | - | ||
| 46 | - | // WpCommitTimingManagerInterface is the protocol interface name. | |
| 47 | - | const WpCommitTimingManagerInterface = "wp_commit_timing_manager_v1" | |
| 48 | - | ||
| 49 | - | // WpCommitTimingManager is the generated binding for wp_commit_timing_manager_v1 version 1. | |
| 50 | - | type WpCommitTimingManager struct { | |
| 51 | - | wl.BaseProxy | |
| 52 | - | } | |
| 53 | - | ||
| 54 | - | // NewWpCommitTimingManager returns an unbound WpCommitTimingManager. | |
| 55 | - | func NewWpCommitTimingManager(ctx *wl.Context) *WpCommitTimingManager { | |
| 56 | - | obj := &WpCommitTimingManager{} | |
| 57 | - | obj.SetContext(ctx) | |
| 58 | - | ctx.Register(obj) | |
| 59 | - | return obj | |
| 60 | - | } | |
| 61 | - | ||
| 62 | - | // Informs the server that the client will no longer be using this protocol object. Existing objects created by this object are not affected. | |
| 63 | - | func (o *WpCommitTimingManager) Destroy() error { | |
| 64 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_commit_timing_manager_v1.destroy", Destructor: true}); err != nil { | |
| 65 | - | return err | |
| 66 | - | } | |
| 67 | - | return nil | |
| 68 | - | } | |
| 69 | - | ||
| 70 | - | // Establish a timing controller for a surface. Only one commit timer can be created for a surface, or a commit_timer_exists protocol error will be generated. | |
| 71 | - | func (o *WpCommitTimingManager) GetTimer(surface *cross_wl_surface.Surface) (*WpCommitTimer, error) { | |
| 72 | - | var arg1 wl.Object | |
| 73 | - | if surface != nil { | |
| 74 | - | arg1 = surface | |
| 75 | - | } | |
| 76 | - | child := &WpCommitTimer{} | |
| 77 | - | child.SetContext(o.Context()) | |
| 78 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_commit_timing_manager_v1.get_timer", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 79 | - | return nil, err | |
| 80 | - | } | |
| 81 | - | return child, nil | |
| 82 | - | } | |
| 83 | - | ||
| 84 | - | // EventSignature returns the declared event argument types in wire order. | |
| 85 | - | func (o *WpCommitTimingManager) EventSignature(opcode uint16) (string, bool) { | |
| 86 | - | switch opcode { | |
| 87 | - | default: | |
| 88 | - | return "", false | |
| 89 | - | } | |
| 90 | - | } | |
| 91 | - | ||
| 92 | - | // Dispatch decodes one event on wp_commit_timing_manager_v1 and calls the registered handlers. | |
| 93 | - | func (o *WpCommitTimingManager) Dispatch(event *wl.Event) { | |
| 94 | - | switch event.Opcode { | |
| 95 | - | default: | |
| 96 | - | } | |
| 97 | - | } | |
| 98 | - | ||
| 99 | - | // WpCommitTimerInterface is the protocol interface name. | |
| 100 | - | const WpCommitTimerInterface = "wp_commit_timer_v1" | |
| 101 | - | ||
| 102 | - | // WpCommitTimer is the generated binding for wp_commit_timer_v1 version 1. | |
| 103 | - | type WpCommitTimer struct { | |
| 104 | - | wl.BaseProxy | |
| 105 | - | } | |
| 106 | - | ||
| 107 | - | // NewWpCommitTimer returns an unbound WpCommitTimer. | |
| 108 | - | func NewWpCommitTimer(ctx *wl.Context) *WpCommitTimer { | |
| 109 | - | obj := &WpCommitTimer{} | |
| 110 | - | obj.SetContext(ctx) | |
| 111 | - | ctx.Register(obj) | |
| 112 | - | return obj | |
| 113 | - | } | |
| 114 | - | ||
| 115 | - | // Provide a timing constraint for a surface content update. A set_timestamp request may be made before a wl_surface.commit to tell the compositor that the content is intended to be presented as closely as possible to, but not before, the specified time. The time is in the domain of the compositor's presentation clock. An invalid_timestamp error will be generated for invalid tv_nsec. If a timestamp already exists on the surface, a timestamp_exists error is generated. Requesting set_timestamp after the commit_timer object's surface is destroyed will generate a "surface_destroyed" error. | |
| 116 | - | func (o *WpCommitTimer) SetTimestamp(tvSecHi uint32, tvSecLo uint32, tvNsec uint32) error { | |
| 117 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_commit_timer_v1.set_timestamp"}, wl.ArgUint(tvSecHi), wl.ArgUint(tvSecLo), wl.ArgUint(tvNsec)); err != nil { | |
| 118 | - | return err | |
| 119 | - | } | |
| 120 | - | return nil | |
| 121 | - | } | |
| 122 | - | ||
| 123 | - | // Informs the server that the client will no longer be using this protocol object. Existing timing constraints are not affected by the destruction. | |
| 124 | - | func (o *WpCommitTimer) Destroy() error { | |
| 125 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_commit_timer_v1.destroy", Destructor: true}); err != nil { | |
| 126 | - | return err | |
| 127 | - | } | |
| 128 | - | return nil | |
| 129 | - | } | |
| 130 | - | ||
| 131 | - | // EventSignature returns the declared event argument types in wire order. | |
| 132 | - | func (o *WpCommitTimer) EventSignature(opcode uint16) (string, bool) { | |
| 133 | - | switch opcode { | |
| 134 | - | default: | |
| 135 | - | return "", false | |
| 136 | - | } | |
| 137 | - | } | |
| 138 | - | ||
| 139 | - | // Dispatch decodes one event on wp_commit_timer_v1 and calls the registered handlers. | |
| 140 | - | func (o *WpCommitTimer) Dispatch(event *wl.Event) { | |
| 141 | - | switch event.Opcode { | |
| 142 | - | default: | |
| 143 | - | } | |
| 144 | - | } | |
D protocol/committiming/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package committiming | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p committiming -o commit-timing-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core commit-timing-v1.xml | |
D protocol/contenttype/content-type-v1.xml +0 -128
| @@ -1,128 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="content_type_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2021 Emmanuel Gil Peyrot | |
| 5 | - | Copyright © 2022 Xaver Hugl | |
| 6 | - | ||
| 7 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 8 | - | copy of this software and associated documentation files (the "Software"), | |
| 9 | - | to deal in the Software without restriction, including without limitation | |
| 10 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 11 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 12 | - | Software is furnished to do so, subject to the following conditions: | |
| 13 | - | ||
| 14 | - | The above copyright notice and this permission notice (including the next | |
| 15 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 16 | - | Software. | |
| 17 | - | ||
| 18 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 23 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 24 | - | DEALINGS IN THE SOFTWARE. | |
| 25 | - | </copyright> | |
| 26 | - | ||
| 27 | - | <interface name="wp_content_type_manager_v1" version="1"> | |
| 28 | - | <description summary="surface content type manager"> | |
| 29 | - | This interface allows a client to describe the kind of content a surface | |
| 30 | - | will display, to allow the compositor to optimize its behavior for it. | |
| 31 | - | ||
| 32 | - | Warning! The protocol described in this file is currently in the testing | |
| 33 | - | phase. Backward compatible changes may be added together with the | |
| 34 | - | corresponding interface version bump. Backward incompatible changes can | |
| 35 | - | only be done by creating a new major version of the extension. | |
| 36 | - | </description> | |
| 37 | - | ||
| 38 | - | <request name="destroy" type="destructor"> | |
| 39 | - | <description summary="destroy the content type manager object"> | |
| 40 | - | Destroy the content type manager. This doesn't destroy objects created | |
| 41 | - | with the manager. | |
| 42 | - | </description> | |
| 43 | - | </request> | |
| 44 | - | ||
| 45 | - | <enum name="error"> | |
| 46 | - | <entry name="already_constructed" value="0" | |
| 47 | - | summary="wl_surface already has a content type object"/> | |
| 48 | - | </enum> | |
| 49 | - | ||
| 50 | - | <request name="get_surface_content_type"> | |
| 51 | - | <description summary="create a new content type object"> | |
| 52 | - | Create a new content type object associated with the given surface. | |
| 53 | - | ||
| 54 | - | Creating a wp_content_type_v1 from a wl_surface which already has one | |
| 55 | - | attached is a client error: already_constructed. | |
| 56 | - | </description> | |
| 57 | - | <arg name="id" type="new_id" interface="wp_content_type_v1"/> | |
| 58 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 59 | - | </request> | |
| 60 | - | </interface> | |
| 61 | - | ||
| 62 | - | <interface name="wp_content_type_v1" version="1"> | |
| 63 | - | <description summary="content type object for a surface"> | |
| 64 | - | The content type object allows the compositor to optimize for the kind | |
| 65 | - | of content shown on the surface. A compositor may for example use it to | |
| 66 | - | set relevant drm properties like "content type". | |
| 67 | - | ||
| 68 | - | The client may request to switch to another content type at any time. | |
| 69 | - | When the associated surface gets destroyed, this object becomes inert and | |
| 70 | - | the client should destroy it. | |
| 71 | - | </description> | |
| 72 | - | ||
| 73 | - | <request name="destroy" type="destructor"> | |
| 74 | - | <description summary="destroy the content type object"> | |
| 75 | - | Switch back to not specifying the content type of this surface. This is | |
| 76 | - | equivalent to setting the content type to none, including double | |
| 77 | - | buffering semantics. See set_content_type for details. | |
| 78 | - | </description> | |
| 79 | - | </request> | |
| 80 | - | ||
| 81 | - | <enum name="type"> | |
| 82 | - | <description summary="possible content types"> | |
| 83 | - | These values describe the available content types for a surface. | |
| 84 | - | </description> | |
| 85 | - | <entry name="none" value="0"> | |
| 86 | - | <description summary="no content type applies"> | |
| 87 | - | The content type none means that either the application has no data | |
| 88 | - | about the content type, or that the content doesn't fit into one of | |
| 89 | - | the other categories. | |
| 90 | - | </description> | |
| 91 | - | </entry> | |
| 92 | - | <entry name="photo" value="1"> | |
| 93 | - | <description summary="photo content type"> | |
| 94 | - | The content type photo describes content derived from digital still | |
| 95 | - | pictures and may be presented with minimal processing. | |
| 96 | - | </description> | |
| 97 | - | </entry> | |
| 98 | - | <entry name="video" value="2"> | |
| 99 | - | <description summary="video content type"> | |
| 100 | - | The content type video describes a video or animation and may be | |
| 101 | - | presented with more accurate timing to avoid stutter. Where scaling | |
| 102 | - | is needed, scaling methods more appropriate for video may be used. | |
| 103 | - | </description> | |
| 104 | - | </entry> | |
| 105 | - | <entry name="game" value="3"> | |
| 106 | - | <description summary="game content type"> | |
| 107 | - | The content type game describes a running game. Its content may be | |
| 108 | - | presented with reduced latency. | |
| 109 | - | </description> | |
| 110 | - | </entry> | |
| 111 | - | </enum> | |
| 112 | - | ||
| 113 | - | <request name="set_content_type"> | |
| 114 | - | <description summary="specify the content type"> | |
| 115 | - | Set the surface content type. This informs the compositor that the | |
| 116 | - | client believes it is displaying buffers matching this content type. | |
| 117 | - | ||
| 118 | - | This is purely a hint for the compositor, which can be used to adjust | |
| 119 | - | its behavior or hardware settings to fit the presented content best. | |
| 120 | - | ||
| 121 | - | The content type is double-buffered state, see wl_surface.commit for | |
| 122 | - | details. | |
| 123 | - | </description> | |
| 124 | - | <arg name="content_type" type="uint" enum="type" | |
| 125 | - | summary="the content type"/> | |
| 126 | - | </request> | |
| 127 | - | </interface> | |
| 128 | - | </protocol> | |
D protocol/contenttype/content-type-v1_generated.go +0 -148
| @@ -1,148 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: content_type_v1 | |
| 3 | - | // Source: content-type-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2021 Emmanuel Gil Peyrot | |
| 7 | - | // Copyright © 2022 Xaver Hugl | |
| 8 | - | // | |
| 9 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 | - | // copy of this software and associated documentation files (the "Software"), | |
| 11 | - | // to deal in the Software without restriction, including without limitation | |
| 12 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 14 | - | // Software is furnished to do so, subject to the following conditions: | |
| 15 | - | // | |
| 16 | - | // The above copyright notice and this permission notice (including the next | |
| 17 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 18 | - | // Software. | |
| 19 | - | // | |
| 20 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 23 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 25 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 26 | - | // DEALINGS IN THE SOFTWARE. | |
| 27 | - | ||
| 28 | - | package contenttype | |
| 29 | - | ||
| 30 | - | import ( | |
| 31 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 32 | - | "github.com/bnema/wlturbo/wl" | |
| 33 | - | ) | |
| 34 | - | ||
| 35 | - | // ERROR_ALREADY_CONSTRUCTED is the error already_constructed value. | |
| 36 | - | const ERROR_ALREADY_CONSTRUCTED = 0 | |
| 37 | - | ||
| 38 | - | // TYPE_NONE is the type none value. | |
| 39 | - | const TYPE_NONE = 0 | |
| 40 | - | ||
| 41 | - | // TYPE_PHOTO is the type photo value. | |
| 42 | - | const TYPE_PHOTO = 1 | |
| 43 | - | ||
| 44 | - | // TYPE_VIDEO is the type video value. | |
| 45 | - | const TYPE_VIDEO = 2 | |
| 46 | - | ||
| 47 | - | // TYPE_GAME is the type game value. | |
| 48 | - | const TYPE_GAME = 3 | |
| 49 | - | ||
| 50 | - | // WpContentTypeManagerInterface is the protocol interface name. | |
| 51 | - | const WpContentTypeManagerInterface = "wp_content_type_manager_v1" | |
| 52 | - | ||
| 53 | - | // WpContentTypeManager is the generated binding for wp_content_type_manager_v1 version 1. | |
| 54 | - | type WpContentTypeManager struct { | |
| 55 | - | wl.BaseProxy | |
| 56 | - | } | |
| 57 | - | ||
| 58 | - | // NewWpContentTypeManager returns an unbound WpContentTypeManager. | |
| 59 | - | func NewWpContentTypeManager(ctx *wl.Context) *WpContentTypeManager { | |
| 60 | - | obj := &WpContentTypeManager{} | |
| 61 | - | obj.SetContext(ctx) | |
| 62 | - | ctx.Register(obj) | |
| 63 | - | return obj | |
| 64 | - | } | |
| 65 | - | ||
| 66 | - | // Destroy the content type manager. This doesn't destroy objects created with the manager. | |
| 67 | - | func (o *WpContentTypeManager) Destroy() error { | |
| 68 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_content_type_manager_v1.destroy", Destructor: true}); err != nil { | |
| 69 | - | return err | |
| 70 | - | } | |
| 71 | - | return nil | |
| 72 | - | } | |
| 73 | - | ||
| 74 | - | // Create a new content type object associated with the given surface. Creating a wp_content_type_v1 from a wl_surface which already has one attached is a client error: already_constructed. | |
| 75 | - | func (o *WpContentTypeManager) GetSurfaceContentType(surface *cross_wl_surface.Surface) (*WpContentType, error) { | |
| 76 | - | var arg1 wl.Object | |
| 77 | - | if surface != nil { | |
| 78 | - | arg1 = surface | |
| 79 | - | } | |
| 80 | - | child := &WpContentType{} | |
| 81 | - | child.SetContext(o.Context()) | |
| 82 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_content_type_manager_v1.get_surface_content_type", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 83 | - | return nil, err | |
| 84 | - | } | |
| 85 | - | return child, nil | |
| 86 | - | } | |
| 87 | - | ||
| 88 | - | // EventSignature returns the declared event argument types in wire order. | |
| 89 | - | func (o *WpContentTypeManager) EventSignature(opcode uint16) (string, bool) { | |
| 90 | - | switch opcode { | |
| 91 | - | default: | |
| 92 | - | return "", false | |
| 93 | - | } | |
| 94 | - | } | |
| 95 | - | ||
| 96 | - | // Dispatch decodes one event on wp_content_type_manager_v1 and calls the registered handlers. | |
| 97 | - | func (o *WpContentTypeManager) Dispatch(event *wl.Event) { | |
| 98 | - | switch event.Opcode { | |
| 99 | - | default: | |
| 100 | - | } | |
| 101 | - | } | |
| 102 | - | ||
| 103 | - | // WpContentTypeInterface is the protocol interface name. | |
| 104 | - | const WpContentTypeInterface = "wp_content_type_v1" | |
| 105 | - | ||
| 106 | - | // WpContentType is the generated binding for wp_content_type_v1 version 1. | |
| 107 | - | type WpContentType struct { | |
| 108 | - | wl.BaseProxy | |
| 109 | - | } | |
| 110 | - | ||
| 111 | - | // NewWpContentType returns an unbound WpContentType. | |
| 112 | - | func NewWpContentType(ctx *wl.Context) *WpContentType { | |
| 113 | - | obj := &WpContentType{} | |
| 114 | - | obj.SetContext(ctx) | |
| 115 | - | ctx.Register(obj) | |
| 116 | - | return obj | |
| 117 | - | } | |
| 118 | - | ||
| 119 | - | // Switch back to not specifying the content type of this surface. This is equivalent to setting the content type to none, including double buffering semantics. See set_content_type for details. | |
| 120 | - | func (o *WpContentType) Destroy() error { | |
| 121 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_content_type_v1.destroy", Destructor: true}); err != nil { | |
| 122 | - | return err | |
| 123 | - | } | |
| 124 | - | return nil | |
| 125 | - | } | |
| 126 | - | ||
| 127 | - | // Set the surface content type. This informs the compositor that the client believes it is displaying buffers matching this content type. This is purely a hint for the compositor, which can be used to adjust its behavior or hardware settings to fit the presented content best. The content type is double-buffered state, see wl_surface.commit for details. | |
| 128 | - | func (o *WpContentType) SetContentType(contentType uint32) error { | |
| 129 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_content_type_v1.set_content_type"}, wl.ArgUint(contentType)); err != nil { | |
| 130 | - | return err | |
| 131 | - | } | |
| 132 | - | return nil | |
| 133 | - | } | |
| 134 | - | ||
| 135 | - | // EventSignature returns the declared event argument types in wire order. | |
| 136 | - | func (o *WpContentType) EventSignature(opcode uint16) (string, bool) { | |
| 137 | - | switch opcode { | |
| 138 | - | default: | |
| 139 | - | return "", false | |
| 140 | - | } | |
| 141 | - | } | |
| 142 | - | ||
| 143 | - | // Dispatch decodes one event on wp_content_type_v1 and calls the registered handlers. | |
| 144 | - | func (o *WpContentType) Dispatch(event *wl.Event) { | |
| 145 | - | switch event.Opcode { | |
| 146 | - | default: | |
| 147 | - | } | |
| 148 | - | } | |
D protocol/contenttype/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package contenttype | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p contenttype -o content-type-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core content-type-v1.xml | |
D protocol/core/core_test.go +0 -532
| @@ -1,532 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package core_test | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "encoding/binary" | |
| 7 | - | "errors" | |
| 8 | - | "io" | |
| 9 | - | "net" | |
| 10 | - | "os" | |
| 11 | - | "testing" | |
| 12 | - | "time" | |
| 13 | - | ||
| 14 | - | "github.com/bnema/wlturbo" | |
| 15 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 16 | - | "golang.org/x/sys/unix" | |
| 17 | - | ) | |
| 18 | - | ||
| 19 | - | func pair(t *testing.T) (*net.UnixConn, *net.UnixConn) { | |
| 20 | - | t.Helper() | |
| 21 | - | f, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0) | |
| 22 | - | if err != nil { | |
| 23 | - | t.Fatal(err) | |
| 24 | - | } | |
| 25 | - | a := os.NewFile(uintptr(f[0]), "a") | |
| 26 | - | b := os.NewFile(uintptr(f[1]), "b") | |
| 27 | - | ca, e := net.FileConn(a) | |
| 28 | - | a.Close() | |
| 29 | - | if e != nil { | |
| 30 | - | t.Fatal(e) | |
| 31 | - | } | |
| 32 | - | cb, e := net.FileConn(b) | |
| 33 | - | b.Close() | |
| 34 | - | if e != nil { | |
| 35 | - | t.Fatal(e) | |
| 36 | - | } | |
| 37 | - | t.Cleanup(func() { ca.Close(); cb.Close() }) | |
| 38 | - | return ca.(*net.UnixConn), cb.(*net.UnixConn) | |
| 39 | - | } | |
| 40 | - | func frame(id uint32, op uint16, body ...uint32) []byte { | |
| 41 | - | p := make([]byte, 8+4*len(body)) | |
| 42 | - | binary.LittleEndian.PutUint32(p, id) | |
| 43 | - | binary.LittleEndian.PutUint32(p[4:], uint32(len(p))<<16|uint32(op)) | |
| 44 | - | for i, v := range body { | |
| 45 | - | binary.LittleEndian.PutUint32(p[8+i*4:], v) | |
| 46 | - | } | |
| 47 | - | return p | |
| 48 | - | } | |
| 49 | - | func receiveRequest(t *testing.T, p *net.UnixConn) { | |
| 50 | - | t.Helper() | |
| 51 | - | p.SetReadDeadline(testDeadline()) | |
| 52 | - | b := make([]byte, 256) | |
| 53 | - | if _, e := p.Read(b); e != nil { | |
| 54 | - | t.Fatal(e) | |
| 55 | - | } | |
| 56 | - | } | |
| 57 | - | func testDeadline() (d time.Time) { return time.Now().Add(2 * time.Second) } | |
| 58 | - | func send(t *testing.T, p *net.UnixConn, msg []byte, fd ...int) { | |
| 59 | - | t.Helper() | |
| 60 | - | var oob []byte | |
| 61 | - | if len(fd) > 0 { | |
| 62 | - | oob = unix.UnixRights(fd...) | |
| 63 | - | } | |
| 64 | - | if _, _, e := p.WriteMsgUnix(msg, oob, nil); e != nil { | |
| 65 | - | t.Fatal(e) | |
| 66 | - | } | |
| 67 | - | } | |
| 68 | - | func TestGeneratedCoreOverSocketpair(t *testing.T) { | |
| 69 | - | c, p := pair(t) | |
| 70 | - | d, err := wlturbo.ConnectFromConn(c) | |
| 71 | - | if err != nil { | |
| 72 | - | t.Fatal(err) | |
| 73 | - | } | |
| 74 | - | defer d.Close() | |
| 75 | - | receiveRequest(t, p) // get_registry | |
| 76 | - | seat := core.NewSeat(d.Context()) | |
| 77 | - | if err := d.Registry().Bind(1, core.SeatInterface, 1, seat); err != nil { | |
| 78 | - | t.Fatal(err) | |
| 79 | - | } | |
| 80 | - | receiveRequest(t, p) | |
| 81 | - | kb, err := seat.GetKeyboard() | |
| 82 | - | if err != nil { | |
| 83 | - | t.Fatal(err) | |
| 84 | - | } | |
| 85 | - | receiveRequest(t, p) | |
| 86 | - | var key uint32 | |
| 87 | - | kb.OnKey(func(_, _, k, _ uint32) { key = k }) | |
| 88 | - | send(t, p, frame(kb.ID(), 3, 1, 2, 42, 1)) | |
| 89 | - | if err := d.Dispatch(); err != nil { | |
| 90 | - | t.Fatal(err) | |
| 91 | - | } | |
| 92 | - | if key != 42 { | |
| 93 | - | t.Fatalf("key=%d", key) | |
| 94 | - | } | |
| 95 | - | compositor := core.NewCompositor(d.Context()) | |
| 96 | - | if err := d.Registry().Bind(2, core.CompositorInterface, 1, compositor); err != nil { | |
| 97 | - | t.Fatal(err) | |
| 98 | - | } | |
| 99 | - | receiveRequest(t, p) | |
| 100 | - | surface, err := compositor.CreateSurface() | |
| 101 | - | if err != nil { | |
| 102 | - | t.Fatal(err) | |
| 103 | - | } | |
| 104 | - | receiveRequest(t, p) | |
| 105 | - | callback, err := surface.Frame() | |
| 106 | - | if err != nil { | |
| 107 | - | t.Fatal(err) | |
| 108 | - | } | |
| 109 | - | receiveRequest(t, p) | |
| 110 | - | var done uint32 | |
| 111 | - | callback.OnDone(func(ms uint32) { done = ms }) | |
| 112 | - | send(t, p, frame(callback.ID(), 0, 123)) | |
| 113 | - | if err := d.Dispatch(); err != nil { | |
| 114 | - | t.Fatal(err) | |
| 115 | - | } | |
| 116 | - | if done != 123 { | |
| 117 | - | t.Fatalf("done=%d", done) | |
| 118 | - | } | |
| 119 | - | send(t, p, frame(callback.ID(), 0, 124)) | |
| 120 | - | if err := d.Dispatch(); !errors.Is(err, wlturbo.ErrUnknownObject) { | |
| 121 | - | t.Fatalf("destroyed callback: %v", err) | |
| 122 | - | } | |
| 123 | - | } | |
| 124 | - | func TestKeymapFDNoHandlerAndMultipleHandlers(t *testing.T) { | |
| 125 | - | c, p := pair(t) | |
| 126 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 127 | - | if e != nil { | |
| 128 | - | t.Fatal(e) | |
| 129 | - | } | |
| 130 | - | defer d.Close() | |
| 131 | - | receiveRequest(t, p) | |
| 132 | - | kb := core.NewKeyboard(d.Context()) | |
| 133 | - | kb.SetID(d.AllocateID()) | |
| 134 | - | d.Context().Register(kb) | |
| 135 | - | r, w, e := os.Pipe() | |
| 136 | - | if e != nil { | |
| 137 | - | t.Fatal(e) | |
| 138 | - | } | |
| 139 | - | defer r.Close() | |
| 140 | - | send(t, p, frame(kb.ID(), 0, 1, 8), int(w.Fd())) | |
| 141 | - | w.Close() | |
| 142 | - | if e := d.Dispatch(); e != nil { | |
| 143 | - | t.Fatal(e) | |
| 144 | - | } | |
| 145 | - | buf := make([]byte, 1) | |
| 146 | - | if n, e := r.Read(buf); n != 0 || e != io.EOF { | |
| 147 | - | t.Fatalf("unclaimed FD n=%d err=%v", n, e) | |
| 148 | - | } | |
| 149 | - | r2, w2, e := os.Pipe() | |
| 150 | - | if e != nil { | |
| 151 | - | t.Fatal(e) | |
| 152 | - | } | |
| 153 | - | defer r2.Close() | |
| 154 | - | received := 0 | |
| 155 | - | kb.OnKeymap(func(_ uint32, fd *wlturbo.OwnedFD, _ uint32) { | |
| 156 | - | if fd == nil { | |
| 157 | - | t.Fatal("first FD missing") | |
| 158 | - | } | |
| 159 | - | n, e := fd.Take() | |
| 160 | - | if e != nil { | |
| 161 | - | t.Fatal(e) | |
| 162 | - | } | |
| 163 | - | received++ | |
| 164 | - | unix.Close(n) | |
| 165 | - | }) | |
| 166 | - | kb.OnKeymap(func(_ uint32, fd *wlturbo.OwnedFD, _ uint32) { | |
| 167 | - | if fd != nil { | |
| 168 | - | t.Fatal("duplicated owner") | |
| 169 | - | } | |
| 170 | - | received++ | |
| 171 | - | }) | |
| 172 | - | send(t, p, frame(kb.ID(), 0, 1, 8), int(w2.Fd())) | |
| 173 | - | w2.Close() | |
| 174 | - | if e := d.Dispatch(); e != nil { | |
| 175 | - | t.Fatal(e) | |
| 176 | - | } | |
| 177 | - | if received != 2 { | |
| 178 | - | t.Fatalf("handlers=%d", received) | |
| 179 | - | } | |
| 180 | - | } | |
| 181 | - | func TestBufferReleaseAndOfferChild(t *testing.T) { | |
| 182 | - | c, p := pair(t) | |
| 183 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 184 | - | if e != nil { | |
| 185 | - | t.Fatal(e) | |
| 186 | - | } | |
| 187 | - | defer d.Close() | |
| 188 | - | receiveRequest(t, p) | |
| 189 | - | b := core.NewBuffer(d.Context()) | |
| 190 | - | b.SetID(d.AllocateID()) | |
| 191 | - | d.Context().Register(b) | |
| 192 | - | releases := 0 | |
| 193 | - | b.OnRelease(func() { releases++ }) | |
| 194 | - | send(t, p, frame(b.ID(), 0)) | |
| 195 | - | if e := d.Dispatch(); e != nil { | |
| 196 | - | t.Fatal(e) | |
| 197 | - | } | |
| 198 | - | if releases != 1 { | |
| 199 | - | t.Fatal("release not dispatched") | |
| 200 | - | } | |
| 201 | - | device := core.NewDataDevice(d.Context()) | |
| 202 | - | device.SetID(d.AllocateID()) | |
| 203 | - | d.Context().Register(device) | |
| 204 | - | var offer *core.DataOffer | |
| 205 | - | device.OnDataOffer(func(o *core.DataOffer) { offer = o }) | |
| 206 | - | send(t, p, frame(device.ID(), 0, 0xff000001)) | |
| 207 | - | if e := d.Dispatch(); e != nil { | |
| 208 | - | t.Fatal(e) | |
| 209 | - | } | |
| 210 | - | if offer == nil || offer.ID() != 0xff000001 { | |
| 211 | - | t.Fatalf("offer=%v", offer) | |
| 212 | - | } | |
| 213 | - | } | |
| 214 | - | ||
| 215 | - | func TestMissingKeymapDescriptor(t *testing.T) { | |
| 216 | - | c, p := pair(t) | |
| 217 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 218 | - | if e != nil { | |
| 219 | - | t.Fatal(e) | |
| 220 | - | } | |
| 221 | - | defer d.Close() | |
| 222 | - | receiveRequest(t, p) | |
| 223 | - | kb := core.NewKeyboard(d.Context()) | |
| 224 | - | kb.SetID(d.AllocateID()) | |
| 225 | - | d.Context().Register(kb) | |
| 226 | - | send(t, p, frame(kb.ID(), 0, 1, 8)) | |
| 227 | - | if e := d.Dispatch(); !errors.Is(e, wlturbo.ErrMalformedFrame) { | |
| 228 | - | t.Fatalf("missing FD: %v", e) | |
| 229 | - | } | |
| 230 | - | } | |
| 231 | - | ||
| 232 | - | func TestInterleavedFDAndPlainMessages(t *testing.T) { | |
| 233 | - | c, p := pair(t) | |
| 234 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 235 | - | if e != nil { | |
| 236 | - | t.Fatal(e) | |
| 237 | - | } | |
| 238 | - | defer d.Close() | |
| 239 | - | receiveRequest(t, p) | |
| 240 | - | kb := core.NewKeyboard(d.Context()) | |
| 241 | - | kb.SetID(d.AllocateID()) | |
| 242 | - | d.Context().Register(kb) | |
| 243 | - | calls := 0 | |
| 244 | - | kb.OnKeymap(func(_ uint32, fd *wlturbo.OwnedFD, _ uint32) { | |
| 245 | - | if fd == nil { | |
| 246 | - | t.Fatal("FD not assigned") | |
| 247 | - | } | |
| 248 | - | _ = fd.Close() | |
| 249 | - | calls++ | |
| 250 | - | }) | |
| 251 | - | kb.OnKey(func(_, _, key, _ uint32) { | |
| 252 | - | if key != 33 { | |
| 253 | - | t.Errorf("key=%d", key) | |
| 254 | - | } | |
| 255 | - | calls++ | |
| 256 | - | }) | |
| 257 | - | r, w, e := os.Pipe() | |
| 258 | - | if e != nil { | |
| 259 | - | t.Fatal(e) | |
| 260 | - | } | |
| 261 | - | defer r.Close() | |
| 262 | - | send(t, p, frame(kb.ID(), 0, 1, 8), int(w.Fd())) | |
| 263 | - | w.Close() | |
| 264 | - | send(t, p, frame(kb.ID(), 3, 1, 2, 33, 1)) | |
| 265 | - | if e := d.Dispatch(); e != nil { | |
| 266 | - | t.Fatal(e) | |
| 267 | - | } | |
| 268 | - | if e := d.Dispatch(); e != nil { | |
| 269 | - | t.Fatal(e) | |
| 270 | - | } | |
| 271 | - | if calls != 2 { | |
| 272 | - | t.Fatalf("calls=%d", calls) | |
| 273 | - | } | |
| 274 | - | } | |
| 275 | - | func TestMalformedGeneratedPayload(t *testing.T) { | |
| 276 | - | c, p := pair(t) | |
| 277 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 278 | - | if e != nil { | |
| 279 | - | t.Fatal(e) | |
| 280 | - | } | |
| 281 | - | defer d.Close() | |
| 282 | - | receiveRequest(t, p) | |
| 283 | - | kb := core.NewKeyboard(d.Context()) | |
| 284 | - | kb.SetID(d.AllocateID()) | |
| 285 | - | d.Context().Register(kb) | |
| 286 | - | send(t, p, frame(kb.ID(), 3, 1, 2)) | |
| 287 | - | if e := d.Dispatch(); !errors.Is(e, wlturbo.ErrMalformedFrame) { | |
| 288 | - | t.Fatalf("truncated key: %v", e) | |
| 289 | - | } | |
| 290 | - | } | |
| 291 | - | ||
| 292 | - | func TestServerChildEventsAfterOffer(t *testing.T) { | |
| 293 | - | c, p := pair(t) | |
| 294 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 295 | - | if e != nil { | |
| 296 | - | t.Fatal(e) | |
| 297 | - | } | |
| 298 | - | defer d.Close() | |
| 299 | - | receiveRequest(t, p) | |
| 300 | - | device := core.NewDataDevice(d.Context()) | |
| 301 | - | device.SetID(d.AllocateID()) | |
| 302 | - | d.Context().Register(device) | |
| 303 | - | const offerID = 0xff000011 | |
| 304 | - | var offer *core.DataOffer | |
| 305 | - | device.OnDataOffer(func(o *core.DataOffer) { offer = o }) | |
| 306 | - | send(t, p, frame(device.ID(), 0, offerID)) | |
| 307 | - | if e := d.Dispatch(); e != nil { | |
| 308 | - | t.Fatal(e) | |
| 309 | - | } | |
| 310 | - | if offer == nil { | |
| 311 | - | t.Fatal("missing concrete child") | |
| 312 | - | } | |
| 313 | - | got := "" | |
| 314 | - | offer.OnOffer(func(mime string) { got = mime }) | |
| 315 | - | payload := append(frame(offerID, 0), 4, 0, 0, 0, 'a', 'b', 'c', 0) | |
| 316 | - | binary.LittleEndian.PutUint32(payload[4:], uint32(len(payload))<<16) | |
| 317 | - | send(t, p, payload) | |
| 318 | - | if e := d.Dispatch(); e != nil { | |
| 319 | - | t.Fatal(e) | |
| 320 | - | } | |
| 321 | - | if got != "abc" { | |
| 322 | - | t.Fatalf("typed child event: %q", got) | |
| 323 | - | } | |
| 324 | - | } | |
| 325 | - | ||
| 326 | - | func TestRegistryBootstrapAnnouncements(t *testing.T) { | |
| 327 | - | c, p := pair(t) | |
| 328 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 329 | - | if e != nil { | |
| 330 | - | t.Fatal(e) | |
| 331 | - | } | |
| 332 | - | defer d.Close() | |
| 333 | - | receiveRequest(t, p) | |
| 334 | - | var got wlturbo.Global | |
| 335 | - | d.Registry().AddHandler("wl_compositor", func(r *wlturbo.Registry, n, v uint32) { got, _ = r.FindGlobalByName(n) }) | |
| 336 | - | name := "wl_compositor" | |
| 337 | - | body := make([]byte, 4+4+((len(name)+1+3)&^3)+4) | |
| 338 | - | binary.LittleEndian.PutUint32(body, 17) | |
| 339 | - | binary.LittleEndian.PutUint32(body[4:], uint32(len(name)+1)) | |
| 340 | - | copy(body[8:], name) | |
| 341 | - | binary.LittleEndian.PutUint32(body[len(body)-4:], 7) | |
| 342 | - | msg := append(frame(d.Registry().ID(), 0), body...) | |
| 343 | - | binary.LittleEndian.PutUint32(msg[4:], uint32(len(msg))<<16) | |
| 344 | - | send(t, p, msg) | |
| 345 | - | if e := d.Dispatch(); e != nil { | |
| 346 | - | t.Fatal(e) | |
| 347 | - | } | |
| 348 | - | if got.Name != 17 || got.Interface != name || got.Version != 7 { | |
| 349 | - | t.Fatalf("global: %+v", got) | |
| 350 | - | } | |
| 351 | - | send(t, p, frame(d.Registry().ID(), 1, 17)) | |
| 352 | - | if e := d.Dispatch(); e != nil { | |
| 353 | - | t.Fatal(e) | |
| 354 | - | } | |
| 355 | - | if _, ok := d.Registry().FindGlobalByName(17); ok { | |
| 356 | - | t.Fatal("global not removed") | |
| 357 | - | } | |
| 358 | - | send(t, p, frame(d.Registry().ID(), 2)) | |
| 359 | - | if e := d.Dispatch(); !errors.Is(e, wlturbo.ErrUnknownOpcode) { | |
| 360 | - | t.Fatalf("unknown registry opcode: %v", e) | |
| 361 | - | } | |
| 362 | - | } | |
| 363 | - | func TestUnclaimedFirstHandlerFDClosed(t *testing.T) { | |
| 364 | - | c, p := pair(t) | |
| 365 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 366 | - | if e != nil { | |
| 367 | - | t.Fatal(e) | |
| 368 | - | } | |
| 369 | - | defer d.Close() | |
| 370 | - | receiveRequest(t, p) | |
| 371 | - | kb := core.NewKeyboard(d.Context()) | |
| 372 | - | kb.SetID(d.AllocateID()) | |
| 373 | - | d.Context().Register(kb) | |
| 374 | - | kb.OnKeymap(func(_ uint32, fd *wlturbo.OwnedFD, _ uint32) { | |
| 375 | - | if fd == nil { | |
| 376 | - | t.Fatal("missing first owner") | |
| 377 | - | } | |
| 378 | - | }) | |
| 379 | - | kb.OnKeymap(func(_ uint32, fd *wlturbo.OwnedFD, _ uint32) { | |
| 380 | - | if fd != nil { | |
| 381 | - | t.Fatal("duplicate owner") | |
| 382 | - | } | |
| 383 | - | }) | |
| 384 | - | r, w, e := os.Pipe() | |
| 385 | - | if e != nil { | |
| 386 | - | t.Fatal(e) | |
| 387 | - | } | |
| 388 | - | defer r.Close() | |
| 389 | - | send(t, p, frame(kb.ID(), 0, 1, 8), int(w.Fd())) | |
| 390 | - | w.Close() | |
| 391 | - | if e := d.Dispatch(); e != nil { | |
| 392 | - | t.Fatal(e) | |
| 393 | - | } | |
| 394 | - | if e := r.SetReadDeadline(testDeadline()); e != nil { | |
| 395 | - | t.Fatal(e) | |
| 396 | - | } | |
| 397 | - | var b [1]byte | |
| 398 | - | if n, e := r.Read(b[:]); n != 0 || e != io.EOF { | |
| 399 | - | t.Fatalf("unclaimed FD not closed: %d %v", n, e) | |
| 400 | - | } | |
| 401 | - | } | |
| 402 | - | ||
| 403 | - | func TestDestroyedProxyRejectsRequests(t *testing.T) { | |
| 404 | - | c, p := pair(t) | |
| 405 | - | d, err := wlturbo.ConnectFromConn(c) | |
| 406 | - | if err != nil { | |
| 407 | - | t.Fatal(err) | |
| 408 | - | } | |
| 409 | - | defer d.Close() | |
| 410 | - | receiveRequest(t, p) | |
| 411 | - | surface := core.NewSurface(d.Context()) | |
| 412 | - | surface.SetID(d.AllocateID()) | |
| 413 | - | d.Context().Register(surface) | |
| 414 | - | if err := surface.Destroy(); err != nil { | |
| 415 | - | t.Fatal(err) | |
| 416 | - | } | |
| 417 | - | receiveRequest(t, p) | |
| 418 | - | if err := surface.Destroy(); err == nil { | |
| 419 | - | t.Fatal("second destroy succeeded") | |
| 420 | - | } | |
| 421 | - | if err := surface.Commit(); err == nil { | |
| 422 | - | t.Fatal("request on destroyed surface succeeded") | |
| 423 | - | } | |
| 424 | - | if _, err := surface.Frame(); err == nil { | |
| 425 | - | t.Fatal("child request on destroyed surface succeeded") | |
| 426 | - | } | |
| 427 | - | p.SetReadDeadline(time.Now().Add(20 * time.Millisecond)) | |
| 428 | - | _, err = p.Read(make([]byte, 32)) | |
| 429 | - | ne, ok := err.(net.Error) | |
| 430 | - | if !ok || !ne.Timeout() { | |
| 431 | - | t.Fatalf("unexpected bytes on wire: %v", err) | |
| 432 | - | } | |
| 433 | - | } | |
| 434 | - | ||
| 435 | - | func TestConcurrentDestroySendsOnce(t *testing.T) { | |
| 436 | - | c, p := pair(t) | |
| 437 | - | d, err := wlturbo.ConnectFromConn(c) | |
| 438 | - | if err != nil { | |
| 439 | - | t.Fatal(err) | |
| 440 | - | } | |
| 441 | - | defer d.Close() | |
| 442 | - | receiveRequest(t, p) | |
| 443 | - | const rounds, destroyers, committers = 100, 4, 4 | |
| 444 | - | totalCommits := 0 | |
| 445 | - | for round := 0; round < rounds; round++ { | |
| 446 | - | surface := core.NewSurface(d.Context()) | |
| 447 | - | surface.SetID(d.AllocateID()) | |
| 448 | - | d.Context().Register(surface) | |
| 449 | - | start := make(chan struct{}) | |
| 450 | - | destroyed := make(chan error, destroyers) | |
| 451 | - | committed := make(chan error, committers) | |
| 452 | - | for i := 0; i < destroyers; i++ { | |
| 453 | - | go func() { <-start; destroyed <- surface.Destroy() }() | |
| 454 | - | } | |
| 455 | - | for i := 0; i < committers; i++ { | |
| 456 | - | go func() { <-start; committed <- surface.Commit() }() | |
| 457 | - | } | |
| 458 | - | close(start) | |
| 459 | - | okDestroy, okCommit := 0, 0 | |
| 460 | - | for i := 0; i < destroyers; i++ { | |
| 461 | - | if <-destroyed == nil { | |
| 462 | - | okDestroy++ | |
| 463 | - | } | |
| 464 | - | } | |
| 465 | - | for i := 0; i < committers; i++ { | |
| 466 | - | if <-committed == nil { | |
| 467 | - | okCommit++ | |
| 468 | - | } | |
| 469 | - | } | |
| 470 | - | if okDestroy != 1 { | |
| 471 | - | t.Fatalf("round %d: %d destroys succeeded, want 1", round, okDestroy) | |
| 472 | - | } | |
| 473 | - | totalCommits += okCommit | |
| 474 | - | // Decode every frame: exactly okCommit commits (opcode 6), then one | |
| 475 | - | // destroy (opcode 0) for this surface, and nothing after it. | |
| 476 | - | frames := readFrames(t, p, okCommit+1) | |
| 477 | - | for i, f := range frames { | |
| 478 | - | if f.id != surface.ID() { | |
| 479 | - | t.Fatalf("round %d: frame %d targets object %d", round, i, f.id) | |
| 480 | - | } | |
| 481 | - | last := i == len(frames)-1 | |
| 482 | - | if last && f.opcode != 0 || !last && f.opcode != 6 { | |
| 483 | - | t.Fatalf("round %d: frame %d opcode %d (last=%v)", round, i, f.opcode, last) | |
| 484 | - | } | |
| 485 | - | } | |
| 486 | - | p.SetReadDeadline(time.Now().Add(2 * time.Millisecond)) | |
| 487 | - | if n, err := p.Read(make([]byte, 8)); n != 0 { | |
| 488 | - | t.Fatalf("round %d: request after destroy (%d bytes, %v)", round, n, err) | |
| 489 | - | } | |
| 490 | - | p.SetReadDeadline(time.Time{}) | |
| 491 | - | } | |
| 492 | - | // Ordering is only exercised when some commits won the race. | |
| 493 | - | if totalCommits == 0 { | |
| 494 | - | t.Fatal("no commit succeeded in any round; ordering was not exercised") | |
| 495 | - | } | |
| 496 | - | } | |
| 497 | - | ||
| 498 | - | type wireFrame struct { | |
| 499 | - | id uint32 | |
| 500 | - | opcode uint16 | |
| 501 | - | } | |
| 502 | - | ||
| 503 | - | func readFrames(t *testing.T, p *net.UnixConn, n int) []wireFrame { | |
| 504 | - | t.Helper() | |
| 505 | - | p.SetReadDeadline(testDeadline()) | |
| 506 | - | defer p.SetReadDeadline(time.Time{}) | |
| 507 | - | var out []wireFrame | |
| 508 | - | var buf []byte | |
| 509 | - | tmp := make([]byte, 4096) | |
| 510 | - | for len(out) < n { | |
| 511 | - | for len(buf) >= 8 { | |
| 512 | - | size := int(binary.LittleEndian.Uint32(buf[4:8]) >> 16) | |
| 513 | - | if size < 8 || len(buf) < size { | |
| 514 | - | break | |
| 515 | - | } | |
| 516 | - | out = append(out, wireFrame{binary.LittleEndian.Uint32(buf[0:4]), uint16(binary.LittleEndian.Uint32(buf[4:8]))}) | |
| 517 | - | buf = buf[size:] | |
| 518 | - | } | |
| 519 | - | if len(out) >= n { | |
| 520 | - | break | |
| 521 | - | } | |
| 522 | - | m, err := p.Read(tmp) | |
| 523 | - | if err != nil { | |
| 524 | - | t.Fatalf("read frames: got %d of %d: %v", len(out), n, err) | |
| 525 | - | } | |
| 526 | - | buf = append(buf, tmp[:m]...) | |
| 527 | - | } | |
| 528 | - | if len(out) != n || len(buf) != 0 { | |
| 529 | - | t.Fatalf("got %d frames (+%d bytes), want %d", len(out), len(buf), n) | |
| 530 | - | } | |
| 531 | - | return out | |
| 532 | - | } | |
D protocol/core/doc.go +0 -8
| @@ -1,8 +0,0 @@ | |||
| 1 | - | // Package core contains canonical Wayland core protocol bindings generated from | |
| 2 | - | // pinned wayland.xml. Bind globals with display.Registry().Bind and the | |
| 3 | - | // corresponding New* constructor. Client-created and server-created children | |
| 4 | - | // are registered with their concrete generated types; never replace them with | |
| 5 | - | // transport wrappers. On* handlers receive typed values. Received OwnedFDs | |
| 6 | - | // are closed after the event unless a handler calls Take; request FDs are | |
| 7 | - | // transferred (and closed locally) only after a complete successful send. | |
| 8 | - | package core | |
D protocol/core/wayland_generated.go +0 -3995 large diff (3995 lines changed): collapsed
D protocol/cursorshape/cursor-shape-v1.xml +0 -162
| @@ -1,162 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="cursor_shape_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright 2018 The Chromium Authors | |
| 5 | - | Copyright 2023 Simon Ser | |
| 6 | - | ||
| 7 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 8 | - | copy of this software and associated documentation files (the "Software"), | |
| 9 | - | to deal in the Software without restriction, including without limitation | |
| 10 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 11 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 12 | - | Software is furnished to do so, subject to the following conditions: | |
| 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 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 17 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 18 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 19 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 20 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 21 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 22 | - | DEALINGS IN THE SOFTWARE. | |
| 23 | - | </copyright> | |
| 24 | - | ||
| 25 | - | <interface name="wp_cursor_shape_manager_v1" version="2"> | |
| 26 | - | <description summary="cursor shape manager"> | |
| 27 | - | This global offers an alternative, optional way to set cursor images. This | |
| 28 | - | new way uses enumerated cursors instead of a wl_surface like | |
| 29 | - | wl_pointer.set_cursor does. | |
| 30 | - | ||
| 31 | - | Warning! The protocol described in this file is currently in the testing | |
| 32 | - | phase. Backward compatible changes may be added together with the | |
| 33 | - | corresponding interface version bump. Backward incompatible changes can | |
| 34 | - | only be done by creating a new major version of the extension. | |
| 35 | - | </description> | |
| 36 | - | ||
| 37 | - | <request name="destroy" type="destructor"> | |
| 38 | - | <description summary="destroy the manager"> | |
| 39 | - | Destroy the cursor shape manager. | |
| 40 | - | </description> | |
| 41 | - | </request> | |
| 42 | - | ||
| 43 | - | <request name="get_pointer"> | |
| 44 | - | <description summary="manage the cursor shape of a pointer device"> | |
| 45 | - | Obtain a wp_cursor_shape_device_v1 for a wl_pointer object. | |
| 46 | - | ||
| 47 | - | When the pointer capability is removed from the wl_seat, the | |
| 48 | - | wp_cursor_shape_device_v1 object becomes inert. | |
| 49 | - | </description> | |
| 50 | - | <arg name="cursor_shape_device" type="new_id" interface="wp_cursor_shape_device_v1"/> | |
| 51 | - | <arg name="pointer" type="object" interface="wl_pointer"/> | |
| 52 | - | </request> | |
| 53 | - | ||
| 54 | - | <request name="get_tablet_tool_v2"> | |
| 55 | - | <description summary="manage the cursor shape of a tablet tool device"> | |
| 56 | - | Obtain a wp_cursor_shape_device_v1 for a zwp_tablet_tool_v2 object. | |
| 57 | - | ||
| 58 | - | When the zwp_tablet_tool_v2 is removed, the wp_cursor_shape_device_v1 | |
| 59 | - | object becomes inert. | |
| 60 | - | </description> | |
| 61 | - | <arg name="cursor_shape_device" type="new_id" interface="wp_cursor_shape_device_v1"/> | |
| 62 | - | <arg name="tablet_tool" type="object" interface="zwp_tablet_tool_v2"/> | |
| 63 | - | </request> | |
| 64 | - | </interface> | |
| 65 | - | ||
| 66 | - | <interface name="wp_cursor_shape_device_v1" version="2"> | |
| 67 | - | <description summary="cursor shape for a device"> | |
| 68 | - | This interface allows clients to set the cursor shape. | |
| 69 | - | </description> | |
| 70 | - | ||
| 71 | - | <enum name="shape"> | |
| 72 | - | <description summary="cursor shapes"> | |
| 73 | - | This enum describes cursor shapes. | |
| 74 | - | ||
| 75 | - | The names are taken from the CSS W3C specification: | |
| 76 | - | https://w3c.github.io/csswg-drafts/css-ui/#cursor | |
| 77 | - | with a few additions. | |
| 78 | - | ||
| 79 | - | Note that there are some groups of cursor shapes that are related: | |
| 80 | - | The first group is drag-and-drop cursors which are used to indicate | |
| 81 | - | the selected action during dnd operations. The second group is resize | |
| 82 | - | cursors which are used to indicate resizing and moving possibilities | |
| 83 | - | on window borders. It is recommended that the shapes in these groups | |
| 84 | - | should use visually compatible images and metaphors. | |
| 85 | - | </description> | |
| 86 | - | <entry name="default" value="1" summary="default cursor"/> | |
| 87 | - | <entry name="context_menu" value="2" summary="a context menu is available for the object under the cursor"/> | |
| 88 | - | <entry name="help" value="3" summary="help is available for the object under the cursor"/> | |
| 89 | - | <entry name="pointer" value="4" summary="pointer that indicates a link or another interactive element"/> | |
| 90 | - | <entry name="progress" value="5" summary="progress indicator"/> | |
| 91 | - | <entry name="wait" value="6" summary="program is busy, user should wait"/> | |
| 92 | - | <entry name="cell" value="7" summary="a cell or set of cells may be selected"/> | |
| 93 | - | <entry name="crosshair" value="8" summary="simple crosshair"/> | |
| 94 | - | <entry name="text" value="9" summary="text may be selected"/> | |
| 95 | - | <entry name="vertical_text" value="10" summary="vertical text may be selected"/> | |
| 96 | - | <entry name="alias" value="11" summary="drag-and-drop: alias of/shortcut to something is to be created"/> | |
| 97 | - | <entry name="copy" value="12" summary="drag-and-drop: something is to be copied"/> | |
| 98 | - | <entry name="move" value="13" summary="drag-and-drop: something is to be moved"/> | |
| 99 | - | <entry name="no_drop" value="14" summary="drag-and-drop: the dragged item cannot be dropped at the current cursor location"/> | |
| 100 | - | <entry name="not_allowed" value="15" summary="drag-and-drop: the requested action will not be carried out"/> | |
| 101 | - | <entry name="grab" value="16" summary="drag-and-drop: something can be grabbed"/> | |
| 102 | - | <entry name="grabbing" value="17" summary="drag-and-drop: something is being grabbed"/> | |
| 103 | - | <entry name="e_resize" value="18" summary="resizing: the east border is to be moved"/> | |
| 104 | - | <entry name="n_resize" value="19" summary="resizing: the north border is to be moved"/> | |
| 105 | - | <entry name="ne_resize" value="20" summary="resizing: the north-east corner is to be moved"/> | |
| 106 | - | <entry name="nw_resize" value="21" summary="resizing: the north-west corner is to be moved"/> | |
| 107 | - | <entry name="s_resize" value="22" summary="resizing: the south border is to be moved"/> | |
| 108 | - | <entry name="se_resize" value="23" summary="resizing: the south-east corner is to be moved"/> | |
| 109 | - | <entry name="sw_resize" value="24" summary="resizing: the south-west corner is to be moved"/> | |
| 110 | - | <entry name="w_resize" value="25" summary="resizing: the west border is to be moved"/> | |
| 111 | - | <entry name="ew_resize" value="26" summary="resizing: the east and west borders are to be moved"/> | |
| 112 | - | <entry name="ns_resize" value="27" summary="resizing: the north and south borders are to be moved"/> | |
| 113 | - | <entry name="nesw_resize" value="28" summary="resizing: the north-east and south-west corners are to be moved"/> | |
| 114 | - | <entry name="nwse_resize" value="29" summary="resizing: the north-west and south-east corners are to be moved"/> | |
| 115 | - | <entry name="col_resize" value="30" summary="resizing: that the item/column can be resized horizontally"/> | |
| 116 | - | <entry name="row_resize" value="31" summary="resizing: that the item/row can be resized vertically"/> | |
| 117 | - | <entry name="all_scroll" value="32" summary="something can be scrolled in any direction"/> | |
| 118 | - | <entry name="zoom_in" value="33" summary="something can be zoomed in"/> | |
| 119 | - | <entry name="zoom_out" value="34" summary="something can be zoomed out"/> | |
| 120 | - | <entry name="dnd_ask" value="35" summary="drag-and-drop: the user will select which action will be carried out (non-css value)" since="2"/> | |
| 121 | - | <entry name="all_resize" value="36" summary="resizing: something can be moved or resized in any direction (non-css value)" since="2"/> | |
| 122 | - | </enum> | |
| 123 | - | ||
| 124 | - | <enum name="error"> | |
| 125 | - | <entry name="invalid_shape" value="1" | |
| 126 | - | summary="the specified shape value is invalid"/> | |
| 127 | - | </enum> | |
| 128 | - | ||
| 129 | - | <request name="destroy" type="destructor"> | |
| 130 | - | <description summary="destroy the cursor shape device"> | |
| 131 | - | Destroy the cursor shape device. | |
| 132 | - | ||
| 133 | - | The device cursor shape remains unchanged. | |
| 134 | - | </description> | |
| 135 | - | </request> | |
| 136 | - | ||
| 137 | - | <request name="set_shape"> | |
| 138 | - | <description summary="set device cursor to the shape"> | |
| 139 | - | Sets the device cursor to the specified shape. The compositor will | |
| 140 | - | change the cursor image based on the specified shape. | |
| 141 | - | ||
| 142 | - | The cursor actually changes only if the input device focus is one of | |
| 143 | - | the requesting client's surfaces. If any, the previous cursor image | |
| 144 | - | (surface or shape) is replaced. | |
| 145 | - | ||
| 146 | - | The "shape" argument must be a valid enum entry, otherwise the | |
| 147 | - | invalid_shape protocol error is raised. | |
| 148 | - | ||
| 149 | - | This is similar to the wl_pointer.set_cursor and | |
| 150 | - | zwp_tablet_tool_v2.set_cursor requests, but this request accepts a | |
| 151 | - | shape instead of contents in the form of a surface. Clients can mix | |
| 152 | - | set_cursor and set_shape requests. | |
| 153 | - | ||
| 154 | - | The serial parameter must match the latest wl_pointer.enter or | |
| 155 | - | zwp_tablet_tool_v2.proximity_in serial number sent to the client. | |
| 156 | - | Otherwise the request will be ignored. | |
| 157 | - | </description> | |
| 158 | - | <arg name="serial" type="uint" summary="serial number of the enter event"/> | |
| 159 | - | <arg name="shape" type="uint" enum="shape"/> | |
| 160 | - | </request> | |
| 161 | - | </interface> | |
| 162 | - | </protocol> | |
D protocol/cursorshape/cursor-shape-v1_generated.go +0 -257
| @@ -1,257 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: cursor_shape_v1 | |
| 3 | - | // Source: cursor-shape-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright 2018 The Chromium Authors | |
| 7 | - | // Copyright 2023 Simon Ser | |
| 8 | - | // | |
| 9 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 | - | // copy of this software and associated documentation files (the "Software"), | |
| 11 | - | // to deal in the Software without restriction, including without limitation | |
| 12 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 14 | - | // Software is furnished to do so, subject to the following conditions: | |
| 15 | - | // The above copyright notice and this permission notice (including the next | |
| 16 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | // Software. | |
| 18 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 23 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 24 | - | // DEALINGS IN THE SOFTWARE. | |
| 25 | - | ||
| 26 | - | package cursorshape | |
| 27 | - | ||
| 28 | - | import ( | |
| 29 | - | cross_wl_pointer "github.com/bnema/wlturbo/protocol/core" | |
| 30 | - | cross_zwp_tablet_tool_v2 "github.com/bnema/wlturbo/protocol/tablet" | |
| 31 | - | "github.com/bnema/wlturbo/wl" | |
| 32 | - | ) | |
| 33 | - | ||
| 34 | - | // SHAPE_DEFAULT is the shape default value. | |
| 35 | - | const SHAPE_DEFAULT = 1 | |
| 36 | - | ||
| 37 | - | // SHAPE_CONTEXT_MENU is the shape context_menu value. | |
| 38 | - | const SHAPE_CONTEXT_MENU = 2 | |
| 39 | - | ||
| 40 | - | // SHAPE_HELP is the shape help value. | |
| 41 | - | const SHAPE_HELP = 3 | |
| 42 | - | ||
| 43 | - | // SHAPE_POINTER is the shape pointer value. | |
| 44 | - | const SHAPE_POINTER = 4 | |
| 45 | - | ||
| 46 | - | // SHAPE_PROGRESS is the shape progress value. | |
| 47 | - | const SHAPE_PROGRESS = 5 | |
| 48 | - | ||
| 49 | - | // SHAPE_WAIT is the shape wait value. | |
| 50 | - | const SHAPE_WAIT = 6 | |
| 51 | - | ||
| 52 | - | // SHAPE_CELL is the shape cell value. | |
| 53 | - | const SHAPE_CELL = 7 | |
| 54 | - | ||
| 55 | - | // SHAPE_CROSSHAIR is the shape crosshair value. | |
| 56 | - | const SHAPE_CROSSHAIR = 8 | |
| 57 | - | ||
| 58 | - | // SHAPE_TEXT is the shape text value. | |
| 59 | - | const SHAPE_TEXT = 9 | |
| 60 | - | ||
| 61 | - | // SHAPE_VERTICAL_TEXT is the shape vertical_text value. | |
| 62 | - | const SHAPE_VERTICAL_TEXT = 10 | |
| 63 | - | ||
| 64 | - | // SHAPE_ALIAS is the shape alias value. | |
| 65 | - | const SHAPE_ALIAS = 11 | |
| 66 | - | ||
| 67 | - | // SHAPE_COPY is the shape copy value. | |
| 68 | - | const SHAPE_COPY = 12 | |
| 69 | - | ||
| 70 | - | // SHAPE_MOVE is the shape move value. | |
| 71 | - | const SHAPE_MOVE = 13 | |
| 72 | - | ||
| 73 | - | // SHAPE_NO_DROP is the shape no_drop value. | |
| 74 | - | const SHAPE_NO_DROP = 14 | |
| 75 | - | ||
| 76 | - | // SHAPE_NOT_ALLOWED is the shape not_allowed value. | |
| 77 | - | const SHAPE_NOT_ALLOWED = 15 | |
| 78 | - | ||
| 79 | - | // SHAPE_GRAB is the shape grab value. | |
| 80 | - | const SHAPE_GRAB = 16 | |
| 81 | - | ||
| 82 | - | // SHAPE_GRABBING is the shape grabbing value. | |
| 83 | - | const SHAPE_GRABBING = 17 | |
| 84 | - | ||
| 85 | - | // SHAPE_E_RESIZE is the shape e_resize value. | |
| 86 | - | const SHAPE_E_RESIZE = 18 | |
| 87 | - | ||
| 88 | - | // SHAPE_N_RESIZE is the shape n_resize value. | |
| 89 | - | const SHAPE_N_RESIZE = 19 | |
| 90 | - | ||
| 91 | - | // SHAPE_NE_RESIZE is the shape ne_resize value. | |
| 92 | - | const SHAPE_NE_RESIZE = 20 | |
| 93 | - | ||
| 94 | - | // SHAPE_NW_RESIZE is the shape nw_resize value. | |
| 95 | - | const SHAPE_NW_RESIZE = 21 | |
| 96 | - | ||
| 97 | - | // SHAPE_S_RESIZE is the shape s_resize value. | |
| 98 | - | const SHAPE_S_RESIZE = 22 | |
| 99 | - | ||
| 100 | - | // SHAPE_SE_RESIZE is the shape se_resize value. | |
| 101 | - | const SHAPE_SE_RESIZE = 23 | |
| 102 | - | ||
| 103 | - | // SHAPE_SW_RESIZE is the shape sw_resize value. | |
| 104 | - | const SHAPE_SW_RESIZE = 24 | |
| 105 | - | ||
| 106 | - | // SHAPE_W_RESIZE is the shape w_resize value. | |
| 107 | - | const SHAPE_W_RESIZE = 25 | |
| 108 | - | ||
| 109 | - | // SHAPE_EW_RESIZE is the shape ew_resize value. | |
| 110 | - | const SHAPE_EW_RESIZE = 26 | |
| 111 | - | ||
| 112 | - | // SHAPE_NS_RESIZE is the shape ns_resize value. | |
| 113 | - | const SHAPE_NS_RESIZE = 27 | |
| 114 | - | ||
| 115 | - | // SHAPE_NESW_RESIZE is the shape nesw_resize value. | |
| 116 | - | const SHAPE_NESW_RESIZE = 28 | |
| 117 | - | ||
| 118 | - | // SHAPE_NWSE_RESIZE is the shape nwse_resize value. | |
| 119 | - | const SHAPE_NWSE_RESIZE = 29 | |
| 120 | - | ||
| 121 | - | // SHAPE_COL_RESIZE is the shape col_resize value. | |
| 122 | - | const SHAPE_COL_RESIZE = 30 | |
| 123 | - | ||
| 124 | - | // SHAPE_ROW_RESIZE is the shape row_resize value. | |
| 125 | - | const SHAPE_ROW_RESIZE = 31 | |
| 126 | - | ||
| 127 | - | // SHAPE_ALL_SCROLL is the shape all_scroll value. | |
| 128 | - | const SHAPE_ALL_SCROLL = 32 | |
| 129 | - | ||
| 130 | - | // SHAPE_ZOOM_IN is the shape zoom_in value. | |
| 131 | - | const SHAPE_ZOOM_IN = 33 | |
| 132 | - | ||
| 133 | - | // SHAPE_ZOOM_OUT is the shape zoom_out value. | |
| 134 | - | const SHAPE_ZOOM_OUT = 34 | |
| 135 | - | ||
| 136 | - | // SHAPE_DND_ASK is the shape dnd_ask value. | |
| 137 | - | const SHAPE_DND_ASK = 35 | |
| 138 | - | ||
| 139 | - | // SHAPE_ALL_RESIZE is the shape all_resize value. | |
| 140 | - | const SHAPE_ALL_RESIZE = 36 | |
| 141 | - | ||
| 142 | - | // ERROR_INVALID_SHAPE is the error invalid_shape value. | |
| 143 | - | const ERROR_INVALID_SHAPE = 1 | |
| 144 | - | ||
| 145 | - | // WpCursorShapeManagerInterface is the protocol interface name. | |
| 146 | - | const WpCursorShapeManagerInterface = "wp_cursor_shape_manager_v1" | |
| 147 | - | ||
| 148 | - | // WpCursorShapeManager is the generated binding for wp_cursor_shape_manager_v1 version 2. | |
| 149 | - | type WpCursorShapeManager struct { | |
| 150 | - | wl.BaseProxy | |
| 151 | - | } | |
| 152 | - | ||
| 153 | - | // NewWpCursorShapeManager returns an unbound WpCursorShapeManager. | |
| 154 | - | func NewWpCursorShapeManager(ctx *wl.Context) *WpCursorShapeManager { | |
| 155 | - | obj := &WpCursorShapeManager{} | |
| 156 | - | obj.SetContext(ctx) | |
| 157 | - | ctx.Register(obj) | |
| 158 | - | return obj | |
| 159 | - | } | |
| 160 | - | ||
| 161 | - | // Destroy the cursor shape manager. | |
| 162 | - | func (o *WpCursorShapeManager) Destroy() error { | |
| 163 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_cursor_shape_manager_v1.destroy", Destructor: true}); err != nil { | |
| 164 | - | return err | |
| 165 | - | } | |
| 166 | - | return nil | |
| 167 | - | } | |
| 168 | - | ||
| 169 | - | // Obtain a wp_cursor_shape_device_v1 for a wl_pointer object. When the pointer capability is removed from the wl_seat, the wp_cursor_shape_device_v1 object becomes inert. | |
| 170 | - | func (o *WpCursorShapeManager) GetPointer(pointer *cross_wl_pointer.Pointer) (*WpCursorShapeDevice, error) { | |
| 171 | - | var arg1 wl.Object | |
| 172 | - | if pointer != nil { | |
| 173 | - | arg1 = pointer | |
| 174 | - | } | |
| 175 | - | child := &WpCursorShapeDevice{} | |
| 176 | - | child.SetContext(o.Context()) | |
| 177 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_cursor_shape_manager_v1.get_pointer", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 178 | - | return nil, err | |
| 179 | - | } | |
| 180 | - | return child, nil | |
| 181 | - | } | |
| 182 | - | ||
| 183 | - | // Obtain a wp_cursor_shape_device_v1 for a zwp_tablet_tool_v2 object. When the zwp_tablet_tool_v2 is removed, the wp_cursor_shape_device_v1 object becomes inert. | |
| 184 | - | func (o *WpCursorShapeManager) GetTabletTool(tabletTool *cross_zwp_tablet_tool_v2.TabletTool) (*WpCursorShapeDevice, error) { | |
| 185 | - | var arg1 wl.Object | |
| 186 | - | if tabletTool != nil { | |
| 187 | - | arg1 = tabletTool | |
| 188 | - | } | |
| 189 | - | child := &WpCursorShapeDevice{} | |
| 190 | - | child.SetContext(o.Context()) | |
| 191 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_cursor_shape_manager_v1.get_tablet_tool_v2", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 192 | - | return nil, err | |
| 193 | - | } | |
| 194 | - | return child, nil | |
| 195 | - | } | |
| 196 | - | ||
| 197 | - | // EventSignature returns the declared event argument types in wire order. | |
| 198 | - | func (o *WpCursorShapeManager) EventSignature(opcode uint16) (string, bool) { | |
| 199 | - | switch opcode { | |
| 200 | - | default: | |
| 201 | - | return "", false | |
| 202 | - | } | |
| 203 | - | } | |
| 204 | - | ||
| 205 | - | // Dispatch decodes one event on wp_cursor_shape_manager_v1 and calls the registered handlers. | |
| 206 | - | func (o *WpCursorShapeManager) Dispatch(event *wl.Event) { | |
| 207 | - | switch event.Opcode { | |
| 208 | - | default: | |
| 209 | - | } | |
| 210 | - | } | |
| 211 | - | ||
| 212 | - | // WpCursorShapeDeviceInterface is the protocol interface name. | |
| 213 | - | const WpCursorShapeDeviceInterface = "wp_cursor_shape_device_v1" | |
| 214 | - | ||
| 215 | - | // WpCursorShapeDevice is the generated binding for wp_cursor_shape_device_v1 version 2. | |
| 216 | - | type WpCursorShapeDevice struct { | |
| 217 | - | wl.BaseProxy | |
| 218 | - | } | |
| 219 | - | ||
| 220 | - | // NewWpCursorShapeDevice returns an unbound WpCursorShapeDevice. | |
| 221 | - | func NewWpCursorShapeDevice(ctx *wl.Context) *WpCursorShapeDevice { | |
| 222 | - | obj := &WpCursorShapeDevice{} | |
| 223 | - | obj.SetContext(ctx) | |
| 224 | - | ctx.Register(obj) | |
| 225 | - | return obj | |
| 226 | - | } | |
| 227 | - | ||
| 228 | - | // Destroy the cursor shape device. The device cursor shape remains unchanged. | |
| 229 | - | func (o *WpCursorShapeDevice) Destroy() error { | |
| 230 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_cursor_shape_device_v1.destroy", Destructor: true}); err != nil { | |
| 231 | - | return err | |
| 232 | - | } | |
| 233 | - | return nil | |
| 234 | - | } | |
| 235 | - | ||
| 236 | - | // Sets the device cursor to the specified shape. The compositor will change the cursor image based on the specified shape. The cursor actually changes only if the input device focus is one of the requesting client's surfaces. If any, the previous cursor image (surface or shape) is replaced. The "shape" argument must be a valid enum entry, otherwise the invalid_shape protocol error is raised. This is similar to the wl_pointer.set_cursor and zwp_tablet_tool_v2.set_cursor requests, but this request accepts a shape instead of contents in the form of a surface. Clients can mix set_cursor and set_shape requests. The serial parameter must match the latest wl_pointer.enter or zwp_tablet_tool_v2.proximity_in serial number sent to the client. Otherwise the request will be ignored. | |
| 237 | - | func (o *WpCursorShapeDevice) SetShape(serial uint32, shape uint32) error { | |
| 238 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_cursor_shape_device_v1.set_shape"}, wl.ArgUint(serial), wl.ArgUint(shape)); err != nil { | |
| 239 | - | return err | |
| 240 | - | } | |
| 241 | - | return nil | |
| 242 | - | } | |
| 243 | - | ||
| 244 | - | // EventSignature returns the declared event argument types in wire order. | |
| 245 | - | func (o *WpCursorShapeDevice) EventSignature(opcode uint16) (string, bool) { | |
| 246 | - | switch opcode { | |
| 247 | - | default: | |
| 248 | - | return "", false | |
| 249 | - | } | |
| 250 | - | } | |
| 251 | - | ||
| 252 | - | // Dispatch decodes one event on wp_cursor_shape_device_v1 and calls the registered handlers. | |
| 253 | - | func (o *WpCursorShapeDevice) Dispatch(event *wl.Event) { | |
| 254 | - | switch event.Opcode { | |
| 255 | - | default: | |
| 256 | - | } | |
| 257 | - | } | |
D protocol/datacontrol/ext-data-control-v1.xml +0 -276
| @@ -1,276 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="ext_data_control_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2018 Simon Ser | |
| 5 | - | Copyright © 2019 Ivan Molodetskikh | |
| 6 | - | Copyright © 2024 Neal Gompa | |
| 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 | - | <description summary="control data devices"> | |
| 31 | - | This protocol allows a privileged client to control data devices. In | |
| 32 | - | particular, the client will be able to manage the current selection and take | |
| 33 | - | the role of a clipboard manager. | |
| 34 | - | ||
| 35 | - | Warning! The protocol described in this file is currently in the testing | |
| 36 | - | phase. Backward compatible changes may be added together with the | |
| 37 | - | corresponding interface version bump. Backward incompatible changes can | |
| 38 | - | only be done by creating a new major version of the extension. | |
| 39 | - | </description> | |
| 40 | - | ||
| 41 | - | <interface name="ext_data_control_manager_v1" version="1"> | |
| 42 | - | <description summary="manager to control data devices"> | |
| 43 | - | This interface is a manager that allows creating per-seat data device | |
| 44 | - | controls. | |
| 45 | - | </description> | |
| 46 | - | ||
| 47 | - | <request name="create_data_source"> | |
| 48 | - | <description summary="create a new data source"> | |
| 49 | - | Create a new data source. | |
| 50 | - | </description> | |
| 51 | - | <arg name="id" type="new_id" interface="ext_data_control_source_v1" | |
| 52 | - | summary="data source to create"/> | |
| 53 | - | </request> | |
| 54 | - | ||
| 55 | - | <request name="get_data_device"> | |
| 56 | - | <description summary="get a data device for a seat"> | |
| 57 | - | Create a data device that can be used to manage a seat's selection. | |
| 58 | - | </description> | |
| 59 | - | <arg name="id" type="new_id" interface="ext_data_control_device_v1"/> | |
| 60 | - | <arg name="seat" type="object" interface="wl_seat"/> | |
| 61 | - | </request> | |
| 62 | - | ||
| 63 | - | <request name="destroy" type="destructor"> | |
| 64 | - | <description summary="destroy the manager"> | |
| 65 | - | All objects created by the manager will still remain valid, until their | |
| 66 | - | appropriate destroy request has been called. | |
| 67 | - | </description> | |
| 68 | - | </request> | |
| 69 | - | </interface> | |
| 70 | - | ||
| 71 | - | <interface name="ext_data_control_device_v1" version="1"> | |
| 72 | - | <description summary="manage a data device for a seat"> | |
| 73 | - | This interface allows a client to manage a seat's selection. | |
| 74 | - | ||
| 75 | - | When the seat is destroyed, this object becomes inert. | |
| 76 | - | </description> | |
| 77 | - | ||
| 78 | - | <request name="set_selection"> | |
| 79 | - | <description summary="copy data to the selection"> | |
| 80 | - | This request asks the compositor to set the selection to the data from | |
| 81 | - | the source on behalf of the client. | |
| 82 | - | ||
| 83 | - | The given source may not be used in any further set_selection or | |
| 84 | - | set_primary_selection requests. Attempting to use a previously used | |
| 85 | - | source triggers the used_source protocol error. | |
| 86 | - | ||
| 87 | - | To unset the selection, set the source to NULL. | |
| 88 | - | </description> | |
| 89 | - | <arg name="source" type="object" interface="ext_data_control_source_v1" | |
| 90 | - | allow-null="true"/> | |
| 91 | - | </request> | |
| 92 | - | ||
| 93 | - | <request name="destroy" type="destructor"> | |
| 94 | - | <description summary="destroy this data device"> | |
| 95 | - | Destroys the data device object. | |
| 96 | - | </description> | |
| 97 | - | </request> | |
| 98 | - | ||
| 99 | - | <event name="data_offer"> | |
| 100 | - | <description summary="introduce a new ext_data_control_offer"> | |
| 101 | - | The data_offer event introduces a new ext_data_control_offer object, | |
| 102 | - | which will subsequently be used in either the | |
| 103 | - | ext_data_control_device.selection event (for the regular clipboard | |
| 104 | - | selections) or the ext_data_control_device.primary_selection event (for | |
| 105 | - | the primary clipboard selections). Immediately following the | |
| 106 | - | ext_data_control_device.data_offer event, the new data_offer object | |
| 107 | - | will send out ext_data_control_offer.offer events to describe the MIME | |
| 108 | - | types it offers. | |
| 109 | - | </description> | |
| 110 | - | <arg name="id" type="new_id" interface="ext_data_control_offer_v1"/> | |
| 111 | - | </event> | |
| 112 | - | ||
| 113 | - | <event name="selection"> | |
| 114 | - | <description summary="advertise new selection"> | |
| 115 | - | The selection event is sent out to notify the client of a new | |
| 116 | - | ext_data_control_offer for the selection for this device. The | |
| 117 | - | ext_data_control_device.data_offer and the ext_data_control_offer.offer | |
| 118 | - | events are sent out immediately before this event to introduce the data | |
| 119 | - | offer object. The selection event is sent to a client when a new | |
| 120 | - | selection is set. The ext_data_control_offer is valid until a new | |
| 121 | - | ext_data_control_offer or NULL is received. The client must destroy the | |
| 122 | - | previous selection ext_data_control_offer, if any, upon receiving this | |
| 123 | - | event. Regardless, the previous selection will be ignored once a new | |
| 124 | - | selection ext_data_control_offer is received. | |
| 125 | - | ||
| 126 | - | The first selection event is sent upon binding the | |
| 127 | - | ext_data_control_device object. | |
| 128 | - | </description> | |
| 129 | - | <arg name="id" type="object" interface="ext_data_control_offer_v1" | |
| 130 | - | allow-null="true"/> | |
| 131 | - | </event> | |
| 132 | - | ||
| 133 | - | <event name="finished"> | |
| 134 | - | <description summary="this data control is no longer valid"> | |
| 135 | - | This data control object is no longer valid and should be destroyed by | |
| 136 | - | the client. | |
| 137 | - | </description> | |
| 138 | - | </event> | |
| 139 | - | ||
| 140 | - | <event name="primary_selection"> | |
| 141 | - | <description summary="advertise new primary selection"> | |
| 142 | - | The primary_selection event is sent out to notify the client of a new | |
| 143 | - | ext_data_control_offer for the primary selection for this device. The | |
| 144 | - | ext_data_control_device.data_offer and the ext_data_control_offer.offer | |
| 145 | - | events are sent out immediately before this event to introduce the data | |
| 146 | - | offer object. The primary_selection event is sent to a client when a | |
| 147 | - | new primary selection is set. The ext_data_control_offer is valid until | |
| 148 | - | a new ext_data_control_offer or NULL is received. The client must | |
| 149 | - | destroy the previous primary selection ext_data_control_offer, if any, | |
| 150 | - | upon receiving this event. Regardless, the previous primary selection | |
| 151 | - | will be ignored once a new primary selection ext_data_control_offer is | |
| 152 | - | received. | |
| 153 | - | ||
| 154 | - | If the compositor supports primary selection, the first | |
| 155 | - | primary_selection event is sent upon binding the | |
| 156 | - | ext_data_control_device object. | |
| 157 | - | </description> | |
| 158 | - | <arg name="id" type="object" interface="ext_data_control_offer_v1" | |
| 159 | - | allow-null="true"/> | |
| 160 | - | </event> | |
| 161 | - | ||
| 162 | - | <request name="set_primary_selection"> | |
| 163 | - | <description summary="copy data to the primary selection"> | |
| 164 | - | This request asks the compositor to set the primary selection to the | |
| 165 | - | data from the source on behalf of the client. | |
| 166 | - | ||
| 167 | - | The given source may not be used in any further set_selection or | |
| 168 | - | set_primary_selection requests. Attempting to use a previously used | |
| 169 | - | source triggers the used_source protocol error. | |
| 170 | - | ||
| 171 | - | To unset the primary selection, set the source to NULL. | |
| 172 | - | ||
| 173 | - | The compositor will ignore this request if it does not support primary | |
| 174 | - | selection. | |
| 175 | - | </description> | |
| 176 | - | <arg name="source" type="object" interface="ext_data_control_source_v1" | |
| 177 | - | allow-null="true"/> | |
| 178 | - | </request> | |
| 179 | - | ||
| 180 | - | <enum name="error"> | |
| 181 | - | <entry name="used_source" value="1" | |
| 182 | - | summary="source given to set_selection or set_primary_selection was already used before"/> | |
| 183 | - | </enum> | |
| 184 | - | </interface> | |
| 185 | - | ||
| 186 | - | <interface name="ext_data_control_source_v1" version="1"> | |
| 187 | - | <description summary="offer to transfer data"> | |
| 188 | - | The ext_data_control_source object is the source side of a | |
| 189 | - | ext_data_control_offer. It is created by the source client in a data | |
| 190 | - | transfer and provides a way to describe the offered data and a way to | |
| 191 | - | respond to requests to transfer the data. | |
| 192 | - | </description> | |
| 193 | - | ||
| 194 | - | <enum name="error"> | |
| 195 | - | <entry name="invalid_offer" value="1" | |
| 196 | - | summary="offer sent after ext_data_control_device.set_selection"/> | |
| 197 | - | </enum> | |
| 198 | - | ||
| 199 | - | <request name="offer"> | |
| 200 | - | <description summary="add an offered MIME type"> | |
| 201 | - | This request adds a MIME type to the set of MIME types advertised to | |
| 202 | - | targets. Can be called several times to offer multiple types. | |
| 203 | - | ||
| 204 | - | Calling this after ext_data_control_device.set_selection is a protocol | |
| 205 | - | error. | |
| 206 | - | </description> | |
| 207 | - | <arg name="mime_type" type="string" | |
| 208 | - | summary="MIME type offered by the data source"/> | |
| 209 | - | </request> | |
| 210 | - | ||
| 211 | - | <request name="destroy" type="destructor"> | |
| 212 | - | <description summary="destroy this source"> | |
| 213 | - | Destroys the data source object. | |
| 214 | - | </description> | |
| 215 | - | </request> | |
| 216 | - | ||
| 217 | - | <event name="send"> | |
| 218 | - | <description summary="send the data"> | |
| 219 | - | Request for data from the client. Send the data as the specified MIME | |
| 220 | - | type over the passed file descriptor, then close it. | |
| 221 | - | </description> | |
| 222 | - | <arg name="mime_type" type="string" summary="MIME type for the data"/> | |
| 223 | - | <arg name="fd" type="fd" summary="file descriptor for the data"/> | |
| 224 | - | </event> | |
| 225 | - | ||
| 226 | - | <event name="cancelled"> | |
| 227 | - | <description summary="selection was cancelled"> | |
| 228 | - | This data source is no longer valid. The data source has been replaced | |
| 229 | - | by another data source. | |
| 230 | - | ||
| 231 | - | The client should clean up and destroy this data source. | |
| 232 | - | </description> | |
| 233 | - | </event> | |
| 234 | - | </interface> | |
| 235 | - | ||
| 236 | - | <interface name="ext_data_control_offer_v1" version="1"> | |
| 237 | - | <description summary="offer to transfer data"> | |
| 238 | - | A ext_data_control_offer represents a piece of data offered for transfer | |
| 239 | - | by another client (the source client). The offer describes the different | |
| 240 | - | MIME types that the data can be converted to and provides the mechanism | |
| 241 | - | for transferring the data directly from the source client. | |
| 242 | - | </description> | |
| 243 | - | ||
| 244 | - | <request name="receive"> | |
| 245 | - | <description summary="request that the data is transferred"> | |
| 246 | - | To transfer the offered data, the client issues this request and | |
| 247 | - | indicates the MIME type it wants to receive. The transfer happens | |
| 248 | - | through the passed file descriptor (typically created with the pipe | |
| 249 | - | system call). The source client writes the data in the MIME type | |
| 250 | - | representation requested and then closes the file descriptor. | |
| 251 | - | ||
| 252 | - | The receiving client reads from the read end of the pipe until EOF and | |
| 253 | - | then closes its end, at which point the transfer is complete. | |
| 254 | - | ||
| 255 | - | This request may happen multiple times for different MIME types. | |
| 256 | - | </description> | |
| 257 | - | <arg name="mime_type" type="string" | |
| 258 | - | summary="MIME type desired by receiver"/> | |
| 259 | - | <arg name="fd" type="fd" summary="file descriptor for data transfer"/> | |
| 260 | - | </request> | |
| 261 | - | ||
| 262 | - | <request name="destroy" type="destructor"> | |
| 263 | - | <description summary="destroy this offer"> | |
| 264 | - | Destroys the data offer object. | |
| 265 | - | </description> | |
| 266 | - | </request> | |
| 267 | - | ||
| 268 | - | <event name="offer"> | |
| 269 | - | <description summary="advertise offered MIME type"> | |
| 270 | - | Sent immediately after creating the ext_data_control_offer object. | |
| 271 | - | One event per offered MIME type. | |
| 272 | - | </description> | |
| 273 | - | <arg name="mime_type" type="string" summary="offered MIME type"/> | |
| 274 | - | </event> | |
| 275 | - | </interface> | |
| 276 | - | </protocol> | |
D protocol/datacontrol/ext-data-control-v1_generated.go +0 -505
| @@ -1,505 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: ext_data_control_v1 | |
| 3 | - | // Source: ext-data-control-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2018 Simon Ser | |
| 7 | - | // Copyright © 2019 Ivan Molodetskikh | |
| 8 | - | // Copyright © 2024 Neal Gompa | |
| 9 | - | // | |
| 10 | - | // Permission to use, copy, modify, distribute, and sell this | |
| 11 | - | // software and its documentation for any purpose is hereby granted | |
| 12 | - | // without fee, provided that the above copyright notice appear in | |
| 13 | - | // all copies and that both that copyright notice and this permission | |
| 14 | - | // notice appear in supporting documentation, and that the name of | |
| 15 | - | // the copyright holders not be used in advertising or publicity | |
| 16 | - | // pertaining to distribution of the software without specific, | |
| 17 | - | // written prior permission. The copyright holders make no | |
| 18 | - | // representations about the suitability of this software for any | |
| 19 | - | // purpose. It is provided "as is" without express or implied | |
| 20 | - | // warranty. | |
| 21 | - | // | |
| 22 | - | // THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | |
| 23 | - | // SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
| 24 | - | // FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 25 | - | // SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 26 | - | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |
| 27 | - | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
| 28 | - | // ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | |
| 29 | - | // THIS SOFTWARE. | |
| 30 | - | ||
| 31 | - | package datacontrol | |
| 32 | - | ||
| 33 | - | import ( | |
| 34 | - | "sync" | |
| 35 | - | ||
| 36 | - | cross_wl_seat "github.com/bnema/wlturbo/protocol/core" | |
| 37 | - | "github.com/bnema/wlturbo/wl" | |
| 38 | - | ) | |
| 39 | - | ||
| 40 | - | // ERROR_USED_SOURCE is the error used_source value. | |
| 41 | - | const ERROR_USED_SOURCE = 1 | |
| 42 | - | ||
| 43 | - | // ERROR_INVALID_OFFER is the error invalid_offer value. | |
| 44 | - | const ERROR_INVALID_OFFER = 1 | |
| 45 | - | ||
| 46 | - | // ExtDataControlManagerInterface is the protocol interface name. | |
| 47 | - | const ExtDataControlManagerInterface = "ext_data_control_manager_v1" | |
| 48 | - | ||
| 49 | - | // ExtDataControlManager is the generated binding for ext_data_control_manager_v1 version 1. | |
| 50 | - | type ExtDataControlManager struct { | |
| 51 | - | wl.BaseProxy | |
| 52 | - | } | |
| 53 | - | ||
| 54 | - | // NewExtDataControlManager returns an unbound ExtDataControlManager. | |
| 55 | - | func NewExtDataControlManager(ctx *wl.Context) *ExtDataControlManager { | |
| 56 | - | obj := &ExtDataControlManager{} | |
| 57 | - | obj.SetContext(ctx) | |
| 58 | - | ctx.Register(obj) | |
| 59 | - | return obj | |
| 60 | - | } | |
| 61 | - | ||
| 62 | - | // Create a new data source. | |
| 63 | - | func (o *ExtDataControlManager) CreateDataSource() (*ExtDataControlSource, error) { | |
| 64 | - | child := &ExtDataControlSource{} | |
| 65 | - | child.SetContext(o.Context()) | |
| 66 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_data_control_manager_v1.create_data_source", Child: child}, wl.ArgObject(child)); err != nil { | |
| 67 | - | return nil, err | |
| 68 | - | } | |
| 69 | - | return child, nil | |
| 70 | - | } | |
| 71 | - | ||
| 72 | - | // Create a data device that can be used to manage a seat's selection. | |
| 73 | - | func (o *ExtDataControlManager) GetDataDevice(seat *cross_wl_seat.Seat) (*ExtDataControlDevice, error) { | |
| 74 | - | var arg1 wl.Object | |
| 75 | - | if seat != nil { | |
| 76 | - | arg1 = seat | |
| 77 | - | } | |
| 78 | - | child := &ExtDataControlDevice{} | |
| 79 | - | child.SetContext(o.Context()) | |
| 80 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_data_control_manager_v1.get_data_device", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 81 | - | return nil, err | |
| 82 | - | } | |
| 83 | - | return child, nil | |
| 84 | - | } | |
| 85 | - | ||
| 86 | - | // All objects created by the manager will still remain valid, until their appropriate destroy request has been called. | |
| 87 | - | func (o *ExtDataControlManager) Destroy() error { | |
| 88 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "ext_data_control_manager_v1.destroy", Destructor: true}); err != nil { | |
| 89 | - | return err | |
| 90 | - | } | |
| 91 | - | return nil | |
| 92 | - | } | |
| 93 | - | ||
| 94 | - | // EventSignature returns the declared event argument types in wire order. | |
| 95 | - | func (o *ExtDataControlManager) EventSignature(opcode uint16) (string, bool) { | |
| 96 | - | switch opcode { | |
| 97 | - | default: | |
| 98 | - | return "", false | |
| 99 | - | } | |
| 100 | - | } | |
| 101 | - | ||
| 102 | - | // Dispatch decodes one event on ext_data_control_manager_v1 and calls the registered handlers. | |
| 103 | - | func (o *ExtDataControlManager) Dispatch(event *wl.Event) { | |
| 104 | - | switch event.Opcode { | |
| 105 | - | default: | |
| 106 | - | } | |
| 107 | - | } | |
| 108 | - | ||
| 109 | - | // ExtDataControlDeviceInterface is the protocol interface name. | |
| 110 | - | const ExtDataControlDeviceInterface = "ext_data_control_device_v1" | |
| 111 | - | ||
| 112 | - | // ExtDataControlDevice is the generated binding for ext_data_control_device_v1 version 1. | |
| 113 | - | type ExtDataControlDevice struct { | |
| 114 | - | wl.BaseProxy | |
| 115 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 116 | - | // handlers while another goroutine dispatches events. | |
| 117 | - | handlersMu sync.Mutex | |
| 118 | - | onDataOffer []func(idObject *ExtDataControlOffer) | |
| 119 | - | onSelection []func(idID uint32) | |
| 120 | - | onFinished []func() | |
| 121 | - | onPrimarySelection []func(idID uint32) | |
| 122 | - | } | |
| 123 | - | ||
| 124 | - | // NewExtDataControlDevice returns an unbound ExtDataControlDevice. | |
| 125 | - | func NewExtDataControlDevice(ctx *wl.Context) *ExtDataControlDevice { | |
| 126 | - | obj := &ExtDataControlDevice{} | |
| 127 | - | obj.SetContext(ctx) | |
| 128 | - | ctx.Register(obj) | |
| 129 | - | return obj | |
| 130 | - | } | |
| 131 | - | ||
| 132 | - | // This request asks the compositor to set the selection to the data from the source on behalf of the client. The given source may not be used in any further set_selection or set_primary_selection requests. Attempting to use a previously used source triggers the used_source protocol error. To unset the selection, set the source to NULL. | |
| 133 | - | func (o *ExtDataControlDevice) SetSelection(source *ExtDataControlSource) error { | |
| 134 | - | var arg0 wl.Object | |
| 135 | - | if source != nil { | |
| 136 | - | arg0 = source | |
| 137 | - | } | |
| 138 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_data_control_device_v1.set_selection"}, wl.ArgObject(arg0)); err != nil { | |
| 139 | - | return err | |
| 140 | - | } | |
| 141 | - | return nil | |
| 142 | - | } | |
| 143 | - | ||
| 144 | - | // Destroys the data device object. | |
| 145 | - | func (o *ExtDataControlDevice) Destroy() error { | |
| 146 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_data_control_device_v1.destroy", Destructor: true}); err != nil { | |
| 147 | - | return err | |
| 148 | - | } | |
| 149 | - | return nil | |
| 150 | - | } | |
| 151 | - | ||
| 152 | - | // This request asks the compositor to set the primary selection to the data from the source on behalf of the client. The given source may not be used in any further set_selection or set_primary_selection requests. Attempting to use a previously used source triggers the used_source protocol error. To unset the primary selection, set the source to NULL. The compositor will ignore this request if it does not support primary selection. | |
| 153 | - | func (o *ExtDataControlDevice) SetPrimarySelection(source *ExtDataControlSource) error { | |
| 154 | - | var arg0 wl.Object | |
| 155 | - | if source != nil { | |
| 156 | - | arg0 = source | |
| 157 | - | } | |
| 158 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "ext_data_control_device_v1.set_primary_selection"}, wl.ArgObject(arg0)); err != nil { | |
| 159 | - | return err | |
| 160 | - | } | |
| 161 | - | return nil | |
| 162 | - | } | |
| 163 | - | ||
| 164 | - | // OnDataOffer registers a handler for the data_offer event. | |
| 165 | - | // | |
| 166 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 167 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 168 | - | func (o *ExtDataControlDevice) OnDataOffer(handler func(idObject *ExtDataControlOffer)) { | |
| 169 | - | if handler == nil { | |
| 170 | - | return | |
| 171 | - | } | |
| 172 | - | o.handlersMu.Lock() | |
| 173 | - | defer o.handlersMu.Unlock() | |
| 174 | - | o.onDataOffer = append(o.onDataOffer, handler) | |
| 175 | - | } | |
| 176 | - | ||
| 177 | - | // handlersForDataOffer returns the handlers registered for data_offer, taken | |
| 178 | - | // under the lock so a handler may register another handler while events are | |
| 179 | - | // being dispatched. | |
| 180 | - | func (o *ExtDataControlDevice) handlersForDataOffer() []func(idObject *ExtDataControlOffer) { | |
| 181 | - | o.handlersMu.Lock() | |
| 182 | - | defer o.handlersMu.Unlock() | |
| 183 | - | return o.onDataOffer | |
| 184 | - | } | |
| 185 | - | ||
| 186 | - | // OnSelection registers a handler for the selection event. | |
| 187 | - | // | |
| 188 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 189 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 190 | - | func (o *ExtDataControlDevice) OnSelection(handler func(idID uint32)) { | |
| 191 | - | if handler == nil { | |
| 192 | - | return | |
| 193 | - | } | |
| 194 | - | o.handlersMu.Lock() | |
| 195 | - | defer o.handlersMu.Unlock() | |
| 196 | - | o.onSelection = append(o.onSelection, handler) | |
| 197 | - | } | |
| 198 | - | ||
| 199 | - | // handlersForSelection returns the handlers registered for selection, taken | |
| 200 | - | // under the lock so a handler may register another handler while events are | |
| 201 | - | // being dispatched. | |
| 202 | - | func (o *ExtDataControlDevice) handlersForSelection() []func(idID uint32) { | |
| 203 | - | o.handlersMu.Lock() | |
| 204 | - | defer o.handlersMu.Unlock() | |
| 205 | - | return o.onSelection | |
| 206 | - | } | |
| 207 | - | ||
| 208 | - | // OnFinished registers a handler for the finished event. | |
| 209 | - | // | |
| 210 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 211 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 212 | - | func (o *ExtDataControlDevice) OnFinished(handler func()) { | |
| 213 | - | if handler == nil { | |
| 214 | - | return | |
| 215 | - | } | |
| 216 | - | o.handlersMu.Lock() | |
| 217 | - | defer o.handlersMu.Unlock() | |
| 218 | - | o.onFinished = append(o.onFinished, handler) | |
| 219 | - | } | |
| 220 | - | ||
| 221 | - | // handlersForFinished returns the handlers registered for finished, taken | |
| 222 | - | // under the lock so a handler may register another handler while events are | |
| 223 | - | // being dispatched. | |
| 224 | - | func (o *ExtDataControlDevice) handlersForFinished() []func() { | |
| 225 | - | o.handlersMu.Lock() | |
| 226 | - | defer o.handlersMu.Unlock() | |
| 227 | - | return o.onFinished | |
| 228 | - | } | |
| 229 | - | ||
| 230 | - | // OnPrimarySelection registers a handler for the primary_selection event. | |
| 231 | - | // | |
| 232 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 233 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 234 | - | func (o *ExtDataControlDevice) OnPrimarySelection(handler func(idID uint32)) { | |
| 235 | - | if handler == nil { | |
| 236 | - | return | |
| 237 | - | } | |
| 238 | - | o.handlersMu.Lock() | |
| 239 | - | defer o.handlersMu.Unlock() | |
| 240 | - | o.onPrimarySelection = append(o.onPrimarySelection, handler) | |
| 241 | - | } | |
| 242 | - | ||
| 243 | - | // handlersForPrimarySelection returns the handlers registered for primary_selection, taken | |
| 244 | - | // under the lock so a handler may register another handler while events are | |
| 245 | - | // being dispatched. | |
| 246 | - | func (o *ExtDataControlDevice) handlersForPrimarySelection() []func(idID uint32) { | |
| 247 | - | o.handlersMu.Lock() | |
| 248 | - | defer o.handlersMu.Unlock() | |
| 249 | - | return o.onPrimarySelection | |
| 250 | - | } | |
| 251 | - | ||
| 252 | - | // EventSignature returns the declared event argument types in wire order. | |
| 253 | - | func (o *ExtDataControlDevice) EventSignature(opcode uint16) (string, bool) { | |
| 254 | - | switch opcode { | |
| 255 | - | case 0: | |
| 256 | - | return "new_id,", true | |
| 257 | - | case 1: | |
| 258 | - | return "object,", true | |
| 259 | - | case 2: | |
| 260 | - | return "", true | |
| 261 | - | case 3: | |
| 262 | - | return "object,", true | |
| 263 | - | default: | |
| 264 | - | return "", false | |
| 265 | - | } | |
| 266 | - | } | |
| 267 | - | ||
| 268 | - | // Dispatch decodes one event on ext_data_control_device_v1 and calls the registered handlers. | |
| 269 | - | func (o *ExtDataControlDevice) Dispatch(event *wl.Event) { | |
| 270 | - | switch event.Opcode { | |
| 271 | - | case 0: // data_offer | |
| 272 | - | idID := event.Uint32() | |
| 273 | - | idObject := &ExtDataControlOffer{} | |
| 274 | - | idObject.SetContext(o.Context()) | |
| 275 | - | idObject.SetID(idID) | |
| 276 | - | idObject.SetVersion(o.Version()) | |
| 277 | - | o.Context().Register(idObject) | |
| 278 | - | ||
| 279 | - | for i, handler := range o.handlersForDataOffer() { | |
| 280 | - | _ = i | |
| 281 | - | handler(idObject) | |
| 282 | - | } | |
| 283 | - | case 1: // selection | |
| 284 | - | idID := event.Uint32() | |
| 285 | - | ||
| 286 | - | for i, handler := range o.handlersForSelection() { | |
| 287 | - | _ = i | |
| 288 | - | handler(idID) | |
| 289 | - | } | |
| 290 | - | case 2: // finished | |
| 291 | - | ||
| 292 | - | for i, handler := range o.handlersForFinished() { | |
| 293 | - | _ = i | |
| 294 | - | handler() | |
| 295 | - | } | |
| 296 | - | case 3: // primary_selection | |
| 297 | - | idID := event.Uint32() | |
| 298 | - | ||
| 299 | - | for i, handler := range o.handlersForPrimarySelection() { | |
| 300 | - | _ = i | |
| 301 | - | handler(idID) | |
| 302 | - | } | |
| 303 | - | default: | |
| 304 | - | } | |
| 305 | - | } | |
| 306 | - | ||
| 307 | - | // ExtDataControlSourceInterface is the protocol interface name. | |
| 308 | - | const ExtDataControlSourceInterface = "ext_data_control_source_v1" | |
| 309 | - | ||
| 310 | - | // ExtDataControlSource is the generated binding for ext_data_control_source_v1 version 1. | |
| 311 | - | type ExtDataControlSource struct { | |
| 312 | - | wl.BaseProxy | |
| 313 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 314 | - | // handlers while another goroutine dispatches events. | |
| 315 | - | handlersMu sync.Mutex | |
| 316 | - | onSend []func(mimeType string, fd *wl.OwnedFD) | |
| 317 | - | onCancelled []func() | |
| 318 | - | } | |
| 319 | - | ||
| 320 | - | // NewExtDataControlSource returns an unbound ExtDataControlSource. | |
| 321 | - | func NewExtDataControlSource(ctx *wl.Context) *ExtDataControlSource { | |
| 322 | - | obj := &ExtDataControlSource{} | |
| 323 | - | obj.SetContext(ctx) | |
| 324 | - | ctx.Register(obj) | |
| 325 | - | return obj | |
| 326 | - | } | |
| 327 | - | ||
| 328 | - | // This request adds a MIME type to the set of MIME types advertised to targets. Can be called several times to offer multiple types. Calling this after ext_data_control_device.set_selection is a protocol error. | |
| 329 | - | func (o *ExtDataControlSource) Offer(mimeType string) error { | |
| 330 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_data_control_source_v1.offer"}, wl.ArgString(mimeType)); err != nil { | |
| 331 | - | return err | |
| 332 | - | } | |
| 333 | - | return nil | |
| 334 | - | } | |
| 335 | - | ||
| 336 | - | // Destroys the data source object. | |
| 337 | - | func (o *ExtDataControlSource) Destroy() error { | |
| 338 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_data_control_source_v1.destroy", Destructor: true}); err != nil { | |
| 339 | - | return err | |
| 340 | - | } | |
| 341 | - | return nil | |
| 342 | - | } | |
| 343 | - | ||
| 344 | - | // OnSend registers a handler for the send event. | |
| 345 | - | // | |
| 346 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 347 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 348 | - | func (o *ExtDataControlSource) OnSend(handler func(mimeType string, fd *wl.OwnedFD)) { | |
| 349 | - | if handler == nil { | |
| 350 | - | return | |
| 351 | - | } | |
| 352 | - | o.handlersMu.Lock() | |
| 353 | - | defer o.handlersMu.Unlock() | |
| 354 | - | o.onSend = append(o.onSend, handler) | |
| 355 | - | } | |
| 356 | - | ||
| 357 | - | // handlersForSend returns the handlers registered for send, taken | |
| 358 | - | // under the lock so a handler may register another handler while events are | |
| 359 | - | // being dispatched. | |
| 360 | - | func (o *ExtDataControlSource) handlersForSend() []func(mimeType string, fd *wl.OwnedFD) { | |
| 361 | - | o.handlersMu.Lock() | |
| 362 | - | defer o.handlersMu.Unlock() | |
| 363 | - | return o.onSend | |
| 364 | - | } | |
| 365 | - | ||
| 366 | - | // OnCancelled registers a handler for the cancelled event. | |
| 367 | - | // | |
| 368 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 369 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 370 | - | func (o *ExtDataControlSource) OnCancelled(handler func()) { | |
| 371 | - | if handler == nil { | |
| 372 | - | return | |
| 373 | - | } | |
| 374 | - | o.handlersMu.Lock() | |
| 375 | - | defer o.handlersMu.Unlock() | |
| 376 | - | o.onCancelled = append(o.onCancelled, handler) | |
| 377 | - | } | |
| 378 | - | ||
| 379 | - | // handlersForCancelled returns the handlers registered for cancelled, taken | |
| 380 | - | // under the lock so a handler may register another handler while events are | |
| 381 | - | // being dispatched. | |
| 382 | - | func (o *ExtDataControlSource) handlersForCancelled() []func() { | |
| 383 | - | o.handlersMu.Lock() | |
| 384 | - | defer o.handlersMu.Unlock() | |
| 385 | - | return o.onCancelled | |
| 386 | - | } | |
| 387 | - | ||
| 388 | - | // EventSignature returns the declared event argument types in wire order. | |
| 389 | - | func (o *ExtDataControlSource) EventSignature(opcode uint16) (string, bool) { | |
| 390 | - | switch opcode { | |
| 391 | - | case 0: | |
| 392 | - | return "string,fd,", true | |
| 393 | - | case 1: | |
| 394 | - | return "", true | |
| 395 | - | default: | |
| 396 | - | return "", false | |
| 397 | - | } | |
| 398 | - | } | |
| 399 | - | ||
| 400 | - | // Dispatch decodes one event on ext_data_control_source_v1 and calls the registered handlers. | |
| 401 | - | func (o *ExtDataControlSource) Dispatch(event *wl.Event) { | |
| 402 | - | switch event.Opcode { | |
| 403 | - | case 0: // send | |
| 404 | - | mimeType := event.String() | |
| 405 | - | fd := event.FD() | |
| 406 | - | ownedfd := fd | |
| 407 | - | defer ownedfd.Close() | |
| 408 | - | ||
| 409 | - | for i, handler := range o.handlersForSend() { | |
| 410 | - | if i > 0 { | |
| 411 | - | fd = nil | |
| 412 | - | } | |
| 413 | - | handler(mimeType, fd) | |
| 414 | - | } | |
| 415 | - | case 1: // cancelled | |
| 416 | - | ||
| 417 | - | for i, handler := range o.handlersForCancelled() { | |
| 418 | - | _ = i | |
| 419 | - | handler() | |
| 420 | - | } | |
| 421 | - | default: | |
| 422 | - | } | |
| 423 | - | } | |
| 424 | - | ||
| 425 | - | // ExtDataControlOfferInterface is the protocol interface name. | |
| 426 | - | const ExtDataControlOfferInterface = "ext_data_control_offer_v1" | |
| 427 | - | ||
| 428 | - | // ExtDataControlOffer is the generated binding for ext_data_control_offer_v1 version 1. | |
| 429 | - | type ExtDataControlOffer struct { | |
| 430 | - | wl.BaseProxy | |
| 431 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 432 | - | // handlers while another goroutine dispatches events. | |
| 433 | - | handlersMu sync.Mutex | |
| 434 | - | onOffer []func(mimeType string) | |
| 435 | - | } | |
| 436 | - | ||
| 437 | - | // NewExtDataControlOffer returns an unbound ExtDataControlOffer. | |
| 438 | - | func NewExtDataControlOffer(ctx *wl.Context) *ExtDataControlOffer { | |
| 439 | - | obj := &ExtDataControlOffer{} | |
| 440 | - | obj.SetContext(ctx) | |
| 441 | - | ctx.Register(obj) | |
| 442 | - | return obj | |
| 443 | - | } | |
| 444 | - | ||
| 445 | - | // To transfer the offered data, the client issues this request and indicates the MIME type it wants to receive. The transfer happens through the passed file descriptor (typically created with the pipe system call). The source client writes the data in the MIME type representation requested and then closes the file descriptor. The receiving client reads from the read end of the pipe until EOF and then closes its end, at which point the transfer is complete. This request may happen multiple times for different MIME types. | |
| 446 | - | func (o *ExtDataControlOffer) Receive(mimeType string, fd int) error { | |
| 447 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_data_control_offer_v1.receive", FDs: []int{fd}}, wl.ArgString(mimeType), wl.ArgFD()); err != nil { | |
| 448 | - | return err | |
| 449 | - | } | |
| 450 | - | return nil | |
| 451 | - | } | |
| 452 | - | ||
| 453 | - | // Destroys the data offer object. | |
| 454 | - | func (o *ExtDataControlOffer) Destroy() error { | |
| 455 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_data_control_offer_v1.destroy", Destructor: true}); err != nil { | |
| 456 | - | return err | |
| 457 | - | } | |
| 458 | - | return nil | |
| 459 | - | } | |
| 460 | - | ||
| 461 | - | // OnOffer registers a handler for the offer event. | |
| 462 | - | // | |
| 463 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 464 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 465 | - | func (o *ExtDataControlOffer) OnOffer(handler func(mimeType string)) { | |
| 466 | - | if handler == nil { | |
| 467 | - | return | |
| 468 | - | } | |
| 469 | - | o.handlersMu.Lock() | |
| 470 | - | defer o.handlersMu.Unlock() | |
| 471 | - | o.onOffer = append(o.onOffer, handler) | |
| 472 | - | } | |
| 473 | - | ||
| 474 | - | // handlersForOffer returns the handlers registered for offer, taken | |
| 475 | - | // under the lock so a handler may register another handler while events are | |
| 476 | - | // being dispatched. | |
| 477 | - | func (o *ExtDataControlOffer) handlersForOffer() []func(mimeType string) { | |
| 478 | - | o.handlersMu.Lock() | |
| 479 | - | defer o.handlersMu.Unlock() | |
| 480 | - | return o.onOffer | |
| 481 | - | } | |
| 482 | - | ||
| 483 | - | // EventSignature returns the declared event argument types in wire order. | |
| 484 | - | func (o *ExtDataControlOffer) EventSignature(opcode uint16) (string, bool) { | |
| 485 | - | switch opcode { | |
| 486 | - | case 0: | |
| 487 | - | return "string,", true | |
| 488 | - | default: | |
| 489 | - | return "", false | |
| 490 | - | } | |
| 491 | - | } | |
| 492 | - | ||
| 493 | - | // Dispatch decodes one event on ext_data_control_offer_v1 and calls the registered handlers. | |
| 494 | - | func (o *ExtDataControlOffer) Dispatch(event *wl.Event) { | |
| 495 | - | switch event.Opcode { | |
| 496 | - | case 0: // offer | |
| 497 | - | mimeType := event.String() | |
| 498 | - | ||
| 499 | - | for i, handler := range o.handlersForOffer() { | |
| 500 | - | _ = i | |
| 501 | - | handler(mimeType) | |
| 502 | - | } | |
| 503 | - | default: | |
| 504 | - | } | |
| 505 | - | } | |
D protocol/datacontrol/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package datacontrol | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p datacontrol -o ext-data-control-v1_generated.go -import wl_seat=github.com/bnema/wlturbo/protocol/core ext-data-control-v1.xml | |
D protocol/drmlease/drm-lease-v1.xml +0 -317
| @@ -1,317 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="drm_lease_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2018 NXP | |
| 5 | - | Copyright © 2019 Status Research & Development GmbH. | |
| 6 | - | Copyright © 2021 Xaver Hugl | |
| 7 | - | ||
| 8 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 9 | - | copy of this software and associated documentation files (the "Software"), | |
| 10 | - | to deal in the Software without restriction, including without limitation | |
| 11 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 12 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 13 | - | Software is furnished to do so, subject to the following conditions: | |
| 14 | - | ||
| 15 | - | The above copyright notice and this permission notice (including the next | |
| 16 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | Software. | |
| 18 | - | ||
| 19 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 22 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 24 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 25 | - | DEALINGS IN THE SOFTWARE. | |
| 26 | - | </copyright> | |
| 27 | - | ||
| 28 | - | <interface name="wp_drm_lease_device_v1" version="1"> | |
| 29 | - | <description summary="lease device"> | |
| 30 | - | This protocol is used by Wayland compositors which act as Direct | |
| 31 | - | Rendering Manager (DRM) masters to lease DRM resources to Wayland | |
| 32 | - | clients. | |
| 33 | - | ||
| 34 | - | The compositor will advertise one wp_drm_lease_device_v1 global for each | |
| 35 | - | DRM node. Some time after a client binds to the wp_drm_lease_device_v1 | |
| 36 | - | global, the compositor will send a drm_fd event followed by zero, one or | |
| 37 | - | more connector events. After all currently available connectors have been | |
| 38 | - | sent, the compositor will send a wp_drm_lease_device_v1.done event. | |
| 39 | - | ||
| 40 | - | When the list of connectors available for lease changes the compositor | |
| 41 | - | will send wp_drm_lease_device_v1.connector events for added connectors and | |
| 42 | - | wp_drm_lease_connector_v1.withdrawn events for removed connectors, | |
| 43 | - | followed by a wp_drm_lease_device_v1.done event. | |
| 44 | - | ||
| 45 | - | The compositor will indicate when a device is gone by removing the global | |
| 46 | - | via a wl_registry.global_remove event. Upon receiving this event, the | |
| 47 | - | client should destroy any matching wp_drm_lease_device_v1 object. | |
| 48 | - | ||
| 49 | - | To destroy a wp_drm_lease_device_v1 object, the client must first issue | |
| 50 | - | a release request. Upon receiving this request, the compositor will | |
| 51 | - | immediately send a released event and destroy the object. The client must | |
| 52 | - | continue to process and discard drm_fd and connector events until it | |
| 53 | - | receives the released event. Upon receiving the released event, the | |
| 54 | - | client can safely cleanup any client-side resources. | |
| 55 | - | ||
| 56 | - | Warning! The protocol described in this file is currently in the testing | |
| 57 | - | phase. Backward compatible changes may be added together with the | |
| 58 | - | corresponding interface version bump. Backward incompatible changes can | |
| 59 | - | only be done by creating a new major version of the extension. | |
| 60 | - | </description> | |
| 61 | - | ||
| 62 | - | <request name="create_lease_request"> | |
| 63 | - | <description summary="create a lease request object"> | |
| 64 | - | Creates a lease request object. | |
| 65 | - | ||
| 66 | - | See the documentation for wp_drm_lease_request_v1 for details. | |
| 67 | - | </description> | |
| 68 | - | <arg name="id" type="new_id" interface="wp_drm_lease_request_v1" /> | |
| 69 | - | </request> | |
| 70 | - | ||
| 71 | - | <request name="release"> | |
| 72 | - | <description summary="release this object"> | |
| 73 | - | Indicates the client no longer wishes to use this object. In response | |
| 74 | - | the compositor will immediately send the released event and destroy | |
| 75 | - | this object. It can however not guarantee that the client won't receive | |
| 76 | - | connector events before the released event. The client must not send any | |
| 77 | - | requests after this one, doing so will raise a wl_display error. | |
| 78 | - | Existing connectors, lease request and leases will not be affected. | |
| 79 | - | </description> | |
| 80 | - | </request> | |
| 81 | - | ||
| 82 | - | <event name="drm_fd"> | |
| 83 | - | <description summary="open a non-master fd for this DRM node"> | |
| 84 | - | The compositor will send this event when the wp_drm_lease_device_v1 | |
| 85 | - | global is bound, although there are no guarantees as to how long this | |
| 86 | - | takes - the compositor might need to wait until regaining DRM master. | |
| 87 | - | The included fd is a non-master DRM file descriptor opened for this | |
| 88 | - | device and the compositor must not authenticate it. | |
| 89 | - | The purpose of this event is to give the client the ability to | |
| 90 | - | query DRM and discover information which may help them pick the | |
| 91 | - | appropriate DRM device or select the appropriate connectors therein. | |
| 92 | - | </description> | |
| 93 | - | <arg name="fd" type="fd" summary="DRM file descriptor" /> | |
| 94 | - | </event> | |
| 95 | - | ||
| 96 | - | <event name="connector"> | |
| 97 | - | <description summary="advertise connectors available for leases"> | |
| 98 | - | The compositor will use this event to advertise connectors available for | |
| 99 | - | lease by clients. This object may be passed into a lease request to | |
| 100 | - | indicate the client would like to lease that connector, see | |
| 101 | - | wp_drm_lease_request_v1.request_connector for details. While the | |
| 102 | - | compositor will make a best effort to not send disconnected connectors, | |
| 103 | - | no guarantees can be made. | |
| 104 | - | ||
| 105 | - | The compositor must send the drm_fd event before sending connectors. | |
| 106 | - | After the drm_fd event it will send all available connectors but may | |
| 107 | - | send additional connectors at any time. | |
| 108 | - | </description> | |
| 109 | - | <arg name="id" type="new_id" interface="wp_drm_lease_connector_v1" /> | |
| 110 | - | </event> | |
| 111 | - | ||
| 112 | - | <event name="done"> | |
| 113 | - | <description summary="signals grouping of connectors"> | |
| 114 | - | The compositor will send this event to indicate that it has sent all | |
| 115 | - | currently available connectors after the client binds to the global or | |
| 116 | - | when it updates the connector list, for example on hotplug, drm master | |
| 117 | - | change or when a leased connector becomes available again. It will | |
| 118 | - | similarly send this event to group wp_drm_lease_connector_v1.withdrawn | |
| 119 | - | events of connectors of this device. | |
| 120 | - | </description> | |
| 121 | - | </event> | |
| 122 | - | ||
| 123 | - | <event name="released" type="destructor"> | |
| 124 | - | <description summary="the compositor has finished using the device"> | |
| 125 | - | This event is sent in response to the release request and indicates | |
| 126 | - | that the compositor is done sending connector events. | |
| 127 | - | The compositor will destroy this object immediately after sending the | |
| 128 | - | event and it will become invalid. The client should release any | |
| 129 | - | resources associated with this device after receiving this event. | |
| 130 | - | </description> | |
| 131 | - | </event> | |
| 132 | - | </interface> | |
| 133 | - | ||
| 134 | - | <interface name="wp_drm_lease_connector_v1" version="1"> | |
| 135 | - | <description summary="a leasable DRM connector"> | |
| 136 | - | Represents a DRM connector which is available for lease. These objects are | |
| 137 | - | created via wp_drm_lease_device_v1.connector events, and should be passed | |
| 138 | - | to lease requests via wp_drm_lease_request_v1.request_connector. | |
| 139 | - | Immediately after the wp_drm_lease_connector_v1 object is created the | |
| 140 | - | compositor will send a name, a description, a connector_id and a done | |
| 141 | - | event. When the description is updated the compositor will send a | |
| 142 | - | description event followed by a done event. | |
| 143 | - | </description> | |
| 144 | - | ||
| 145 | - | <event name="name"> | |
| 146 | - | <description summary="name"> | |
| 147 | - | The compositor sends this event once the connector is created to | |
| 148 | - | indicate the name of this connector. This will not change for the | |
| 149 | - | duration of the Wayland session, but is not guaranteed to be consistent | |
| 150 | - | between sessions. | |
| 151 | - | ||
| 152 | - | If the compositor supports wl_output version 4 and this connector | |
| 153 | - | corresponds to a wl_output, the compositor should use the same name as | |
| 154 | - | for the wl_output. | |
| 155 | - | </description> | |
| 156 | - | <arg name="name" type="string" summary="connector name" /> | |
| 157 | - | </event> | |
| 158 | - | ||
| 159 | - | <event name="description"> | |
| 160 | - | <description summary="description"> | |
| 161 | - | The compositor sends this event once the connector is created to provide | |
| 162 | - | a human-readable description for this connector, which may be presented | |
| 163 | - | to the user. The compositor may send this event multiple times over the | |
| 164 | - | lifetime of this object to reflect changes in the description. | |
| 165 | - | </description> | |
| 166 | - | <arg name="description" type="string" summary="connector description" /> | |
| 167 | - | </event> | |
| 168 | - | ||
| 169 | - | <event name="connector_id"> | |
| 170 | - | <description summary="connector_id"> | |
| 171 | - | The compositor sends this event once the connector is created to | |
| 172 | - | indicate the DRM object ID which represents the underlying connector | |
| 173 | - | that is being offered. Note that the final lease may include additional | |
| 174 | - | object IDs, such as CRTCs and planes. | |
| 175 | - | </description> | |
| 176 | - | <arg name="connector_id" type="uint" summary="DRM connector ID" /> | |
| 177 | - | </event> | |
| 178 | - | ||
| 179 | - | <event name="done"> | |
| 180 | - | <description summary="all properties have been sent"> | |
| 181 | - | This event is sent after all properties of a connector have been sent. | |
| 182 | - | This allows changes to the properties to be seen as atomic even if they | |
| 183 | - | happen via multiple events. | |
| 184 | - | </description> | |
| 185 | - | </event> | |
| 186 | - | ||
| 187 | - | <event name="withdrawn"> | |
| 188 | - | <description summary="lease offer withdrawn"> | |
| 189 | - | Sent to indicate that the compositor will no longer honor requests for | |
| 190 | - | DRM leases which include this connector. The client may still issue a | |
| 191 | - | lease request including this connector, but the compositor will send | |
| 192 | - | wp_drm_lease_v1.finished without issuing a lease fd. Compositors are | |
| 193 | - | encouraged to send this event when they lose access to connector, for | |
| 194 | - | example when the connector is hot-unplugged, when the connector gets | |
| 195 | - | leased to a client or when the compositor loses DRM master. | |
| 196 | - | ||
| 197 | - | If a client holds a lease for the connector, the status of the lease | |
| 198 | - | remains the same. The client should destroy the object after receiving | |
| 199 | - | this event. | |
| 200 | - | </description> | |
| 201 | - | </event> | |
| 202 | - | ||
| 203 | - | <request name="destroy" type="destructor"> | |
| 204 | - | <description summary="destroy connector"> | |
| 205 | - | The client may send this request to indicate that it will not use this | |
| 206 | - | connector. Clients are encouraged to send this after receiving the | |
| 207 | - | "withdrawn" event so that the server can release the resources | |
| 208 | - | associated with this connector offer. Neither existing lease requests | |
| 209 | - | nor leases will be affected. | |
| 210 | - | </description> | |
| 211 | - | </request> | |
| 212 | - | </interface> | |
| 213 | - | ||
| 214 | - | <interface name="wp_drm_lease_request_v1" version="1"> | |
| 215 | - | <description summary="DRM lease request"> | |
| 216 | - | A client that wishes to lease DRM resources will attach the list of | |
| 217 | - | connectors advertised with wp_drm_lease_device_v1.connector that they | |
| 218 | - | wish to lease, then use wp_drm_lease_request_v1.submit to submit the | |
| 219 | - | request. | |
| 220 | - | </description> | |
| 221 | - | ||
| 222 | - | <enum name="error"> | |
| 223 | - | <entry name="wrong_device" value="0" | |
| 224 | - | summary="requested a connector from a different lease device"/> | |
| 225 | - | <entry name="duplicate_connector" value="1" | |
| 226 | - | summary="requested a connector twice"/> | |
| 227 | - | <entry name="empty_lease" value="2" | |
| 228 | - | summary="requested a lease without requesting a connector"/> | |
| 229 | - | </enum> | |
| 230 | - | ||
| 231 | - | <request name="request_connector"> | |
| 232 | - | <description summary="request a connector for this lease"> | |
| 233 | - | Indicates that the client would like to lease the given connector. | |
| 234 | - | This is only used as a suggestion, the compositor may choose to | |
| 235 | - | include any resources in the lease it issues, or change the set of | |
| 236 | - | leased resources at any time. Compositors are however encouraged to | |
| 237 | - | include the requested connector and other resources necessary | |
| 238 | - | to drive the connected output in the lease. | |
| 239 | - | ||
| 240 | - | Requesting a connector that was created from a different lease device | |
| 241 | - | than this lease request raises the wrong_device error. Requesting a | |
| 242 | - | connector twice will raise the duplicate_connector error. | |
| 243 | - | </description> | |
| 244 | - | <arg name="connector" type="object" | |
| 245 | - | interface="wp_drm_lease_connector_v1" /> | |
| 246 | - | </request> | |
| 247 | - | ||
| 248 | - | <request name="submit" type="destructor"> | |
| 249 | - | <description summary="submit the lease request"> | |
| 250 | - | Submits the lease request and creates a new wp_drm_lease_v1 object. | |
| 251 | - | After calling submit the compositor will immediately destroy this | |
| 252 | - | object, issuing any more requests will cause a wl_display error. | |
| 253 | - | The compositor doesn't make any guarantees about the events of the | |
| 254 | - | lease object, clients cannot expect an immediate response. | |
| 255 | - | Not requesting any connectors before submitting the lease request | |
| 256 | - | will raise the empty_lease error. | |
| 257 | - | </description> | |
| 258 | - | <arg name="id" type="new_id" interface="wp_drm_lease_v1" /> | |
| 259 | - | </request> | |
| 260 | - | </interface> | |
| 261 | - | ||
| 262 | - | <interface name="wp_drm_lease_v1" version="1"> | |
| 263 | - | <description summary="a DRM lease"> | |
| 264 | - | A DRM lease object is used to transfer the DRM file descriptor to the | |
| 265 | - | client and manage the lifetime of the lease. | |
| 266 | - | ||
| 267 | - | Some time after the wp_drm_lease_v1 object is created, the compositor | |
| 268 | - | will reply with the lease request's result. If the lease request is | |
| 269 | - | granted, the compositor will send a lease_fd event. If the lease request | |
| 270 | - | is denied, the compositor will send a finished event without a lease_fd | |
| 271 | - | event. | |
| 272 | - | </description> | |
| 273 | - | ||
| 274 | - | <event name="lease_fd"> | |
| 275 | - | <description summary="shares the DRM file descriptor"> | |
| 276 | - | This event returns a file descriptor suitable for use with DRM-related | |
| 277 | - | ioctls. The client should use drmModeGetLease to enumerate the DRM | |
| 278 | - | objects which have been leased to them. The compositor guarantees it | |
| 279 | - | will not use the leased DRM objects itself until it sends the finished | |
| 280 | - | event. If the compositor cannot or will not grant a lease for the | |
| 281 | - | requested connectors, it will not send this event, instead sending the | |
| 282 | - | finished event. | |
| 283 | - | ||
| 284 | - | The compositor will send this event at most once during this objects | |
| 285 | - | lifetime. | |
| 286 | - | </description> | |
| 287 | - | <arg name="leased_fd" type="fd" summary="leased DRM file descriptor" /> | |
| 288 | - | </event> | |
| 289 | - | ||
| 290 | - | <event name="finished"> | |
| 291 | - | <description summary="sent when the lease has been revoked"> | |
| 292 | - | The compositor uses this event to either reject a lease request, or if | |
| 293 | - | it previously sent a lease_fd, to notify the client that the lease has | |
| 294 | - | been revoked. If the client requires a new lease, they should destroy | |
| 295 | - | this object and submit a new lease request. The compositor will send | |
| 296 | - | no further events for this object after sending the finish event. | |
| 297 | - | Compositors should revoke the lease when any of the leased resources | |
| 298 | - | become unavailable, namely when a hot-unplug occurs or when the | |
| 299 | - | compositor loses DRM master. Compositors may advertise the connector | |
| 300 | - | for leasing again, if the resource is available, by sending the | |
| 301 | - | connector event through the wp_drm_lease_device_v1 interface. | |
| 302 | - | </description> | |
| 303 | - | </event> | |
| 304 | - | ||
| 305 | - | <request name="destroy" type="destructor"> | |
| 306 | - | <description summary="destroys the lease object"> | |
| 307 | - | The client should send this to indicate that it no longer wishes to use | |
| 308 | - | this lease. The compositor should use drmModeRevokeLease on the | |
| 309 | - | appropriate file descriptor, if necessary. | |
| 310 | - | ||
| 311 | - | Upon destruction, the compositor should advertise the connector for | |
| 312 | - | leasing again by sending the connector event through the | |
| 313 | - | wp_drm_lease_device_v1 interface. | |
| 314 | - | </description> | |
| 315 | - | </request> | |
| 316 | - | </interface> | |
| 317 | - | </protocol> | |
D protocol/drmlease/drm-lease-v1_generated.go +0 -594
| @@ -1,594 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: drm_lease_v1 | |
| 3 | - | // Source: drm-lease-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2018 NXP | |
| 7 | - | // Copyright © 2019 Status Research & Development GmbH. | |
| 8 | - | // Copyright © 2021 Xaver Hugl | |
| 9 | - | // | |
| 10 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 11 | - | // copy of this software and associated documentation files (the "Software"), | |
| 12 | - | // to deal in the Software without restriction, including without limitation | |
| 13 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 14 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 15 | - | // Software is furnished to do so, subject to the following conditions: | |
| 16 | - | // | |
| 17 | - | // The above copyright notice and this permission notice (including the next | |
| 18 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 19 | - | // Software. | |
| 20 | - | // | |
| 21 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 22 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 23 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 24 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 25 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 26 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 27 | - | // DEALINGS IN THE SOFTWARE. | |
| 28 | - | ||
| 29 | - | package drmlease | |
| 30 | - | ||
| 31 | - | import ( | |
| 32 | - | "sync" | |
| 33 | - | ||
| 34 | - | "github.com/bnema/wlturbo/wl" | |
| 35 | - | ) | |
| 36 | - | ||
| 37 | - | // ERROR_WRONG_DEVICE is the error wrong_device value. | |
| 38 | - | const ERROR_WRONG_DEVICE = 0 | |
| 39 | - | ||
| 40 | - | // ERROR_DUPLICATE_CONNECTOR is the error duplicate_connector value. | |
| 41 | - | const ERROR_DUPLICATE_CONNECTOR = 1 | |
| 42 | - | ||
| 43 | - | // ERROR_EMPTY_LEASE is the error empty_lease value. | |
| 44 | - | const ERROR_EMPTY_LEASE = 2 | |
| 45 | - | ||
| 46 | - | // WpDrmLeaseDeviceInterface is the protocol interface name. | |
| 47 | - | const WpDrmLeaseDeviceInterface = "wp_drm_lease_device_v1" | |
| 48 | - | ||
| 49 | - | // WpDrmLeaseDevice is the generated binding for wp_drm_lease_device_v1 version 1. | |
| 50 | - | type WpDrmLeaseDevice struct { | |
| 51 | - | wl.BaseProxy | |
| 52 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 53 | - | // handlers while another goroutine dispatches events. | |
| 54 | - | handlersMu sync.Mutex | |
| 55 | - | onDrmFd []func(fd *wl.OwnedFD) | |
| 56 | - | onConnector []func(idObject *WpDrmLeaseConnector) | |
| 57 | - | onDone []func() | |
| 58 | - | onReleased []func() | |
| 59 | - | } | |
| 60 | - | ||
| 61 | - | // NewWpDrmLeaseDevice returns an unbound WpDrmLeaseDevice. | |
| 62 | - | func NewWpDrmLeaseDevice(ctx *wl.Context) *WpDrmLeaseDevice { | |
| 63 | - | obj := &WpDrmLeaseDevice{} | |
| 64 | - | obj.SetContext(ctx) | |
| 65 | - | ctx.Register(obj) | |
| 66 | - | return obj | |
| 67 | - | } | |
| 68 | - | ||
| 69 | - | // Creates a lease request object. See the documentation for wp_drm_lease_request_v1 for details. | |
| 70 | - | func (o *WpDrmLeaseDevice) CreateLeaseRequest() (*WpDrmLeaseRequest, error) { | |
| 71 | - | child := &WpDrmLeaseRequest{} | |
| 72 | - | child.SetContext(o.Context()) | |
| 73 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_drm_lease_device_v1.create_lease_request", Child: child}, wl.ArgObject(child)); err != nil { | |
| 74 | - | return nil, err | |
| 75 | - | } | |
| 76 | - | return child, nil | |
| 77 | - | } | |
| 78 | - | ||
| 79 | - | // Indicates the client no longer wishes to use this object. In response the compositor will immediately send the released event and destroy this object. It can however not guarantee that the client won't receive connector events before the released event. The client must not send any requests after this one, doing so will raise a wl_display error. Existing connectors, lease request and leases will not be affected. | |
| 80 | - | func (o *WpDrmLeaseDevice) Release() error { | |
| 81 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_drm_lease_device_v1.release"}); err != nil { | |
| 82 | - | return err | |
| 83 | - | } | |
| 84 | - | return nil | |
| 85 | - | } | |
| 86 | - | ||
| 87 | - | // OnDrmFd registers a handler for the drm_fd event. | |
| 88 | - | // | |
| 89 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 90 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 91 | - | func (o *WpDrmLeaseDevice) OnDrmFd(handler func(fd *wl.OwnedFD)) { | |
| 92 | - | if handler == nil { | |
| 93 | - | return | |
| 94 | - | } | |
| 95 | - | o.handlersMu.Lock() | |
| 96 | - | defer o.handlersMu.Unlock() | |
| 97 | - | o.onDrmFd = append(o.onDrmFd, handler) | |
| 98 | - | } | |
| 99 | - | ||
| 100 | - | // handlersForDrmFd returns the handlers registered for drm_fd, taken | |
| 101 | - | // under the lock so a handler may register another handler while events are | |
| 102 | - | // being dispatched. | |
| 103 | - | func (o *WpDrmLeaseDevice) handlersForDrmFd() []func(fd *wl.OwnedFD) { | |
| 104 | - | o.handlersMu.Lock() | |
| 105 | - | defer o.handlersMu.Unlock() | |
| 106 | - | return o.onDrmFd | |
| 107 | - | } | |
| 108 | - | ||
| 109 | - | // OnConnector registers a handler for the connector event. | |
| 110 | - | // | |
| 111 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 112 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 113 | - | func (o *WpDrmLeaseDevice) OnConnector(handler func(idObject *WpDrmLeaseConnector)) { | |
| 114 | - | if handler == nil { | |
| 115 | - | return | |
| 116 | - | } | |
| 117 | - | o.handlersMu.Lock() | |
| 118 | - | defer o.handlersMu.Unlock() | |
| 119 | - | o.onConnector = append(o.onConnector, handler) | |
| 120 | - | } | |
| 121 | - | ||
| 122 | - | // handlersForConnector returns the handlers registered for connector, taken | |
| 123 | - | // under the lock so a handler may register another handler while events are | |
| 124 | - | // being dispatched. | |
| 125 | - | func (o *WpDrmLeaseDevice) handlersForConnector() []func(idObject *WpDrmLeaseConnector) { | |
| 126 | - | o.handlersMu.Lock() | |
| 127 | - | defer o.handlersMu.Unlock() | |
| 128 | - | return o.onConnector | |
| 129 | - | } | |
| 130 | - | ||
| 131 | - | // OnDone registers a handler for the done event. | |
| 132 | - | // | |
| 133 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 134 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 135 | - | func (o *WpDrmLeaseDevice) OnDone(handler func()) { | |
| 136 | - | if handler == nil { | |
| 137 | - | return | |
| 138 | - | } | |
| 139 | - | o.handlersMu.Lock() | |
| 140 | - | defer o.handlersMu.Unlock() | |
| 141 | - | o.onDone = append(o.onDone, handler) | |
| 142 | - | } | |
| 143 | - | ||
| 144 | - | // handlersForDone returns the handlers registered for done, taken | |
| 145 | - | // under the lock so a handler may register another handler while events are | |
| 146 | - | // being dispatched. | |
| 147 | - | func (o *WpDrmLeaseDevice) handlersForDone() []func() { | |
| 148 | - | o.handlersMu.Lock() | |
| 149 | - | defer o.handlersMu.Unlock() | |
| 150 | - | return o.onDone | |
| 151 | - | } | |
| 152 | - | ||
| 153 | - | // OnReleased registers a handler for the released event. | |
| 154 | - | // | |
| 155 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 156 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 157 | - | func (o *WpDrmLeaseDevice) OnReleased(handler func()) { | |
| 158 | - | if handler == nil { | |
| 159 | - | return | |
| 160 | - | } | |
| 161 | - | o.handlersMu.Lock() | |
| 162 | - | defer o.handlersMu.Unlock() | |
| 163 | - | o.onReleased = append(o.onReleased, handler) | |
| 164 | - | } | |
| 165 | - | ||
| 166 | - | // handlersForReleased returns the handlers registered for released, taken | |
| 167 | - | // under the lock so a handler may register another handler while events are | |
| 168 | - | // being dispatched. | |
| 169 | - | func (o *WpDrmLeaseDevice) handlersForReleased() []func() { | |
| 170 | - | o.handlersMu.Lock() | |
| 171 | - | defer o.handlersMu.Unlock() | |
| 172 | - | return o.onReleased | |
| 173 | - | } | |
| 174 | - | ||
| 175 | - | // EventSignature returns the declared event argument types in wire order. | |
| 176 | - | func (o *WpDrmLeaseDevice) EventSignature(opcode uint16) (string, bool) { | |
| 177 | - | switch opcode { | |
| 178 | - | case 0: | |
| 179 | - | return "fd,", true | |
| 180 | - | case 1: | |
| 181 | - | return "new_id,", true | |
| 182 | - | case 2: | |
| 183 | - | return "", true | |
| 184 | - | case 3: | |
| 185 | - | return "", true | |
| 186 | - | default: | |
| 187 | - | return "", false | |
| 188 | - | } | |
| 189 | - | } | |
| 190 | - | ||
| 191 | - | // Dispatch decodes one event on wp_drm_lease_device_v1 and calls the registered handlers. | |
| 192 | - | func (o *WpDrmLeaseDevice) Dispatch(event *wl.Event) { | |
| 193 | - | switch event.Opcode { | |
| 194 | - | case 0: // drm_fd | |
| 195 | - | fd := event.FD() | |
| 196 | - | ownedfd := fd | |
| 197 | - | defer ownedfd.Close() | |
| 198 | - | ||
| 199 | - | for i, handler := range o.handlersForDrmFd() { | |
| 200 | - | if i > 0 { | |
| 201 | - | fd = nil | |
| 202 | - | } | |
| 203 | - | handler(fd) | |
| 204 | - | } | |
| 205 | - | case 1: // connector | |
| 206 | - | idID := event.Uint32() | |
| 207 | - | idObject := &WpDrmLeaseConnector{} | |
| 208 | - | idObject.SetContext(o.Context()) | |
| 209 | - | idObject.SetID(idID) | |
| 210 | - | idObject.SetVersion(o.Version()) | |
| 211 | - | o.Context().Register(idObject) | |
| 212 | - | ||
| 213 | - | for i, handler := range o.handlersForConnector() { | |
| 214 | - | _ = i | |
| 215 | - | handler(idObject) | |
| 216 | - | } | |
| 217 | - | case 2: // done | |
| 218 | - | ||
| 219 | - | for i, handler := range o.handlersForDone() { | |
| 220 | - | _ = i | |
| 221 | - | handler() | |
| 222 | - | } | |
| 223 | - | case 3: // released | |
| 224 | - | ||
| 225 | - | for i, handler := range o.handlersForReleased() { | |
| 226 | - | _ = i | |
| 227 | - | handler() | |
| 228 | - | } | |
| 229 | - | o.Context().Unregister(o) | |
| 230 | - | default: | |
| 231 | - | } | |
| 232 | - | } | |
| 233 | - | ||
| 234 | - | // WpDrmLeaseConnectorInterface is the protocol interface name. | |
| 235 | - | const WpDrmLeaseConnectorInterface = "wp_drm_lease_connector_v1" | |
| 236 | - | ||
| 237 | - | // WpDrmLeaseConnector is the generated binding for wp_drm_lease_connector_v1 version 1. | |
| 238 | - | type WpDrmLeaseConnector struct { | |
| 239 | - | wl.BaseProxy | |
| 240 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 241 | - | // handlers while another goroutine dispatches events. | |
| 242 | - | handlersMu sync.Mutex | |
| 243 | - | onName []func(name string) | |
| 244 | - | onDescription []func(description string) | |
| 245 | - | onConnectorId []func(connectorId uint32) | |
| 246 | - | onDone []func() | |
| 247 | - | onWithdrawn []func() | |
| 248 | - | } | |
| 249 | - | ||
| 250 | - | // NewWpDrmLeaseConnector returns an unbound WpDrmLeaseConnector. | |
| 251 | - | func NewWpDrmLeaseConnector(ctx *wl.Context) *WpDrmLeaseConnector { | |
| 252 | - | obj := &WpDrmLeaseConnector{} | |
| 253 | - | obj.SetContext(ctx) | |
| 254 | - | ctx.Register(obj) | |
| 255 | - | return obj | |
| 256 | - | } | |
| 257 | - | ||
| 258 | - | // The client may send this request to indicate that it will not use this connector. Clients are encouraged to send this after receiving the "withdrawn" event so that the server can release the resources associated with this connector offer. Neither existing lease requests nor leases will be affected. | |
| 259 | - | func (o *WpDrmLeaseConnector) Destroy() error { | |
| 260 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_drm_lease_connector_v1.destroy", Destructor: true}); err != nil { | |
| 261 | - | return err | |
| 262 | - | } | |
| 263 | - | return nil | |
| 264 | - | } | |
| 265 | - | ||
| 266 | - | // OnName registers a handler for the name event. | |
| 267 | - | // | |
| 268 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 269 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 270 | - | func (o *WpDrmLeaseConnector) OnName(handler func(name string)) { | |
| 271 | - | if handler == nil { | |
| 272 | - | return | |
| 273 | - | } | |
| 274 | - | o.handlersMu.Lock() | |
| 275 | - | defer o.handlersMu.Unlock() | |
| 276 | - | o.onName = append(o.onName, handler) | |
| 277 | - | } | |
| 278 | - | ||
| 279 | - | // handlersForName returns the handlers registered for name, taken | |
| 280 | - | // under the lock so a handler may register another handler while events are | |
| 281 | - | // being dispatched. | |
| 282 | - | func (o *WpDrmLeaseConnector) handlersForName() []func(name string) { | |
| 283 | - | o.handlersMu.Lock() | |
| 284 | - | defer o.handlersMu.Unlock() | |
| 285 | - | return o.onName | |
| 286 | - | } | |
| 287 | - | ||
| 288 | - | // OnDescription registers a handler for the description event. | |
| 289 | - | // | |
| 290 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 291 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 292 | - | func (o *WpDrmLeaseConnector) OnDescription(handler func(description string)) { | |
| 293 | - | if handler == nil { | |
| 294 | - | return | |
| 295 | - | } | |
| 296 | - | o.handlersMu.Lock() | |
| 297 | - | defer o.handlersMu.Unlock() | |
| 298 | - | o.onDescription = append(o.onDescription, handler) | |
| 299 | - | } | |
| 300 | - | ||
| 301 | - | // handlersForDescription returns the handlers registered for description, taken | |
| 302 | - | // under the lock so a handler may register another handler while events are | |
| 303 | - | // being dispatched. | |
| 304 | - | func (o *WpDrmLeaseConnector) handlersForDescription() []func(description string) { | |
| 305 | - | o.handlersMu.Lock() | |
| 306 | - | defer o.handlersMu.Unlock() | |
| 307 | - | return o.onDescription | |
| 308 | - | } | |
| 309 | - | ||
| 310 | - | // OnConnectorId registers a handler for the connector_id event. | |
| 311 | - | // | |
| 312 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 313 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 314 | - | func (o *WpDrmLeaseConnector) OnConnectorId(handler func(connectorId uint32)) { | |
| 315 | - | if handler == nil { | |
| 316 | - | return | |
| 317 | - | } | |
| 318 | - | o.handlersMu.Lock() | |
| 319 | - | defer o.handlersMu.Unlock() | |
| 320 | - | o.onConnectorId = append(o.onConnectorId, handler) | |
| 321 | - | } | |
| 322 | - | ||
| 323 | - | // handlersForConnectorId returns the handlers registered for connector_id, taken | |
| 324 | - | // under the lock so a handler may register another handler while events are | |
| 325 | - | // being dispatched. | |
| 326 | - | func (o *WpDrmLeaseConnector) handlersForConnectorId() []func(connectorId uint32) { | |
| 327 | - | o.handlersMu.Lock() | |
| 328 | - | defer o.handlersMu.Unlock() | |
| 329 | - | return o.onConnectorId | |
| 330 | - | } | |
| 331 | - | ||
| 332 | - | // OnDone registers a handler for the done event. | |
| 333 | - | // | |
| 334 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 335 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 336 | - | func (o *WpDrmLeaseConnector) OnDone(handler func()) { | |
| 337 | - | if handler == nil { | |
| 338 | - | return | |
| 339 | - | } | |
| 340 | - | o.handlersMu.Lock() | |
| 341 | - | defer o.handlersMu.Unlock() | |
| 342 | - | o.onDone = append(o.onDone, handler) | |
| 343 | - | } | |
| 344 | - | ||
| 345 | - | // handlersForDone returns the handlers registered for done, taken | |
| 346 | - | // under the lock so a handler may register another handler while events are | |
| 347 | - | // being dispatched. | |
| 348 | - | func (o *WpDrmLeaseConnector) handlersForDone() []func() { | |
| 349 | - | o.handlersMu.Lock() | |
| 350 | - | defer o.handlersMu.Unlock() | |
| 351 | - | return o.onDone | |
| 352 | - | } | |
| 353 | - | ||
| 354 | - | // OnWithdrawn registers a handler for the withdrawn event. | |
| 355 | - | // | |
| 356 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 357 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 358 | - | func (o *WpDrmLeaseConnector) OnWithdrawn(handler func()) { | |
| 359 | - | if handler == nil { | |
| 360 | - | return | |
| 361 | - | } | |
| 362 | - | o.handlersMu.Lock() | |
| 363 | - | defer o.handlersMu.Unlock() | |
| 364 | - | o.onWithdrawn = append(o.onWithdrawn, handler) | |
| 365 | - | } | |
| 366 | - | ||
| 367 | - | // handlersForWithdrawn returns the handlers registered for withdrawn, taken | |
| 368 | - | // under the lock so a handler may register another handler while events are | |
| 369 | - | // being dispatched. | |
| 370 | - | func (o *WpDrmLeaseConnector) handlersForWithdrawn() []func() { | |
| 371 | - | o.handlersMu.Lock() | |
| 372 | - | defer o.handlersMu.Unlock() | |
| 373 | - | return o.onWithdrawn | |
| 374 | - | } | |
| 375 | - | ||
| 376 | - | // EventSignature returns the declared event argument types in wire order. | |
| 377 | - | func (o *WpDrmLeaseConnector) EventSignature(opcode uint16) (string, bool) { | |
| 378 | - | switch opcode { | |
| 379 | - | case 0: | |
| 380 | - | return "string,", true | |
| 381 | - | case 1: | |
| 382 | - | return "string,", true | |
| 383 | - | case 2: | |
| 384 | - | return "uint,", true | |
| 385 | - | case 3: | |
| 386 | - | return "", true | |
| 387 | - | case 4: | |
| 388 | - | return "", true | |
| 389 | - | default: | |
| 390 | - | return "", false | |
| 391 | - | } | |
| 392 | - | } | |
| 393 | - | ||
| 394 | - | // Dispatch decodes one event on wp_drm_lease_connector_v1 and calls the registered handlers. | |
| 395 | - | func (o *WpDrmLeaseConnector) Dispatch(event *wl.Event) { | |
| 396 | - | switch event.Opcode { | |
| 397 | - | case 0: // name | |
| 398 | - | name := event.String() | |
| 399 | - | ||
| 400 | - | for i, handler := range o.handlersForName() { | |
| 401 | - | _ = i | |
| 402 | - | handler(name) | |
| 403 | - | } | |
| 404 | - | case 1: // description | |
| 405 | - | description := event.String() | |
| 406 | - | ||
| 407 | - | for i, handler := range o.handlersForDescription() { | |
| 408 | - | _ = i | |
| 409 | - | handler(description) | |
| 410 | - | } | |
| 411 | - | case 2: // connector_id | |
| 412 | - | connectorId := event.Uint32() | |
| 413 | - | ||
| 414 | - | for i, handler := range o.handlersForConnectorId() { | |
| 415 | - | _ = i | |
| 416 | - | handler(connectorId) | |
| 417 | - | } | |
| 418 | - | case 3: // done | |
| 419 | - | ||
| 420 | - | for i, handler := range o.handlersForDone() { | |
| 421 | - | _ = i | |
| 422 | - | handler() | |
| 423 | - | } | |
| 424 | - | case 4: // withdrawn | |
| 425 | - | ||
| 426 | - | for i, handler := range o.handlersForWithdrawn() { | |
| 427 | - | _ = i | |
| 428 | - | handler() | |
| 429 | - | } | |
| 430 | - | default: | |
| 431 | - | } | |
| 432 | - | } | |
| 433 | - | ||
| 434 | - | // WpDrmLeaseRequestInterface is the protocol interface name. | |
| 435 | - | const WpDrmLeaseRequestInterface = "wp_drm_lease_request_v1" | |
| 436 | - | ||
| 437 | - | // WpDrmLeaseRequest is the generated binding for wp_drm_lease_request_v1 version 1. | |
| 438 | - | type WpDrmLeaseRequest struct { | |
| 439 | - | wl.BaseProxy | |
| 440 | - | } | |
| 441 | - | ||
| 442 | - | // NewWpDrmLeaseRequest returns an unbound WpDrmLeaseRequest. | |
| 443 | - | func NewWpDrmLeaseRequest(ctx *wl.Context) *WpDrmLeaseRequest { | |
| 444 | - | obj := &WpDrmLeaseRequest{} | |
| 445 | - | obj.SetContext(ctx) | |
| 446 | - | ctx.Register(obj) | |
| 447 | - | return obj | |
| 448 | - | } | |
| 449 | - | ||
| 450 | - | // Indicates that the client would like to lease the given connector. This is only used as a suggestion, the compositor may choose to include any resources in the lease it issues, or change the set of leased resources at any time. Compositors are however encouraged to include the requested connector and other resources necessary to drive the connected output in the lease. Requesting a connector that was created from a different lease device than this lease request raises the wrong_device error. Requesting a connector twice will raise the duplicate_connector error. | |
| 451 | - | func (o *WpDrmLeaseRequest) RequestConnector(connector *WpDrmLeaseConnector) error { | |
| 452 | - | var arg0 wl.Object | |
| 453 | - | if connector != nil { | |
| 454 | - | arg0 = connector | |
| 455 | - | } | |
| 456 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_drm_lease_request_v1.request_connector"}, wl.ArgObject(arg0)); err != nil { | |
| 457 | - | return err | |
| 458 | - | } | |
| 459 | - | return nil | |
| 460 | - | } | |
| 461 | - | ||
| 462 | - | // Submits the lease request and creates a new wp_drm_lease_v1 object. After calling submit the compositor will immediately destroy this object, issuing any more requests will cause a wl_display error. The compositor doesn't make any guarantees about the events of the lease object, clients cannot expect an immediate response. Not requesting any connectors before submitting the lease request will raise the empty_lease error. | |
| 463 | - | func (o *WpDrmLeaseRequest) Submit() (*WpDrmLease, error) { | |
| 464 | - | child := &WpDrmLease{} | |
| 465 | - | child.SetContext(o.Context()) | |
| 466 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_drm_lease_request_v1.submit", Destructor: true, Child: child}, wl.ArgObject(child)); err != nil { | |
| 467 | - | return nil, err | |
| 468 | - | } | |
| 469 | - | return child, nil | |
| 470 | - | } | |
| 471 | - | ||
| 472 | - | // EventSignature returns the declared event argument types in wire order. | |
| 473 | - | func (o *WpDrmLeaseRequest) EventSignature(opcode uint16) (string, bool) { | |
| 474 | - | switch opcode { | |
| 475 | - | default: | |
| 476 | - | return "", false | |
| 477 | - | } | |
| 478 | - | } | |
| 479 | - | ||
| 480 | - | // Dispatch decodes one event on wp_drm_lease_request_v1 and calls the registered handlers. | |
| 481 | - | func (o *WpDrmLeaseRequest) Dispatch(event *wl.Event) { | |
| 482 | - | switch event.Opcode { | |
| 483 | - | default: | |
| 484 | - | } | |
| 485 | - | } | |
| 486 | - | ||
| 487 | - | // WpDrmLeaseInterface is the protocol interface name. | |
| 488 | - | const WpDrmLeaseInterface = "wp_drm_lease_v1" | |
| 489 | - | ||
| 490 | - | // WpDrmLease is the generated binding for wp_drm_lease_v1 version 1. | |
| 491 | - | type WpDrmLease struct { | |
| 492 | - | wl.BaseProxy | |
| 493 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 494 | - | // handlers while another goroutine dispatches events. | |
| 495 | - | handlersMu sync.Mutex | |
| 496 | - | onLeaseFd []func(leasedFd *wl.OwnedFD) | |
| 497 | - | onFinished []func() | |
| 498 | - | } | |
| 499 | - | ||
| 500 | - | // NewWpDrmLease returns an unbound WpDrmLease. | |
| 501 | - | func NewWpDrmLease(ctx *wl.Context) *WpDrmLease { | |
| 502 | - | obj := &WpDrmLease{} | |
| 503 | - | obj.SetContext(ctx) | |
| 504 | - | ctx.Register(obj) | |
| 505 | - | return obj | |
| 506 | - | } | |
| 507 | - | ||
| 508 | - | // The client should send this to indicate that it no longer wishes to use this lease. The compositor should use drmModeRevokeLease on the appropriate file descriptor, if necessary. Upon destruction, the compositor should advertise the connector for leasing again by sending the connector event through the wp_drm_lease_device_v1 interface. | |
| 509 | - | func (o *WpDrmLease) Destroy() error { | |
| 510 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_drm_lease_v1.destroy", Destructor: true}); err != nil { | |
| 511 | - | return err | |
| 512 | - | } | |
| 513 | - | return nil | |
| 514 | - | } | |
| 515 | - | ||
| 516 | - | // OnLeaseFd registers a handler for the lease_fd event. | |
| 517 | - | // | |
| 518 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 519 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 520 | - | func (o *WpDrmLease) OnLeaseFd(handler func(leasedFd *wl.OwnedFD)) { | |
| 521 | - | if handler == nil { | |
| 522 | - | return | |
| 523 | - | } | |
| 524 | - | o.handlersMu.Lock() | |
| 525 | - | defer o.handlersMu.Unlock() | |
| 526 | - | o.onLeaseFd = append(o.onLeaseFd, handler) | |
| 527 | - | } | |
| 528 | - | ||
| 529 | - | // handlersForLeaseFd returns the handlers registered for lease_fd, taken | |
| 530 | - | // under the lock so a handler may register another handler while events are | |
| 531 | - | // being dispatched. | |
| 532 | - | func (o *WpDrmLease) handlersForLeaseFd() []func(leasedFd *wl.OwnedFD) { | |
| 533 | - | o.handlersMu.Lock() | |
| 534 | - | defer o.handlersMu.Unlock() | |
| 535 | - | return o.onLeaseFd | |
| 536 | - | } | |
| 537 | - | ||
| 538 | - | // OnFinished registers a handler for the finished event. | |
| 539 | - | // | |
| 540 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 541 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 542 | - | func (o *WpDrmLease) OnFinished(handler func()) { | |
| 543 | - | if handler == nil { | |
| 544 | - | return | |
| 545 | - | } | |
| 546 | - | o.handlersMu.Lock() | |
| 547 | - | defer o.handlersMu.Unlock() | |
| 548 | - | o.onFinished = append(o.onFinished, handler) | |
| 549 | - | } | |
| 550 | - | ||
| 551 | - | // handlersForFinished returns the handlers registered for finished, taken | |
| 552 | - | // under the lock so a handler may register another handler while events are | |
| 553 | - | // being dispatched. | |
| 554 | - | func (o *WpDrmLease) handlersForFinished() []func() { | |
| 555 | - | o.handlersMu.Lock() | |
| 556 | - | defer o.handlersMu.Unlock() | |
| 557 | - | return o.onFinished | |
| 558 | - | } | |
| 559 | - | ||
| 560 | - | // EventSignature returns the declared event argument types in wire order. | |
| 561 | - | func (o *WpDrmLease) EventSignature(opcode uint16) (string, bool) { | |
| 562 | - | switch opcode { | |
| 563 | - | case 0: | |
| 564 | - | return "fd,", true | |
| 565 | - | case 1: | |
| 566 | - | return "", true | |
| 567 | - | default: | |
| 568 | - | return "", false | |
| 569 | - | } | |
| 570 | - | } | |
| 571 | - | ||
| 572 | - | // Dispatch decodes one event on wp_drm_lease_v1 and calls the registered handlers. | |
| 573 | - | func (o *WpDrmLease) Dispatch(event *wl.Event) { | |
| 574 | - | switch event.Opcode { | |
| 575 | - | case 0: // lease_fd | |
| 576 | - | leasedFd := event.FD() | |
| 577 | - | ownedleasedFd := leasedFd | |
| 578 | - | defer ownedleasedFd.Close() | |
| 579 | - | ||
| 580 | - | for i, handler := range o.handlersForLeaseFd() { | |
| 581 | - | if i > 0 { | |
| 582 | - | leasedFd = nil | |
| 583 | - | } | |
| 584 | - | handler(leasedFd) | |
| 585 | - | } | |
| 586 | - | case 1: // finished | |
| 587 | - | ||
| 588 | - | for i, handler := range o.handlersForFinished() { | |
| 589 | - | _ = i | |
| 590 | - | handler() | |
| 591 | - | } | |
| 592 | - | default: | |
| 593 | - | } | |
| 594 | - | } | |
D protocol/drmlease/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package drmlease | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p drmlease -o drm-lease-v1_generated.go drm-lease-v1.xml | |
D protocol/drmsyncobj/linux-drm-syncobj-v1.xml +0 -261
| @@ -1,261 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="linux_drm_syncobj_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright 2016 The Chromium Authors. | |
| 5 | - | Copyright 2017 Intel Corporation | |
| 6 | - | Copyright 2018 Collabora, Ltd | |
| 7 | - | Copyright 2021 Simon Ser | |
| 8 | - | ||
| 9 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 | - | copy of this software and associated documentation files (the "Software"), | |
| 11 | - | to deal in the Software without restriction, including without limitation | |
| 12 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 14 | - | Software is furnished to do so, subject to the following conditions: | |
| 15 | - | ||
| 16 | - | The above copyright notice and this permission notice (including the next | |
| 17 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 18 | - | Software. | |
| 19 | - | ||
| 20 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 23 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 25 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 26 | - | DEALINGS IN THE SOFTWARE. | |
| 27 | - | </copyright> | |
| 28 | - | ||
| 29 | - | <description summary="protocol for providing explicit synchronization"> | |
| 30 | - | This protocol allows clients to request explicit synchronization for | |
| 31 | - | buffers. It is tied to the Linux DRM synchronization object framework. | |
| 32 | - | ||
| 33 | - | Synchronization refers to co-ordination of pipelined operations performed | |
| 34 | - | on buffers. Most GPU clients will schedule an asynchronous operation to | |
| 35 | - | render to the buffer, then immediately send the buffer to the compositor | |
| 36 | - | to be attached to a surface. | |
| 37 | - | ||
| 38 | - | With implicit synchronization, ensuring that the rendering operation is | |
| 39 | - | complete before the compositor displays the buffer is an implementation | |
| 40 | - | detail handled by either the kernel or userspace graphics driver. | |
| 41 | - | ||
| 42 | - | By contrast, with explicit synchronization, DRM synchronization object | |
| 43 | - | timeline points mark when the asynchronous operations are complete. When | |
| 44 | - | submitting a buffer, the client provides a timeline point which will be | |
| 45 | - | waited on before the compositor accesses the buffer, and another timeline | |
| 46 | - | point that the compositor will signal when it no longer needs to access the | |
| 47 | - | buffer contents for the purposes of the surface commit. | |
| 48 | - | ||
| 49 | - | Linux DRM synchronization objects are documented at: | |
| 50 | - | https://dri.freedesktop.org/docs/drm/gpu/drm-mm.html#drm-sync-objects | |
| 51 | - | ||
| 52 | - | Warning! The protocol described in this file is currently in the testing | |
| 53 | - | phase. Backward compatible changes may be added together with the | |
| 54 | - | corresponding interface version bump. Backward incompatible changes can | |
| 55 | - | only be done by creating a new major version of the extension. | |
| 56 | - | </description> | |
| 57 | - | ||
| 58 | - | <interface name="wp_linux_drm_syncobj_manager_v1" version="1"> | |
| 59 | - | <description summary="global for providing explicit synchronization"> | |
| 60 | - | This global is a factory interface, allowing clients to request | |
| 61 | - | explicit synchronization for buffers on a per-surface basis. | |
| 62 | - | ||
| 63 | - | See wp_linux_drm_syncobj_surface_v1 for more information. | |
| 64 | - | </description> | |
| 65 | - | ||
| 66 | - | <request name="destroy" type="destructor"> | |
| 67 | - | <description summary="destroy explicit synchronization factory object"> | |
| 68 | - | Destroy this explicit synchronization factory object. Other objects | |
| 69 | - | shall not be affected by this request. | |
| 70 | - | </description> | |
| 71 | - | </request> | |
| 72 | - | ||
| 73 | - | <enum name="error"> | |
| 74 | - | <entry name="surface_exists" value="0" | |
| 75 | - | summary="the surface already has a synchronization object associated"/> | |
| 76 | - | <entry name="invalid_timeline" value="1" | |
| 77 | - | summary="the timeline object could not be imported"/> | |
| 78 | - | </enum> | |
| 79 | - | ||
| 80 | - | <request name="get_surface"> | |
| 81 | - | <description summary="extend surface interface for explicit synchronization"> | |
| 82 | - | Instantiate an interface extension for the given wl_surface to provide | |
| 83 | - | explicit synchronization. | |
| 84 | - | ||
| 85 | - | If the given wl_surface already has an explicit synchronization object | |
| 86 | - | associated, the surface_exists protocol error is raised. | |
| 87 | - | ||
| 88 | - | Graphics APIs, like EGL or Vulkan, that manage the buffer queue and | |
| 89 | - | commits of a wl_surface themselves, are likely to be using this | |
| 90 | - | extension internally. If a client is using such an API for a | |
| 91 | - | wl_surface, it should not directly use this extension on that surface, | |
| 92 | - | to avoid raising a surface_exists protocol error. | |
| 93 | - | </description> | |
| 94 | - | <arg name="id" type="new_id" interface="wp_linux_drm_syncobj_surface_v1" | |
| 95 | - | summary="the new synchronization surface object id"/> | |
| 96 | - | <arg name="surface" type="object" interface="wl_surface" | |
| 97 | - | summary="the surface"/> | |
| 98 | - | </request> | |
| 99 | - | ||
| 100 | - | <request name="import_timeline"> | |
| 101 | - | <description summary="import a DRM syncobj timeline"> | |
| 102 | - | Import a DRM synchronization object timeline. | |
| 103 | - | ||
| 104 | - | If the FD cannot be imported, the invalid_timeline error is raised. | |
| 105 | - | </description> | |
| 106 | - | <arg name="id" type="new_id" interface="wp_linux_drm_syncobj_timeline_v1"/> | |
| 107 | - | <arg name="fd" type="fd" summary="drm_syncobj file descriptor"/> | |
| 108 | - | </request> | |
| 109 | - | </interface> | |
| 110 | - | ||
| 111 | - | <interface name="wp_linux_drm_syncobj_timeline_v1" version="1"> | |
| 112 | - | <description summary="synchronization object timeline"> | |
| 113 | - | This object represents an explicit synchronization object timeline | |
| 114 | - | imported by the client to the compositor. | |
| 115 | - | </description> | |
| 116 | - | ||
| 117 | - | <request name="destroy" type="destructor"> | |
| 118 | - | <description summary="destroy the timeline"> | |
| 119 | - | Destroy the synchronization object timeline. Other objects are not | |
| 120 | - | affected by this request, in particular timeline points set by | |
| 121 | - | set_acquire_point and set_release_point are not unset. | |
| 122 | - | </description> | |
| 123 | - | </request> | |
| 124 | - | </interface> | |
| 125 | - | ||
| 126 | - | <interface name="wp_linux_drm_syncobj_surface_v1" version="1"> | |
| 127 | - | <description summary="per-surface explicit synchronization"> | |
| 128 | - | This object is an add-on interface for wl_surface to enable explicit | |
| 129 | - | synchronization. | |
| 130 | - | ||
| 131 | - | Each surface can be associated with only one object of this interface at | |
| 132 | - | any time. | |
| 133 | - | ||
| 134 | - | Explicit synchronization is guaranteed to be supported for buffers | |
| 135 | - | created with any version of the linux-dmabuf protocol. Compositors are | |
| 136 | - | free to support explicit synchronization for additional buffer types. | |
| 137 | - | If at surface commit time the attached buffer does not support explicit | |
| 138 | - | synchronization, an unsupported_buffer error is raised. | |
| 139 | - | ||
| 140 | - | As long as the wp_linux_drm_syncobj_surface_v1 object is alive, the | |
| 141 | - | compositor may ignore implicit synchronization for buffers attached and | |
| 142 | - | committed to the wl_surface. The delivery of wl_buffer.release events | |
| 143 | - | for buffers attached to the surface becomes undefined. | |
| 144 | - | ||
| 145 | - | Clients must set both acquire and release points if and only if a | |
| 146 | - | non-null buffer is attached in the same surface commit. See the | |
| 147 | - | no_buffer, no_acquire_point and no_release_point protocol errors. | |
| 148 | - | ||
| 149 | - | If at surface commit time the acquire and release DRM syncobj timelines | |
| 150 | - | are identical, the acquire point value must be strictly less than the | |
| 151 | - | release point value, or else the conflicting_points protocol error is | |
| 152 | - | raised. | |
| 153 | - | </description> | |
| 154 | - | ||
| 155 | - | <request name="destroy" type="destructor"> | |
| 156 | - | <description summary="destroy the surface synchronization object"> | |
| 157 | - | Destroy this surface synchronization object. | |
| 158 | - | ||
| 159 | - | Any timeline point set by this object with set_acquire_point or | |
| 160 | - | set_release_point since the last commit may be discarded by the | |
| 161 | - | compositor. Any timeline point set by this object before the last | |
| 162 | - | commit will not be affected. | |
| 163 | - | </description> | |
| 164 | - | </request> | |
| 165 | - | ||
| 166 | - | <enum name="error"> | |
| 167 | - | <entry name="no_surface" value="1" | |
| 168 | - | summary="the associated wl_surface was destroyed"/> | |
| 169 | - | <entry name="unsupported_buffer" value="2" | |
| 170 | - | summary="the buffer does not support explicit synchronization"/> | |
| 171 | - | <entry name="no_buffer" value="3" summary="no buffer was attached"/> | |
| 172 | - | <entry name="no_acquire_point" value="4" | |
| 173 | - | summary="no acquire timeline point was set"/> | |
| 174 | - | <entry name="no_release_point" value="5" | |
| 175 | - | summary="no release timeline point was set"/> | |
| 176 | - | <entry name="conflicting_points" value="6" | |
| 177 | - | summary="acquire and release timeline points are in conflict"/> | |
| 178 | - | </enum> | |
| 179 | - | ||
| 180 | - | <request name="set_acquire_point"> | |
| 181 | - | <description summary="set the acquire timeline point"> | |
| 182 | - | Set the timeline point that must be signalled before the compositor may | |
| 183 | - | sample from the buffer attached with wl_surface.attach. | |
| 184 | - | ||
| 185 | - | The 64-bit unsigned value combined from point_hi and point_lo is the | |
| 186 | - | point value. | |
| 187 | - | ||
| 188 | - | The acquire point is double-buffered state, and will be applied on the | |
| 189 | - | next wl_surface.commit request for the associated surface. Thus, it | |
| 190 | - | applies only to the buffer that is attached to the surface at commit | |
| 191 | - | time. | |
| 192 | - | ||
| 193 | - | If an acquire point has already been attached during the same commit | |
| 194 | - | cycle, the new point replaces the old one. | |
| 195 | - | ||
| 196 | - | If the associated wl_surface was destroyed, a no_surface error is | |
| 197 | - | raised. | |
| 198 | - | ||
| 199 | - | If at surface commit time there is a pending acquire timeline point set | |
| 200 | - | but no pending buffer attached, a no_buffer error is raised. If at | |
| 201 | - | surface commit time there is a pending buffer attached but no pending | |
| 202 | - | acquire timeline point set, the no_acquire_point protocol error is | |
| 203 | - | raised. | |
| 204 | - | </description> | |
| 205 | - | <arg name="timeline" type="object" interface="wp_linux_drm_syncobj_timeline_v1"/> | |
| 206 | - | <arg name="point_hi" type="uint" summary="high 32 bits of the point value"/> | |
| 207 | - | <arg name="point_lo" type="uint" summary="low 32 bits of the point value"/> | |
| 208 | - | </request> | |
| 209 | - | ||
| 210 | - | <request name="set_release_point"> | |
| 211 | - | <description summary="set the release timeline point"> | |
| 212 | - | Set the timeline point that must be signalled by the compositor when it | |
| 213 | - | has finished its usage of the buffer attached with wl_surface.attach | |
| 214 | - | for the relevant commit. | |
| 215 | - | ||
| 216 | - | Once the timeline point is signaled, and assuming the associated buffer | |
| 217 | - | is not pending release from other wl_surface.commit requests, no | |
| 218 | - | additional explicit or implicit synchronization with the compositor is | |
| 219 | - | required to safely re-use the buffer. | |
| 220 | - | ||
| 221 | - | Note that clients cannot rely on the release point being always | |
| 222 | - | signaled after the acquire point: compositors may release buffers | |
| 223 | - | without ever reading from them. In addition, the compositor may use | |
| 224 | - | different presentation paths for different commits, which may have | |
| 225 | - | different release behavior. As a result, the compositor may signal the | |
| 226 | - | release points in a different order than the client committed them. | |
| 227 | - | ||
| 228 | - | Because signaling a timeline point also signals every previous point, | |
| 229 | - | it is generally not safe to use the same timeline object for the | |
| 230 | - | release points of multiple buffers. The out-of-order signaling | |
| 231 | - | described above may lead to a release point being signaled before the | |
| 232 | - | compositor has finished reading. To avoid this, it is strongly | |
| 233 | - | recommended that each buffer should use a separate timeline for its | |
| 234 | - | release points. | |
| 235 | - | ||
| 236 | - | The 64-bit unsigned value combined from point_hi and point_lo is the | |
| 237 | - | point value. | |
| 238 | - | ||
| 239 | - | The release point is double-buffered state, and will be applied on the | |
| 240 | - | next wl_surface.commit request for the associated surface. Thus, it | |
| 241 | - | applies only to the buffer that is attached to the surface at commit | |
| 242 | - | time. | |
| 243 | - | ||
| 244 | - | If a release point has already been attached during the same commit | |
| 245 | - | cycle, the new point replaces the old one. | |
| 246 | - | ||
| 247 | - | If the associated wl_surface was destroyed, a no_surface error is | |
| 248 | - | raised. | |
| 249 | - | ||
| 250 | - | If at surface commit time there is a pending release timeline point set | |
| 251 | - | but no pending buffer attached, a no_buffer error is raised. If at | |
| 252 | - | surface commit time there is a pending buffer attached but no pending | |
| 253 | - | release timeline point set, the no_release_point protocol error is | |
| 254 | - | raised. | |
| 255 | - | </description> | |
| 256 | - | <arg name="timeline" type="object" interface="wp_linux_drm_syncobj_timeline_v1"/> | |
| 257 | - | <arg name="point_hi" type="uint" summary="high 32 bits of the point value"/> | |
| 258 | - | <arg name="point_lo" type="uint" summary="low 32 bits of the point value"/> | |
| 259 | - | </request> | |
| 260 | - | </interface> | |
| 261 | - | </protocol> | |
D protocol/drmsyncobj/linux-drm-syncobj-v1_generated.go +0 -224
| @@ -1,224 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: linux_drm_syncobj_v1 | |
| 3 | - | // Source: linux-drm-syncobj-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright 2016 The Chromium Authors. | |
| 7 | - | // Copyright 2017 Intel Corporation | |
| 8 | - | // Copyright 2018 Collabora, Ltd | |
| 9 | - | // Copyright 2021 Simon Ser | |
| 10 | - | // | |
| 11 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 12 | - | // copy of this software and associated documentation files (the "Software"), | |
| 13 | - | // to deal in the Software without restriction, including without limitation | |
| 14 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 15 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 16 | - | // Software is furnished to do so, subject to the following conditions: | |
| 17 | - | // | |
| 18 | - | // The above copyright notice and this permission notice (including the next | |
| 19 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 20 | - | // Software. | |
| 21 | - | // | |
| 22 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 23 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 24 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 25 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 26 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 27 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 28 | - | // DEALINGS IN THE SOFTWARE. | |
| 29 | - | ||
| 30 | - | package drmsyncobj | |
| 31 | - | ||
| 32 | - | import ( | |
| 33 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 34 | - | "github.com/bnema/wlturbo/wl" | |
| 35 | - | ) | |
| 36 | - | ||
| 37 | - | // ERROR_SURFACE_EXISTS is the error surface_exists value. | |
| 38 | - | const ERROR_SURFACE_EXISTS = 0 | |
| 39 | - | ||
| 40 | - | // ERROR_INVALID_TIMELINE is the error invalid_timeline value. | |
| 41 | - | const ERROR_INVALID_TIMELINE = 1 | |
| 42 | - | ||
| 43 | - | // ERROR_NO_SURFACE is the error no_surface value. | |
| 44 | - | const ERROR_NO_SURFACE = 1 | |
| 45 | - | ||
| 46 | - | // ERROR_UNSUPPORTED_BUFFER is the error unsupported_buffer value. | |
| 47 | - | const ERROR_UNSUPPORTED_BUFFER = 2 | |
| 48 | - | ||
| 49 | - | // ERROR_NO_BUFFER is the error no_buffer value. | |
| 50 | - | const ERROR_NO_BUFFER = 3 | |
| 51 | - | ||
| 52 | - | // ERROR_NO_ACQUIRE_POINT is the error no_acquire_point value. | |
| 53 | - | const ERROR_NO_ACQUIRE_POINT = 4 | |
| 54 | - | ||
| 55 | - | // ERROR_NO_RELEASE_POINT is the error no_release_point value. | |
| 56 | - | const ERROR_NO_RELEASE_POINT = 5 | |
| 57 | - | ||
| 58 | - | // ERROR_CONFLICTING_POINTS is the error conflicting_points value. | |
| 59 | - | const ERROR_CONFLICTING_POINTS = 6 | |
| 60 | - | ||
| 61 | - | // WpLinuxDrmSyncobjManagerInterface is the protocol interface name. | |
| 62 | - | const WpLinuxDrmSyncobjManagerInterface = "wp_linux_drm_syncobj_manager_v1" | |
| 63 | - | ||
| 64 | - | // WpLinuxDrmSyncobjManager is the generated binding for wp_linux_drm_syncobj_manager_v1 version 1. | |
| 65 | - | type WpLinuxDrmSyncobjManager struct { | |
| 66 | - | wl.BaseProxy | |
| 67 | - | } | |
| 68 | - | ||
| 69 | - | // NewWpLinuxDrmSyncobjManager returns an unbound WpLinuxDrmSyncobjManager. | |
| 70 | - | func NewWpLinuxDrmSyncobjManager(ctx *wl.Context) *WpLinuxDrmSyncobjManager { | |
| 71 | - | obj := &WpLinuxDrmSyncobjManager{} | |
| 72 | - | obj.SetContext(ctx) | |
| 73 | - | ctx.Register(obj) | |
| 74 | - | return obj | |
| 75 | - | } | |
| 76 | - | ||
| 77 | - | // Destroy this explicit synchronization factory object. Other objects shall not be affected by this request. | |
| 78 | - | func (o *WpLinuxDrmSyncobjManager) Destroy() error { | |
| 79 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_linux_drm_syncobj_manager_v1.destroy", Destructor: true}); err != nil { | |
| 80 | - | return err | |
| 81 | - | } | |
| 82 | - | return nil | |
| 83 | - | } | |
| 84 | - | ||
| 85 | - | // Instantiate an interface extension for the given wl_surface to provide explicit synchronization. If the given wl_surface already has an explicit synchronization object associated, the surface_exists protocol error is raised. Graphics APIs, like EGL or Vulkan, that manage the buffer queue and commits of a wl_surface themselves, are likely to be using this extension internally. If a client is using such an API for a wl_surface, it should not directly use this extension on that surface, to avoid raising a surface_exists protocol error. | |
| 86 | - | func (o *WpLinuxDrmSyncobjManager) GetSurface(surface *cross_wl_surface.Surface) (*WpLinuxDrmSyncobjSurface, error) { | |
| 87 | - | var arg1 wl.Object | |
| 88 | - | if surface != nil { | |
| 89 | - | arg1 = surface | |
| 90 | - | } | |
| 91 | - | child := &WpLinuxDrmSyncobjSurface{} | |
| 92 | - | child.SetContext(o.Context()) | |
| 93 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_linux_drm_syncobj_manager_v1.get_surface", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 94 | - | return nil, err | |
| 95 | - | } | |
| 96 | - | return child, nil | |
| 97 | - | } | |
| 98 | - | ||
| 99 | - | // Import a DRM synchronization object timeline. If the FD cannot be imported, the invalid_timeline error is raised. | |
| 100 | - | func (o *WpLinuxDrmSyncobjManager) ImportTimeline(fd int) (*WpLinuxDrmSyncobjTimeline, error) { | |
| 101 | - | child := &WpLinuxDrmSyncobjTimeline{} | |
| 102 | - | child.SetContext(o.Context()) | |
| 103 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_linux_drm_syncobj_manager_v1.import_timeline", Child: child, FDs: []int{fd}}, wl.ArgObject(child), wl.ArgFD()); err != nil { | |
| 104 | - | return nil, err | |
| 105 | - | } | |
| 106 | - | return child, nil | |
| 107 | - | } | |
| 108 | - | ||
| 109 | - | // EventSignature returns the declared event argument types in wire order. | |
| 110 | - | func (o *WpLinuxDrmSyncobjManager) EventSignature(opcode uint16) (string, bool) { | |
| 111 | - | switch opcode { | |
| 112 | - | default: | |
| 113 | - | return "", false | |
| 114 | - | } | |
| 115 | - | } | |
| 116 | - | ||
| 117 | - | // Dispatch decodes one event on wp_linux_drm_syncobj_manager_v1 and calls the registered handlers. | |
| 118 | - | func (o *WpLinuxDrmSyncobjManager) Dispatch(event *wl.Event) { | |
| 119 | - | switch event.Opcode { | |
| 120 | - | default: | |
| 121 | - | } | |
| 122 | - | } | |
| 123 | - | ||
| 124 | - | // WpLinuxDrmSyncobjTimelineInterface is the protocol interface name. | |
| 125 | - | const WpLinuxDrmSyncobjTimelineInterface = "wp_linux_drm_syncobj_timeline_v1" | |
| 126 | - | ||
| 127 | - | // WpLinuxDrmSyncobjTimeline is the generated binding for wp_linux_drm_syncobj_timeline_v1 version 1. | |
| 128 | - | type WpLinuxDrmSyncobjTimeline struct { | |
| 129 | - | wl.BaseProxy | |
| 130 | - | } | |
| 131 | - | ||
| 132 | - | // NewWpLinuxDrmSyncobjTimeline returns an unbound WpLinuxDrmSyncobjTimeline. | |
| 133 | - | func NewWpLinuxDrmSyncobjTimeline(ctx *wl.Context) *WpLinuxDrmSyncobjTimeline { | |
| 134 | - | obj := &WpLinuxDrmSyncobjTimeline{} | |
| 135 | - | obj.SetContext(ctx) | |
| 136 | - | ctx.Register(obj) | |
| 137 | - | return obj | |
| 138 | - | } | |
| 139 | - | ||
| 140 | - | // Destroy the synchronization object timeline. Other objects are not affected by this request, in particular timeline points set by set_acquire_point and set_release_point are not unset. | |
| 141 | - | func (o *WpLinuxDrmSyncobjTimeline) Destroy() error { | |
| 142 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_linux_drm_syncobj_timeline_v1.destroy", Destructor: true}); err != nil { | |
| 143 | - | return err | |
| 144 | - | } | |
| 145 | - | return nil | |
| 146 | - | } | |
| 147 | - | ||
| 148 | - | // EventSignature returns the declared event argument types in wire order. | |
| 149 | - | func (o *WpLinuxDrmSyncobjTimeline) EventSignature(opcode uint16) (string, bool) { | |
| 150 | - | switch opcode { | |
| 151 | - | default: | |
| 152 | - | return "", false | |
| 153 | - | } | |
| 154 | - | } | |
| 155 | - | ||
| 156 | - | // Dispatch decodes one event on wp_linux_drm_syncobj_timeline_v1 and calls the registered handlers. | |
| 157 | - | func (o *WpLinuxDrmSyncobjTimeline) Dispatch(event *wl.Event) { | |
| 158 | - | switch event.Opcode { | |
| 159 | - | default: | |
| 160 | - | } | |
| 161 | - | } | |
| 162 | - | ||
| 163 | - | // WpLinuxDrmSyncobjSurfaceInterface is the protocol interface name. | |
| 164 | - | const WpLinuxDrmSyncobjSurfaceInterface = "wp_linux_drm_syncobj_surface_v1" | |
| 165 | - | ||
| 166 | - | // WpLinuxDrmSyncobjSurface is the generated binding for wp_linux_drm_syncobj_surface_v1 version 1. | |
| 167 | - | type WpLinuxDrmSyncobjSurface struct { | |
| 168 | - | wl.BaseProxy | |
| 169 | - | } | |
| 170 | - | ||
| 171 | - | // NewWpLinuxDrmSyncobjSurface returns an unbound WpLinuxDrmSyncobjSurface. | |
| 172 | - | func NewWpLinuxDrmSyncobjSurface(ctx *wl.Context) *WpLinuxDrmSyncobjSurface { | |
| 173 | - | obj := &WpLinuxDrmSyncobjSurface{} | |
| 174 | - | obj.SetContext(ctx) | |
| 175 | - | ctx.Register(obj) | |
| 176 | - | return obj | |
| 177 | - | } | |
| 178 | - | ||
| 179 | - | // Destroy this surface synchronization object. Any timeline point set by this object with set_acquire_point or set_release_point since the last commit may be discarded by the compositor. Any timeline point set by this object before the last commit will not be affected. | |
| 180 | - | func (o *WpLinuxDrmSyncobjSurface) Destroy() error { | |
| 181 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_linux_drm_syncobj_surface_v1.destroy", Destructor: true}); err != nil { | |
| 182 | - | return err | |
| 183 | - | } | |
| 184 | - | return nil | |
| 185 | - | } | |
| 186 | - | ||
| 187 | - | // Set the timeline point that must be signalled before the compositor may sample from the buffer attached with wl_surface.attach. The 64-bit unsigned value combined from point_hi and point_lo is the point value. The acquire point is double-buffered state, and will be applied on the next wl_surface.commit request for the associated surface. Thus, it applies only to the buffer that is attached to the surface at commit time. If an acquire point has already been attached during the same commit cycle, the new point replaces the old one. If the associated wl_surface was destroyed, a no_surface error is raised. If at surface commit time there is a pending acquire timeline point set but no pending buffer attached, a no_buffer error is raised. If at surface commit time there is a pending buffer attached but no pending acquire timeline point set, the no_acquire_point protocol error is raised. | |
| 188 | - | func (o *WpLinuxDrmSyncobjSurface) SetAcquirePoint(timeline *WpLinuxDrmSyncobjTimeline, pointHi uint32, pointLo uint32) error { | |
| 189 | - | var arg0 wl.Object | |
| 190 | - | if timeline != nil { | |
| 191 | - | arg0 = timeline | |
| 192 | - | } | |
| 193 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_linux_drm_syncobj_surface_v1.set_acquire_point"}, wl.ArgObject(arg0), wl.ArgUint(pointHi), wl.ArgUint(pointLo)); err != nil { | |
| 194 | - | return err | |
| 195 | - | } | |
| 196 | - | return nil | |
| 197 | - | } | |
| 198 | - | ||
| 199 | - | // Set the timeline point that must be signalled by the compositor when it has finished its usage of the buffer attached with wl_surface.attach for the relevant commit. Once the timeline point is signaled, and assuming the associated buffer is not pending release from other wl_surface.commit requests, no additional explicit or implicit synchronization with the compositor is required to safely re-use the buffer. Note that clients cannot rely on the release point being always signaled after the acquire point: compositors may release buffers without ever reading from them. In addition, the compositor may use different presentation paths for different commits, which may have different release behavior. As a result, the compositor may signal the release points in a different order than the client committed them. Because signaling a timeline point also signals every previous point, it is generally not safe to use the same timeline object for the release points of multiple buffers. The out-of-order signaling described above may lead to a release point being signaled before the compositor has finished reading. To avoid this, it is strongly recommended that each buffer should use a separate timeline for its release points. The 64-bit unsigned value combined from point_hi and point_lo is the point value. The release point is double-buffered state, and will be applied on the next wl_surface.commit request for the associated surface. Thus, it applies only to the buffer that is attached to the surface at commit time. If a release point has already been attached during the same commit cycle, the new point replaces the old one. If the associated wl_surface was destroyed, a no_surface error is raised. If at surface commit time there is a pending release timeline point set but no pending buffer attached, a no_buffer error is raised. If at surface commit time there is a pending buffer attached but no pending release timeline point set, the no_release_point protocol error is raised. | |
| 200 | - | func (o *WpLinuxDrmSyncobjSurface) SetReleasePoint(timeline *WpLinuxDrmSyncobjTimeline, pointHi uint32, pointLo uint32) error { | |
| 201 | - | var arg0 wl.Object | |
| 202 | - | if timeline != nil { | |
| 203 | - | arg0 = timeline | |
| 204 | - | } | |
| 205 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_linux_drm_syncobj_surface_v1.set_release_point"}, wl.ArgObject(arg0), wl.ArgUint(pointHi), wl.ArgUint(pointLo)); err != nil { | |
| 206 | - | return err | |
| 207 | - | } | |
| 208 | - | return nil | |
| 209 | - | } | |
| 210 | - | ||
| 211 | - | // EventSignature returns the declared event argument types in wire order. | |
| 212 | - | func (o *WpLinuxDrmSyncobjSurface) EventSignature(opcode uint16) (string, bool) { | |
| 213 | - | switch opcode { | |
| 214 | - | default: | |
| 215 | - | return "", false | |
| 216 | - | } | |
| 217 | - | } | |
| 218 | - | ||
| 219 | - | // Dispatch decodes one event on wp_linux_drm_syncobj_surface_v1 and calls the registered handlers. | |
| 220 | - | func (o *WpLinuxDrmSyncobjSurface) Dispatch(event *wl.Event) { | |
| 221 | - | switch event.Opcode { | |
| 222 | - | default: | |
| 223 | - | } | |
| 224 | - | } | |
D protocol/extensions_test.go +0 -722
| @@ -1,722 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package protocol_test | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "encoding/binary" | |
| 7 | - | "errors" | |
| 8 | - | "net" | |
| 9 | - | "os" | |
| 10 | - | "slices" | |
| 11 | - | "strings" | |
| 12 | - | "testing" | |
| 13 | - | "time" | |
| 14 | - | ||
| 15 | - | "github.com/bnema/wlturbo" | |
| 16 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 17 | - | "github.com/bnema/wlturbo/protocol/cursorshape" | |
| 18 | - | "github.com/bnema/wlturbo/protocol/drmsyncobj" | |
| 19 | - | "github.com/bnema/wlturbo/protocol/fractionalscale" | |
| 20 | - | "github.com/bnema/wlturbo/protocol/linuxdmabuf" | |
| 21 | - | "github.com/bnema/wlturbo/protocol/textinput" | |
| 22 | - | "github.com/bnema/wlturbo/protocol/viewporter" | |
| 23 | - | "github.com/bnema/wlturbo/protocol/xdgshell" | |
| 24 | - | "golang.org/x/sys/unix" | |
| 25 | - | ) | |
| 26 | - | ||
| 27 | - | func pair(t *testing.T) (*net.UnixConn, *net.UnixConn) { | |
| 28 | - | t.Helper() | |
| 29 | - | fds, e := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0) | |
| 30 | - | if e != nil { | |
| 31 | - | t.Fatal(e) | |
| 32 | - | } | |
| 33 | - | a := os.NewFile(uintptr(fds[0]), "a") | |
| 34 | - | b := os.NewFile(uintptr(fds[1]), "b") | |
| 35 | - | ca, e := net.FileConn(a) | |
| 36 | - | a.Close() | |
| 37 | - | if e != nil { | |
| 38 | - | t.Fatal(e) | |
| 39 | - | } | |
| 40 | - | cb, e := net.FileConn(b) | |
| 41 | - | b.Close() | |
| 42 | - | if e != nil { | |
| 43 | - | t.Fatal(e) | |
| 44 | - | } | |
| 45 | - | t.Cleanup(func() { ca.Close(); cb.Close() }) | |
| 46 | - | return ca.(*net.UnixConn), cb.(*net.UnixConn) | |
| 47 | - | } | |
| 48 | - | func msg(id uint32, op uint16, body ...uint32) []byte { | |
| 49 | - | b := make([]byte, 8+4*len(body)) | |
| 50 | - | binary.NativeEndian.PutUint32(b, id) | |
| 51 | - | binary.NativeEndian.PutUint32(b[4:], uint32(len(b))<<16|uint32(op)) | |
| 52 | - | for i, v := range body { | |
| 53 | - | binary.NativeEndian.PutUint32(b[8+i*4:], v) | |
| 54 | - | } | |
| 55 | - | return b | |
| 56 | - | } | |
| 57 | - | func payload(id uint32, op uint16, b ...byte) []byte { | |
| 58 | - | p := make([]byte, 8+len(b)) | |
| 59 | - | copy(p, msg(id, op)) | |
| 60 | - | copy(p[8:], b) | |
| 61 | - | binary.NativeEndian.PutUint32(p[4:], uint32(len(p))<<16|uint32(op)) | |
| 62 | - | return p | |
| 63 | - | } | |
| 64 | - | func arr(b []byte) []byte { | |
| 65 | - | out := make([]byte, 4+(len(b)+3)&^3) | |
| 66 | - | binary.NativeEndian.PutUint32(out, uint32(len(b))) | |
| 67 | - | copy(out[4:], b) | |
| 68 | - | return out | |
| 69 | - | } | |
| 70 | - | func str(s string) []byte { return arr(append([]byte(s), 0)) } | |
| 71 | - | func send(t *testing.T, p *net.UnixConn, b []byte, fd ...int) { | |
| 72 | - | t.Helper() | |
| 73 | - | var rights []byte | |
| 74 | - | if len(fd) > 0 { | |
| 75 | - | rights = unix.UnixRights(fd...) | |
| 76 | - | } | |
| 77 | - | if _, _, e := p.WriteMsgUnix(b, rights, nil); e != nil { | |
| 78 | - | t.Fatal(e) | |
| 79 | - | } | |
| 80 | - | } | |
| 81 | - | func request(t *testing.T, p *net.UnixConn) (uint32, uint16, []byte) { | |
| 82 | - | t.Helper() | |
| 83 | - | p.SetReadDeadline(time.Now().Add(2 * time.Second)) | |
| 84 | - | b := make([]byte, 4096) | |
| 85 | - | n, e := p.Read(b) | |
| 86 | - | if e != nil { | |
| 87 | - | t.Fatal(e) | |
| 88 | - | } | |
| 89 | - | if n < 8 { | |
| 90 | - | t.Fatal("short request") | |
| 91 | - | } | |
| 92 | - | return binary.NativeEndian.Uint32(b), uint16(binary.NativeEndian.Uint32(b[4:])), b[8:n] | |
| 93 | - | } | |
| 94 | - | func noerr(t *testing.T, e error) { | |
| 95 | - | t.Helper() | |
| 96 | - | if e != nil { | |
| 97 | - | t.Fatal(e) | |
| 98 | - | } | |
| 99 | - | } | |
| 100 | - | func bind(t *testing.T, d *wlturbo.Display, p *net.UnixConn, name uint32, iface string, announced uint32, supported uint32, proxy wlturbo.Proxy) { | |
| 101 | - | t.Helper() | |
| 102 | - | // A fake server must advertise a global before clients can negotiate it. | |
| 103 | - | announcement := append(msg(0, 0, name)[8:], str(iface)...) | |
| 104 | - | announcement = append(announcement, msg(0, 0, announced)[8:]...) | |
| 105 | - | send(t, p, payload(d.Registry().ID(), 0, announcement...)) | |
| 106 | - | noerr(t, d.Dispatch()) | |
| 107 | - | v, err := d.Registry().BindNegotiated(iface, supported, proxy) | |
| 108 | - | noerr(t, err) | |
| 109 | - | want := min(announced, supported) | |
| 110 | - | _, op, b := request(t, p) | |
| 111 | - | if op != 0 || v != want || binary.NativeEndian.Uint32(b) != name || binary.NativeEndian.Uint32(b[len(b)-8:]) != want || binary.NativeEndian.Uint32(b[len(b)-4:]) != proxy.ID() { | |
| 112 | - | t.Fatalf("bad bind %s announced=%d supported=%d negotiated=%d wire=%x", iface, announced, supported, v, b) | |
| 113 | - | } | |
| 114 | - | } | |
| 115 | - | ||
| 116 | - | // serverID is the first server-allocated object ID on the wire. | |
| 117 | - | const serverID = 0xff000000 | |
| 118 | - | ||
| 119 | - | // wordBytes encodes 32-bit words as a message body in native byte order. | |
| 120 | - | func wordBytes(v ...uint32) []byte { return msg(0, 0, v...)[8:] } | |
| 121 | - | ||
| 122 | - | // cat concatenates message body fragments. | |
| 123 | - | func cat(parts ...[]byte) []byte { | |
| 124 | - | var out []byte | |
| 125 | - | for _, p := range parts { | |
| 126 | - | out = append(out, p...) | |
| 127 | - | } | |
| 128 | - | return out | |
| 129 | - | } | |
| 130 | - | ||
| 131 | - | // decodeWords splits a message body into 32-bit words. | |
| 132 | - | func decodeWords(b []byte) []uint32 { | |
| 133 | - | w := make([]uint32, len(b)/4) | |
| 134 | - | for i := range w { | |
| 135 | - | w[i] = binary.NativeEndian.Uint32(b[i*4:]) | |
| 136 | - | } | |
| 137 | - | return w | |
| 138 | - | } | |
| 139 | - | ||
| 140 | - | // wantWords requires a request body to be exactly the given 32-bit words. | |
| 141 | - | func wantWords(t *testing.T, what string, b []byte, want ...uint32) { | |
| 142 | - | t.Helper() | |
| 143 | - | if got := decodeWords(b); !slices.Equal(got, want) { // nil and empty are equal | |
| 144 | - | t.Fatalf("%s wire = %v, want %v", what, got, want) | |
| 145 | - | } | |
| 146 | - | } | |
| 147 | - | ||
| 148 | - | // wantRequestWords reads one request and requires its exact object, opcode and | |
| 149 | - | // 32-bit word arguments. | |
| 150 | - | func wantRequestWords(t *testing.T, p *net.UnixConn, id uint32, op uint16, want ...uint32) { | |
| 151 | - | t.Helper() | |
| 152 | - | gid, gop, body := request(t, p) | |
| 153 | - | if gid != id || gop != op || len(body) != 4*len(want) { | |
| 154 | - | t.Fatalf("request object=%d op=%d body=%x, want object=%d op=%d words=%v", gid, gop, body, id, op, want) | |
| 155 | - | } | |
| 156 | - | wantWords(t, "request", body, want...) | |
| 157 | - | } | |
| 158 | - | ||
| 159 | - | // requireFDClosed fails if fd is still open in this process: the binding must | |
| 160 | - | // close its copy of a descriptor once the kernel took it with a request. Call | |
| 161 | - | // it before reading the request, because the received duplicate may reuse the | |
| 162 | - | // same descriptor number. | |
| 163 | - | func requireFDClosed(t *testing.T, fd int) { | |
| 164 | - | t.Helper() | |
| 165 | - | if _, e := unix.FcntlInt(uintptr(fd), unix.F_GETFD, 0); e == nil { | |
| 166 | - | t.Fatalf("descriptor %d sent by the client was not closed", fd) | |
| 167 | - | } | |
| 168 | - | } | |
| 169 | - | ||
| 170 | - | // requireNoWrite fails unless the client wrote nothing within a short deadline. | |
| 171 | - | func requireNoWrite(t *testing.T, p *net.UnixConn) { | |
| 172 | - | t.Helper() | |
| 173 | - | p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) | |
| 174 | - | var b [64]byte | |
| 175 | - | n, e := p.Read(b[:]) | |
| 176 | - | if e == nil { | |
| 177 | - | t.Fatalf("unexpected bytes on the wire: %x", b[:n]) | |
| 178 | - | } | |
| 179 | - | if !errors.Is(e, os.ErrDeadlineExceeded) { | |
| 180 | - | t.Fatal(e) | |
| 181 | - | } | |
| 182 | - | } | |
| 183 | - | ||
| 184 | - | // recvRequestFDs reads one client message and the descriptors that came with | |
| 185 | - | // it. Every received descriptor is closed before a fatal failure, so a failed | |
| 186 | - | // check cannot leak them; on success the caller owns fds. | |
| 187 | - | func recvRequestFDs(t *testing.T, p *net.UnixConn) (id uint32, op uint16, body []byte, fds []int) { | |
| 188 | - | t.Helper() | |
| 189 | - | fail := func(format string, args ...any) { | |
| 190 | - | t.Helper() | |
| 191 | - | for _, fd := range fds { | |
| 192 | - | unix.Close(fd) | |
| 193 | - | } | |
| 194 | - | t.Fatalf(format, args...) | |
| 195 | - | } | |
| 196 | - | p.SetReadDeadline(time.Now().Add(2 * time.Second)) | |
| 197 | - | b := make([]byte, 4096) | |
| 198 | - | oob := make([]byte, 256) | |
| 199 | - | n, oobn, _, _, e := p.ReadMsgUnix(b, oob) | |
| 200 | - | if oobn > 0 { | |
| 201 | - | msgs, pe := unix.ParseSocketControlMessage(oob[:oobn]) | |
| 202 | - | for i := range msgs { | |
| 203 | - | r, re := unix.ParseUnixRights(&msgs[i]) | |
| 204 | - | fds = append(fds, r...) | |
| 205 | - | if re != nil && pe == nil { | |
| 206 | - | pe = re | |
| 207 | - | } | |
| 208 | - | } | |
| 209 | - | if pe != nil { | |
| 210 | - | fail("control message: %v", pe) | |
| 211 | - | } | |
| 212 | - | } | |
| 213 | - | if e != nil { | |
| 214 | - | fail("read request: %v", e) | |
| 215 | - | } | |
| 216 | - | if n < 8 { | |
| 217 | - | fail("short request (%d bytes)", n) | |
| 218 | - | } | |
| 219 | - | if size := int(binary.NativeEndian.Uint32(b[4:]) >> 16); size != n { | |
| 220 | - | fail("header size %d != %d bytes read", size, n) | |
| 221 | - | } | |
| 222 | - | return binary.NativeEndian.Uint32(b), uint16(binary.NativeEndian.Uint32(b[4:])), b[8:n], fds | |
| 223 | - | } | |
| 224 | - | ||
| 225 | - | // requestWithFD reads the next request, requires its object and opcode, and | |
| 226 | - | // requires exactly one descriptor, which the caller then owns. | |
| 227 | - | func requestWithFD(t *testing.T, p *net.UnixConn, id uint32, op uint16) ([]byte, int) { | |
| 228 | - | t.Helper() | |
| 229 | - | gid, gop, body, fds := recvRequestFDs(t, p) | |
| 230 | - | if gid != id || gop != op || len(fds) != 1 { | |
| 231 | - | for _, fd := range fds { | |
| 232 | - | unix.Close(fd) | |
| 233 | - | } | |
| 234 | - | t.Fatalf("request object=%d op=%d fds=%d, want object=%d op=%d with 1 descriptor (body %x)", gid, gop, len(fds), id, op, body) | |
| 235 | - | } | |
| 236 | - | return body, fds[0] | |
| 237 | - | } | |
| 238 | - | ||
| 239 | - | // register gives a proxy a client-allocated ID and registers it with d. | |
| 240 | - | func register(d *wlturbo.Display, o wlturbo.Proxy) { | |
| 241 | - | o.SetID(d.AllocateID()) | |
| 242 | - | d.Context().Register(o) | |
| 243 | - | } | |
| 244 | - | ||
| 245 | - | // wireEnv is one client connection against a fake compositor on a socketpair. | |
| 246 | - | type wireEnv struct { | |
| 247 | - | t *testing.T | |
| 248 | - | d *wlturbo.Display | |
| 249 | - | p *net.UnixConn | |
| 250 | - | } | |
| 251 | - | ||
| 252 | - | func newWireEnv(t *testing.T) *wireEnv { | |
| 253 | - | t.Helper() | |
| 254 | - | c, p := pair(t) | |
| 255 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 256 | - | noerr(t, e) | |
| 257 | - | t.Cleanup(func() { d.Close() }) | |
| 258 | - | request(t, p) // wl_display.get_registry | |
| 259 | - | return &wireEnv{t: t, d: d, p: p} | |
| 260 | - | } | |
| 261 | - | ||
| 262 | - | func (s *wireEnv) dispatch() { s.t.Helper(); noerr(s.t, s.d.Dispatch()) } | |
| 263 | - | ||
| 264 | - | // bind advertises and binds a global; see the package-level bind. | |
| 265 | - | func (s *wireEnv) bind(name uint32, iface string, announced, supported uint32, proxy wlturbo.Proxy) { | |
| 266 | - | s.t.Helper() | |
| 267 | - | bind(s.t, s.d, s.p, name, iface, announced, supported, proxy) | |
| 268 | - | } | |
| 269 | - | ||
| 270 | - | // event sends one server event and dispatches it on the client. | |
| 271 | - | func (s *wireEnv) event(id uint32, op uint16, body ...byte) { | |
| 272 | - | s.t.Helper() | |
| 273 | - | s.eventFD(id, op, body) | |
| 274 | - | } | |
| 275 | - | ||
| 276 | - | // eventFD is event for an event that carries descriptors (SCM_RIGHTS). | |
| 277 | - | func (s *wireEnv) eventFD(id uint32, op uint16, body []byte, fd ...int) { | |
| 278 | - | s.t.Helper() | |
| 279 | - | send(s.t, s.p, payload(id, op, body...), fd...) | |
| 280 | - | s.dispatch() | |
| 281 | - | } | |
| 282 | - | ||
| 283 | - | // req reads the next client request and checks its object and opcode. | |
| 284 | - | func (s *wireEnv) req(id uint32, op uint16) []byte { | |
| 285 | - | s.t.Helper() | |
| 286 | - | gid, gop, b := request(s.t, s.p) | |
| 287 | - | if gid != id || gop != op { | |
| 288 | - | s.t.Fatalf("request object=%d op=%d, want object=%d op=%d (body %x)", gid, gop, id, op, b) | |
| 289 | - | } | |
| 290 | - | return b | |
| 291 | - | } | |
| 292 | - | ||
| 293 | - | // reqFD is req for a request that carries exactly one descriptor. | |
| 294 | - | func (s *wireEnv) reqFD(id uint32, op uint16) ([]byte, int) { | |
| 295 | - | s.t.Helper() | |
| 296 | - | return requestWithFD(s.t, s.p, id, op) | |
| 297 | - | } | |
| 298 | - | ||
| 299 | - | // noRequest fails if the client wrote anything. | |
| 300 | - | func (s *wireEnv) noRequest() { s.t.Helper(); requireNoWrite(s.t, s.p) } | |
| 301 | - | ||
| 302 | - | func (s *wireEnv) surface() *core.Surface { | |
| 303 | - | o := core.NewSurface(s.d.Context()) | |
| 304 | - | register(s.d, o) | |
| 305 | - | return o | |
| 306 | - | } | |
| 307 | - | func (s *wireEnv) seat() *core.Seat { | |
| 308 | - | o := core.NewSeat(s.d.Context()) | |
| 309 | - | register(s.d, o) | |
| 310 | - | return o | |
| 311 | - | } | |
| 312 | - | func (s *wireEnv) output() *core.Output { | |
| 313 | - | o := core.NewOutput(s.d.Context()) | |
| 314 | - | register(s.d, o) | |
| 315 | - | return o | |
| 316 | - | } | |
| 317 | - | func (s *wireEnv) pointer() *core.Pointer { | |
| 318 | - | o := core.NewPointer(s.d.Context()) | |
| 319 | - | register(s.d, o) | |
| 320 | - | return o | |
| 321 | - | } | |
| 322 | - | func (s *wireEnv) region() *core.Region { | |
| 323 | - | o := core.NewRegion(s.d.Context()) | |
| 324 | - | register(s.d, o) | |
| 325 | - | return o | |
| 326 | - | } | |
| 327 | - | func (s *wireEnv) buffer() *core.Buffer { | |
| 328 | - | o := core.NewBuffer(s.d.Context()) | |
| 329 | - | register(s.d, o) | |
| 330 | - | return o | |
| 331 | - | } | |
| 332 | - | ||
| 333 | - | func TestExtensionsOverSocketpair(t *testing.T) { | |
| 334 | - | c, p := pair(t) | |
| 335 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 336 | - | noerr(t, e) | |
| 337 | - | defer d.Close() | |
| 338 | - | request(t, p) | |
| 339 | - | // A registry announcement is the only input to optional-global discovery. | |
| 340 | - | send(t, p, payload(d.Registry().ID(), 0, append(msg(0, 0, 11)[8:12], append(str(fractionalscale.WpFractionalScaleManagerInterface), msg(0, 0, 1)[8:12]...)...)...)) | |
| 341 | - | noerr(t, d.Dispatch()) | |
| 342 | - | if g, ok := d.Registry().FindGlobal(fractionalscale.WpFractionalScaleManagerInterface); !ok || g.Version != 1 { | |
| 343 | - | t.Fatal("announced fractional scale missing", g, ok) | |
| 344 | - | } | |
| 345 | - | if _, ok := d.Registry().FindGlobal(textinput.TextInputManagerV3Interface); ok { | |
| 346 | - | t.Fatal("absent text input") | |
| 347 | - | } | |
| 348 | - | // Remove the discovery-only announcement before the bind matrix assigns | |
| 349 | - | // its own global name to this interface. | |
| 350 | - | send(t, p, msg(d.Registry().ID(), 1, 11)) | |
| 351 | - | noerr(t, d.Dispatch()) | |
| 352 | - | surface := core.NewSurface(d.Context()) | |
| 353 | - | surface.SetID(d.AllocateID()) | |
| 354 | - | d.Context().Register(surface) | |
| 355 | - | seat := core.NewSeat(d.Context()) | |
| 356 | - | seat.SetID(d.AllocateID()) | |
| 357 | - | d.Context().Register(seat) | |
| 358 | - | wm := xdgshell.NewXdgWmBase(d.Context()) | |
| 359 | - | bind(t, d, p, 1, xdgshell.XdgWmBaseInterface, 6, 7, wm) | |
| 360 | - | xs, e := wm.GetXdgSurface(surface) | |
| 361 | - | noerr(t, e) | |
| 362 | - | request(t, p) | |
| 363 | - | top, e := xs.GetToplevel() | |
| 364 | - | noerr(t, e) | |
| 365 | - | request(t, p) | |
| 366 | - | var sequence []string | |
| 367 | - | top.OnConfigure(func(w, h int32, states []byte) { | |
| 368 | - | if w != 800 || h != 600 { | |
| 369 | - | t.Fatalf("size %d,%d", w, h) | |
| 370 | - | } | |
| 371 | - | sequence = append(sequence, "top") | |
| 372 | - | }) | |
| 373 | - | xs.OnConfigure(func(serial uint32) { sequence = append(sequence, "surface"); noerr(t, xs.AckConfigure(serial)) }) | |
| 374 | - | send(t, p, payload(top.ID(), 0, append(msg(0, 0, 800, 600)[8:], arr(nil)...)...)) | |
| 375 | - | noerr(t, d.Dispatch()) | |
| 376 | - | send(t, p, msg(xs.ID(), 0, 9)) | |
| 377 | - | noerr(t, d.Dispatch()) | |
| 378 | - | _, op, b := request(t, p) | |
| 379 | - | if op != 4 || binary.NativeEndian.Uint32(b) != 9 || strings.Join(sequence, ",") != "top,surface" { | |
| 380 | - | t.Fatalf("xdg %d %x %v", op, b, sequence) | |
| 381 | - | } | |
| 382 | - | noerr(t, top.Destroy()) | |
| 383 | - | request(t, p) | |
| 384 | - | noerr(t, xs.Destroy()) | |
| 385 | - | request(t, p) | |
| 386 | - | noerr(t, wm.Destroy()) | |
| 387 | - | request(t, p) | |
| 388 | - | dm := linuxdmabuf.NewLinuxDmabuf(d.Context()) | |
| 389 | - | bind(t, d, p, 2, linuxdmabuf.LinuxDmabufInterface, 6, 4, dm) | |
| 390 | - | fb, e := dm.GetDefaultFeedback() | |
| 391 | - | noerr(t, e) | |
| 392 | - | request(t, p) | |
| 393 | - | table, e := os.CreateTemp(t.TempDir(), "table") | |
| 394 | - | noerr(t, e) | |
| 395 | - | var bytes [32]byte | |
| 396 | - | binary.NativeEndian.PutUint32(bytes[:], 0x34325258) | |
| 397 | - | binary.NativeEndian.PutUint64(bytes[8:], 19) | |
| 398 | - | binary.NativeEndian.PutUint32(bytes[16:], 0x34325241) | |
| 399 | - | binary.NativeEndian.PutUint64(bytes[24:], 42) | |
| 400 | - | _, e = table.Write(bytes[:]) | |
| 401 | - | noerr(t, e) | |
| 402 | - | defer table.Close() | |
| 403 | - | var entries []linuxdmabuf.FormatEntry | |
| 404 | - | var indices []uint16 | |
| 405 | - | var feedback []string | |
| 406 | - | fb.OnMainDevice(func(dev []byte) { | |
| 407 | - | if len(dev) != 8 { | |
| 408 | - | t.Fatalf("device %x", dev) | |
| 409 | - | } | |
| 410 | - | feedback = append(feedback, "main") | |
| 411 | - | }) | |
| 412 | - | fb.OnFormatTable(func(fd *wlturbo.OwnedFD, size uint32) { | |
| 413 | - | entries, e = linuxdmabuf.ReadFormatTable(fd, size) | |
| 414 | - | noerr(t, e) | |
| 415 | - | feedback = append(feedback, "table") | |
| 416 | - | }) | |
| 417 | - | fb.OnTrancheTargetDevice(func(dev []byte) { feedback = append(feedback, "target") }) | |
| 418 | - | fb.OnTrancheFormats(func(data []byte) { | |
| 419 | - | indices, e = linuxdmabuf.TrancheIndices(data, len(entries)) | |
| 420 | - | noerr(t, e) | |
| 421 | - | feedback = append(feedback, "formats") | |
| 422 | - | }) | |
| 423 | - | fb.OnTrancheFlags(func(flags uint32) { | |
| 424 | - | if flags != 1 { | |
| 425 | - | t.Fatal(flags) | |
| 426 | - | } | |
| 427 | - | feedback = append(feedback, "flags") | |
| 428 | - | }) | |
| 429 | - | fb.OnTrancheDone(func() { feedback = append(feedback, "tranche") }) | |
| 430 | - | fb.OnDone(func() { feedback = append(feedback, "done") }) | |
| 431 | - | send(t, p, payload(fb.ID(), 2, arr(make([]byte, 8))...)) | |
| 432 | - | noerr(t, d.Dispatch()) | |
| 433 | - | send(t, p, msg(fb.ID(), 1, 32), int(table.Fd())) | |
| 434 | - | noerr(t, d.Dispatch()) | |
| 435 | - | send(t, p, payload(fb.ID(), 4, arr(make([]byte, 8))...)) | |
| 436 | - | noerr(t, d.Dispatch()) | |
| 437 | - | send(t, p, payload(fb.ID(), 5, arr([]byte{0, 0, 1, 0})...)) | |
| 438 | - | noerr(t, d.Dispatch()) | |
| 439 | - | send(t, p, msg(fb.ID(), 6, 1)) | |
| 440 | - | noerr(t, d.Dispatch()) | |
| 441 | - | send(t, p, msg(fb.ID(), 3)) | |
| 442 | - | noerr(t, d.Dispatch()) | |
| 443 | - | send(t, p, msg(fb.ID(), 0)) | |
| 444 | - | noerr(t, d.Dispatch()) | |
| 445 | - | if len(entries) != 2 || entries[1].Modifier != 42 || len(indices) != 2 || indices[1] != 1 || strings.Join(feedback, ",") != "main,table,target,formats,flags,tranche,done" { | |
| 446 | - | t.Fatalf("feedback %v %v %v", entries, indices, feedback) | |
| 447 | - | } | |
| 448 | - | noerr(t, fb.Destroy()) | |
| 449 | - | request(t, p) | |
| 450 | - | params, e := dm.CreateParams() | |
| 451 | - | noerr(t, e) | |
| 452 | - | request(t, p) | |
| 453 | - | f, e := os.Open("/dev/null") | |
| 454 | - | noerr(t, e) | |
| 455 | - | noerr(t, params.Add(int(f.Fd()), 0, 0, 4, 0, 0)) | |
| 456 | - | request(t, p) | |
| 457 | - | if _, e := unix.FcntlInt(f.Fd(), unix.F_GETFD, 0); e == nil { | |
| 458 | - | t.Fatal("sent fd not closed") | |
| 459 | - | } | |
| 460 | - | f.Close() | |
| 461 | - | var buffer *core.Buffer | |
| 462 | - | params.OnCreated(func(b *core.Buffer) { buffer = b }) | |
| 463 | - | params.OnFailed(func() { sequence = append(sequence, "failed") }) | |
| 464 | - | noerr(t, params.Create(1, 1, 0x34325258, 0)) | |
| 465 | - | request(t, p) | |
| 466 | - | send(t, p, msg(params.ID(), 0, 999)) | |
| 467 | - | noerr(t, d.Dispatch()) | |
| 468 | - | if buffer == nil || buffer.ID() != 999 { | |
| 469 | - | t.Fatal("typed buffer missing") | |
| 470 | - | } | |
| 471 | - | noerr(t, buffer.Destroy()) | |
| 472 | - | request(t, p) | |
| 473 | - | noerr(t, params.Destroy()) | |
| 474 | - | request(t, p) | |
| 475 | - | failedParams, e := dm.CreateParams() | |
| 476 | - | noerr(t, e) | |
| 477 | - | request(t, p) | |
| 478 | - | failedParams.OnFailed(func() { sequence = append(sequence, "failed") }) | |
| 479 | - | noerr(t, failedParams.Create(1, 1, 0x34325258, 0)) | |
| 480 | - | request(t, p) | |
| 481 | - | send(t, p, msg(failedParams.ID(), 1)) | |
| 482 | - | noerr(t, d.Dispatch()) | |
| 483 | - | if sequence[len(sequence)-1] != "failed" { | |
| 484 | - | t.Fatal(sequence) | |
| 485 | - | } | |
| 486 | - | noerr(t, failedParams.Destroy()) | |
| 487 | - | request(t, p) | |
| 488 | - | immedParams, e := dm.CreateParams() | |
| 489 | - | noerr(t, e) | |
| 490 | - | request(t, p) | |
| 491 | - | immediate, e := immedParams.CreateImmed(1, 1, 0x34325258, 0) | |
| 492 | - | noerr(t, e) | |
| 493 | - | request(t, p) | |
| 494 | - | noerr(t, immediate.Destroy()) | |
| 495 | - | request(t, p) | |
| 496 | - | noerr(t, immedParams.Destroy()) | |
| 497 | - | request(t, p) | |
| 498 | - | noerr(t, dm.Destroy()) | |
| 499 | - | request(t, p) | |
| 500 | - | sync := drmsyncobj.NewWpLinuxDrmSyncobjManager(d.Context()) | |
| 501 | - | bind(t, d, p, 3, drmsyncobj.WpLinuxDrmSyncobjManagerInterface, 1, 1, sync) | |
| 502 | - | ss, e := sync.GetSurface(surface) | |
| 503 | - | noerr(t, e) | |
| 504 | - | request(t, p) | |
| 505 | - | f, e = os.Open("/dev/null") | |
| 506 | - | noerr(t, e) | |
| 507 | - | tl, e := sync.ImportTimeline(int(f.Fd())) | |
| 508 | - | noerr(t, e) | |
| 509 | - | request(t, p) | |
| 510 | - | if _, e := unix.FcntlInt(f.Fd(), unix.F_GETFD, 0); e == nil { | |
| 511 | - | t.Fatal("timeline fd not closed") | |
| 512 | - | } | |
| 513 | - | f.Close() | |
| 514 | - | noerr(t, ss.SetAcquirePoint(tl, 0x123, 0x456)) | |
| 515 | - | _, op, b = request(t, p) | |
| 516 | - | if op != 1 || binary.NativeEndian.Uint32(b[4:]) != 0x123 || binary.NativeEndian.Uint32(b[8:]) != 0x456 { | |
| 517 | - | t.Fatalf("acquire %d %x", op, b) | |
| 518 | - | } | |
| 519 | - | noerr(t, ss.SetReleasePoint(tl, 0x789, 0xabc)) | |
| 520 | - | _, op, b = request(t, p) | |
| 521 | - | if op != 2 || binary.NativeEndian.Uint32(b[4:]) != 0x789 { | |
| 522 | - | t.Fatalf("release %d %x", op, b) | |
| 523 | - | } | |
| 524 | - | noerr(t, ss.Destroy()) | |
| 525 | - | request(t, p) | |
| 526 | - | noerr(t, tl.Destroy()) | |
| 527 | - | request(t, p) | |
| 528 | - | noerr(t, sync.Destroy()) | |
| 529 | - | request(t, p) | |
| 530 | - | vp := viewporter.NewWpViewporter(d.Context()) | |
| 531 | - | bind(t, d, p, 4, viewporter.WpViewporterInterface, 1, 1, vp) | |
| 532 | - | view, e := vp.GetViewport(surface) | |
| 533 | - | noerr(t, e) | |
| 534 | - | request(t, p) | |
| 535 | - | noerr(t, view.Destroy()) | |
| 536 | - | request(t, p) | |
| 537 | - | noerr(t, vp.Destroy()) | |
| 538 | - | request(t, p) | |
| 539 | - | fs := fractionalscale.NewWpFractionalScaleManager(d.Context()) | |
| 540 | - | bind(t, d, p, 5, fractionalscale.WpFractionalScaleManagerInterface, 1, 1, fs) | |
| 541 | - | scale, e := fs.GetFractionalScale(surface) | |
| 542 | - | noerr(t, e) | |
| 543 | - | request(t, p) | |
| 544 | - | var preferred uint32 | |
| 545 | - | scale.OnPreferredScale(func(v uint32) { preferred = v }) | |
| 546 | - | send(t, p, msg(scale.ID(), 0, 150)) | |
| 547 | - | noerr(t, d.Dispatch()) | |
| 548 | - | if preferred != 150 { | |
| 549 | - | t.Fatal(preferred) | |
| 550 | - | } | |
| 551 | - | noerr(t, scale.Destroy()) | |
| 552 | - | request(t, p) | |
| 553 | - | noerr(t, fs.Destroy()) | |
| 554 | - | request(t, p) | |
| 555 | - | ti := textinput.NewTextInputManagerV3(d.Context()) | |
| 556 | - | bind(t, d, p, 6, textinput.TextInputManagerV3Interface, 2, 1, ti) | |
| 557 | - | input, e := ti.GetTextInput(seat) | |
| 558 | - | noerr(t, e) | |
| 559 | - | request(t, p) | |
| 560 | - | noerr(t, input.Enable()) | |
| 561 | - | request(t, p) | |
| 562 | - | noerr(t, input.SetSurroundingText("hello", 5, 5)) | |
| 563 | - | request(t, p) | |
| 564 | - | noerr(t, input.Commit()) | |
| 565 | - | request(t, p) | |
| 566 | - | var events []string | |
| 567 | - | input.OnPreeditString(func(s string, _, _ int32) { events = append(events, "preedit:"+s) }) | |
| 568 | - | input.OnCommitString(func(s string) { events = append(events, "commit:"+s) }) | |
| 569 | - | input.OnDeleteSurroundingText(func(_, _ uint32) { events = append(events, "delete") }) | |
| 570 | - | input.OnDone(func(uint32) { events = append(events, "done") }) | |
| 571 | - | send(t, p, payload(input.ID(), 2, append(str("é"), msg(0, 0, 0, 0)[8:]...)...)) | |
| 572 | - | noerr(t, d.Dispatch()) | |
| 573 | - | send(t, p, payload(input.ID(), 3, str("hi")...)) | |
| 574 | - | noerr(t, d.Dispatch()) | |
| 575 | - | send(t, p, msg(input.ID(), 4, 1, 2)) | |
| 576 | - | noerr(t, d.Dispatch()) | |
| 577 | - | send(t, p, msg(input.ID(), 5, 1)) | |
| 578 | - | noerr(t, d.Dispatch()) | |
| 579 | - | if strings.Join(events, ",") != "preedit:é,commit:hi,delete,done" { | |
| 580 | - | t.Fatal(events) | |
| 581 | - | } | |
| 582 | - | noerr(t, input.Disable()) | |
| 583 | - | request(t, p) | |
| 584 | - | noerr(t, input.Commit()) | |
| 585 | - | request(t, p) | |
| 586 | - | noerr(t, input.Destroy()) | |
| 587 | - | request(t, p) | |
| 588 | - | noerr(t, ti.Destroy()) | |
| 589 | - | request(t, p) | |
| 590 | - | // Core data-device remains in protocol/core; verify its typed child and | |
| 591 | - | // both directions of clipboard descriptor ownership. | |
| 592 | - | mgr := core.NewDataDeviceManager(d.Context()) | |
| 593 | - | bind(t, d, p, 7, core.DataDeviceManagerInterface, 3, 4, mgr) | |
| 594 | - | device, e := mgr.GetDataDevice(seat) | |
| 595 | - | noerr(t, e) | |
| 596 | - | request(t, p) | |
| 597 | - | source, e := mgr.CreateDataSource() | |
| 598 | - | noerr(t, e) | |
| 599 | - | request(t, p) | |
| 600 | - | var offer *core.DataOffer | |
| 601 | - | device.OnDataOffer(func(o *core.DataOffer) { offer = o }) | |
| 602 | - | send(t, p, msg(device.ID(), 0, 998)) | |
| 603 | - | noerr(t, d.Dispatch()) | |
| 604 | - | if offer == nil || offer.ID() != 998 { | |
| 605 | - | t.Fatal("offer not typed") | |
| 606 | - | } | |
| 607 | - | read, write, e := os.Pipe() | |
| 608 | - | noerr(t, e) | |
| 609 | - | defer read.Close() | |
| 610 | - | noerr(t, offer.Receive("text/plain", int(write.Fd()))) | |
| 611 | - | request(t, p) | |
| 612 | - | if _, e := unix.FcntlInt(write.Fd(), unix.F_GETFD, 0); e == nil { | |
| 613 | - | t.Fatal("clipboard sent fd retained") | |
| 614 | - | } | |
| 615 | - | write.Close() | |
| 616 | - | source.OnSend(func(mime string, fd *wlturbo.OwnedFD) { | |
| 617 | - | if mime != "text/plain" { | |
| 618 | - | t.Fatal(mime) | |
| 619 | - | } | |
| 620 | - | n, e := fd.Take() | |
| 621 | - | noerr(t, e) | |
| 622 | - | unix.Close(n) | |
| 623 | - | }) | |
| 624 | - | received, e := os.Open("/dev/null") | |
| 625 | - | noerr(t, e) | |
| 626 | - | send(t, p, payload(source.ID(), 1, str("text/plain")...), int(received.Fd())) | |
| 627 | - | noerr(t, d.Dispatch()) | |
| 628 | - | received.Close() | |
| 629 | - | noerr(t, offer.Destroy()) | |
| 630 | - | request(t, p) | |
| 631 | - | noerr(t, source.Destroy()) | |
| 632 | - | request(t, p) | |
| 633 | - | noerr(t, device.Release()) | |
| 634 | - | request(t, p) | |
| 635 | - | // release is a version 4 request; the manager was negotiated at 3, so it | |
| 636 | - | // must be refused locally instead of reaching the compositor. | |
| 637 | - | if err := mgr.Release(); !errors.Is(err, wlturbo.ErrVersionTooLow) { | |
| 638 | - | t.Fatalf("release at v3 = %v, want ErrVersionTooLow", err) | |
| 639 | - | } | |
| 640 | - | // Cursor shape: get a device for a wl_pointer and set a shape at an | |
| 641 | - | // enter serial; check the exact wire arguments. | |
| 642 | - | pointer := core.NewPointer(d.Context()) | |
| 643 | - | pointer.SetID(d.AllocateID()) | |
| 644 | - | d.Context().Register(pointer) | |
| 645 | - | shapes := cursorshape.NewWpCursorShapeManager(d.Context()) | |
| 646 | - | bind(t, d, p, 8, cursorshape.WpCursorShapeManagerInterface, 2, 1, shapes) | |
| 647 | - | shape, e := shapes.GetPointer(pointer) | |
| 648 | - | noerr(t, e) | |
| 649 | - | if id, op, b := request(t, p); id != shapes.ID() || op != 1 || binary.NativeEndian.Uint32(b) != shape.ID() || binary.NativeEndian.Uint32(b[4:]) != pointer.ID() { | |
| 650 | - | t.Fatalf("get_pointer wire id=%d op=%d %x", id, op, b) | |
| 651 | - | } | |
| 652 | - | noerr(t, shape.SetShape(42, cursorshape.SHAPE_POINTER)) | |
| 653 | - | if id, op, b := request(t, p); id != shape.ID() || op != 1 || binary.NativeEndian.Uint32(b) != 42 || binary.NativeEndian.Uint32(b[4:]) != 4 { | |
| 654 | - | t.Fatalf("set_shape wire id=%d op=%d %x", id, op, b) | |
| 655 | - | } | |
| 656 | - | noerr(t, shape.Destroy()) | |
| 657 | - | request(t, p) | |
| 658 | - | noerr(t, shapes.Destroy()) | |
| 659 | - | request(t, p) | |
| 660 | - | ||
| 661 | - | } | |
| 662 | - | ||
| 663 | - | func TestLiveFeedback(t *testing.T) { | |
| 664 | - | if os.Getenv("WLTURBO_LIVE") != "1" { | |
| 665 | - | t.Skip("set WLTURBO_LIVE=1") | |
| 666 | - | } | |
| 667 | - | d, e := wlturbo.Connect("") | |
| 668 | - | noerr(t, e) | |
| 669 | - | defer d.Close() | |
| 670 | - | noerr(t, d.Roundtrip()) | |
| 671 | - | for _, iface := range []string{xdgshell.XdgWmBaseInterface, linuxdmabuf.LinuxDmabufInterface, drmsyncobj.WpLinuxDrmSyncobjManagerInterface, viewporter.WpViewporterInterface, fractionalscale.WpFractionalScaleManagerInterface, textinput.TextInputManagerV3Interface, cursorshape.WpCursorShapeManagerInterface} { | |
| 672 | - | g, ok := d.Registry().FindGlobal(iface) | |
| 673 | - | if !ok { | |
| 674 | - | t.Logf("%s absent", iface) | |
| 675 | - | continue | |
| 676 | - | } | |
| 677 | - | v := g.Version | |
| 678 | - | cap := uint32(1) | |
| 679 | - | if iface == xdgshell.XdgWmBaseInterface { | |
| 680 | - | cap = 7 | |
| 681 | - | } | |
| 682 | - | if iface == linuxdmabuf.LinuxDmabufInterface { | |
| 683 | - | cap = 4 | |
| 684 | - | } | |
| 685 | - | if v > cap { | |
| 686 | - | v = cap | |
| 687 | - | } | |
| 688 | - | t.Logf("%s negotiated=%d (server=%d)", iface, v, g.Version) | |
| 689 | - | if iface != linuxdmabuf.LinuxDmabufInterface { | |
| 690 | - | continue | |
| 691 | - | } | |
| 692 | - | if v < 4 { | |
| 693 | - | t.Fatal("dmabuf feedback requires v4") | |
| 694 | - | } | |
| 695 | - | dm := linuxdmabuf.NewLinuxDmabuf(d.Context()) | |
| 696 | - | negotiated, err := d.Registry().BindNegotiated(iface, 4, dm) | |
| 697 | - | noerr(t, err) | |
| 698 | - | if negotiated != v { | |
| 699 | - | t.Fatalf("dmabuf negotiated=%d want=%d", negotiated, v) | |
| 700 | - | } | |
| 701 | - | fb, e := dm.GetDefaultFeedback() | |
| 702 | - | noerr(t, e) | |
| 703 | - | done := false | |
| 704 | - | fb.OnMainDevice(func(b []byte) { t.Logf("main_device=%x", b) }) | |
| 705 | - | fb.OnFormatTable(func(fd *wlturbo.OwnedFD, size uint32) { | |
| 706 | - | entries, err := linuxdmabuf.ReadFormatTable(fd, size) | |
| 707 | - | if err != nil { | |
| 708 | - | t.Errorf("table: %v", err) | |
| 709 | - | } | |
| 710 | - | t.Logf("format-table entries=%d", len(entries)) | |
| 711 | - | }) | |
| 712 | - | fb.OnDone(func() { done = true }) | |
| 713 | - | for i := 0; i < 100 && !done; i++ { | |
| 714 | - | noerr(t, d.Dispatch()) | |
| 715 | - | } | |
| 716 | - | if !done { | |
| 717 | - | t.Fatal("no feedback done") | |
| 718 | - | } | |
| 719 | - | noerr(t, fb.Destroy()) | |
| 720 | - | noerr(t, dm.Destroy()) | |
| 721 | - | } | |
| 722 | - | } | |
D protocol/extforeigntoplevel/ext-foreign-toplevel-list-v1.xml +0 -219
| @@ -1,219 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="ext_foreign_toplevel_list_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2018 Ilia Bozhinov | |
| 5 | - | Copyright © 2020 Isaac Freund | |
| 6 | - | Copyright © 2022 wb9688 | |
| 7 | - | Copyright © 2023 i509VCB | |
| 8 | - | ||
| 9 | - | Permission to use, copy, modify, distribute, and sell this | |
| 10 | - | software and its documentation for any purpose is hereby granted | |
| 11 | - | without fee, provided that the above copyright notice appear in | |
| 12 | - | all copies and that both that copyright notice and this permission | |
| 13 | - | notice appear in supporting documentation, and that the name of | |
| 14 | - | the copyright holders not be used in advertising or publicity | |
| 15 | - | pertaining to distribution of the software without specific, | |
| 16 | - | written prior permission. The copyright holders make no | |
| 17 | - | representations about the suitability of this software for any | |
| 18 | - | purpose. It is provided "as is" without express or implied | |
| 19 | - | warranty. | |
| 20 | - | ||
| 21 | - | THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | |
| 22 | - | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
| 23 | - | FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 24 | - | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 25 | - | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |
| 26 | - | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
| 27 | - | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | |
| 28 | - | THIS SOFTWARE. | |
| 29 | - | </copyright> | |
| 30 | - | ||
| 31 | - | <description summary="list toplevels"> | |
| 32 | - | The purpose of this protocol is to provide protocol object handles for | |
| 33 | - | toplevels, possibly originating from another client. | |
| 34 | - | ||
| 35 | - | This protocol is intentionally minimalistic and expects additional | |
| 36 | - | functionality (e.g. creating a screencopy source from a toplevel handle, | |
| 37 | - | getting information about the state of the toplevel) to be implemented | |
| 38 | - | in extension protocols. | |
| 39 | - | ||
| 40 | - | The compositor may choose to restrict this protocol to a special client | |
| 41 | - | launched by the compositor itself or expose it to all clients, | |
| 42 | - | this is compositor policy. | |
| 43 | - | ||
| 44 | - | The key words "must", "must not", "required", "shall", "shall not", | |
| 45 | - | "should", "should not", "recommended", "may", and "optional" in this | |
| 46 | - | document are to be interpreted as described in IETF RFC 2119. | |
| 47 | - | ||
| 48 | - | Warning! The protocol described in this file is currently in the testing | |
| 49 | - | phase. Backward compatible changes may be added together with the | |
| 50 | - | corresponding interface version bump. Backward incompatible changes can | |
| 51 | - | only be done by creating a new major version of the extension. | |
| 52 | - | </description> | |
| 53 | - | ||
| 54 | - | <interface name="ext_foreign_toplevel_list_v1" version="1"> | |
| 55 | - | <description summary="list toplevels"> | |
| 56 | - | A toplevel is defined as a surface with a role similar to xdg_toplevel. | |
| 57 | - | XWayland surfaces may be treated like toplevels in this protocol. | |
| 58 | - | ||
| 59 | - | After a client binds the ext_foreign_toplevel_list_v1, each mapped | |
| 60 | - | toplevel window will be sent using the ext_foreign_toplevel_list_v1.toplevel | |
| 61 | - | event. | |
| 62 | - | ||
| 63 | - | Clients which only care about the current state can perform a roundtrip after | |
| 64 | - | binding this global. | |
| 65 | - | ||
| 66 | - | For each instance of ext_foreign_toplevel_list_v1, the compositor must | |
| 67 | - | create a new ext_foreign_toplevel_handle_v1 object for each mapped toplevel. | |
| 68 | - | ||
| 69 | - | If a compositor implementation sends the ext_foreign_toplevel_list_v1.finished | |
| 70 | - | event after the global is bound, the compositor must not send any | |
| 71 | - | ext_foreign_toplevel_list_v1.toplevel events. | |
| 72 | - | </description> | |
| 73 | - | ||
| 74 | - | <event name="toplevel"> | |
| 75 | - | <description summary="a toplevel has been created"> | |
| 76 | - | This event is emitted whenever a new toplevel window is created. It is | |
| 77 | - | emitted for all toplevels, regardless of the app that has created them. | |
| 78 | - | ||
| 79 | - | All initial properties of the toplevel (identifier, title, app_id) will be sent | |
| 80 | - | immediately after this event using the corresponding events for | |
| 81 | - | ext_foreign_toplevel_handle_v1. The compositor will use the | |
| 82 | - | ext_foreign_toplevel_handle_v1.done event to indicate when all data has | |
| 83 | - | been sent. | |
| 84 | - | </description> | |
| 85 | - | <arg name="toplevel" type="new_id" interface="ext_foreign_toplevel_handle_v1"/> | |
| 86 | - | </event> | |
| 87 | - | ||
| 88 | - | <event name="finished"> | |
| 89 | - | <description summary="the compositor has finished with the toplevel manager"> | |
| 90 | - | This event indicates that the compositor is done sending events | |
| 91 | - | to this object. The client should destroy the object. | |
| 92 | - | See ext_foreign_toplevel_list_v1.destroy for more information. | |
| 93 | - | ||
| 94 | - | The compositor must not send any more toplevel events after this event. | |
| 95 | - | </description> | |
| 96 | - | </event> | |
| 97 | - | ||
| 98 | - | <request name="stop"> | |
| 99 | - | <description summary="stop sending events"> | |
| 100 | - | This request indicates that the client no longer wishes to receive | |
| 101 | - | events for new toplevels. | |
| 102 | - | ||
| 103 | - | The Wayland protocol is asynchronous, meaning the compositor may send | |
| 104 | - | further toplevel events until the stop request is processed. | |
| 105 | - | The client should wait for a ext_foreign_toplevel_list_v1.finished | |
| 106 | - | event before destroying this object. | |
| 107 | - | </description> | |
| 108 | - | </request> | |
| 109 | - | ||
| 110 | - | <request name="destroy" type="destructor"> | |
| 111 | - | <description summary="destroy the ext_foreign_toplevel_list_v1 object"> | |
| 112 | - | This request should be called either when the client will no longer | |
| 113 | - | use the ext_foreign_toplevel_list_v1 or after the finished event | |
| 114 | - | has been received to allow destruction of the object. | |
| 115 | - | ||
| 116 | - | If a client wishes to destroy this object it should send a | |
| 117 | - | ext_foreign_toplevel_list_v1.stop request and wait for a ext_foreign_toplevel_list_v1.finished | |
| 118 | - | event, then destroy the handles and then this object. | |
| 119 | - | </description> | |
| 120 | - | </request> | |
| 121 | - | </interface> | |
| 122 | - | ||
| 123 | - | <interface name="ext_foreign_toplevel_handle_v1" version="1"> | |
| 124 | - | <description summary="a mapped toplevel"> | |
| 125 | - | A ext_foreign_toplevel_handle_v1 object represents a mapped toplevel | |
| 126 | - | window. A single app may have multiple mapped toplevels. | |
| 127 | - | </description> | |
| 128 | - | ||
| 129 | - | <request name="destroy" type="destructor"> | |
| 130 | - | <description summary="destroy the ext_foreign_toplevel_handle_v1 object"> | |
| 131 | - | This request should be used when the client will no longer use the handle | |
| 132 | - | or after the closed event has been received to allow destruction of the | |
| 133 | - | object. | |
| 134 | - | ||
| 135 | - | When a handle is destroyed, a new handle may not be created by the server | |
| 136 | - | until the toplevel is unmapped and then remapped. Destroying a toplevel handle | |
| 137 | - | is not recommended unless the client is cleaning up child objects | |
| 138 | - | before destroying the ext_foreign_toplevel_list_v1 object, the toplevel | |
| 139 | - | was closed or the toplevel handle will not be used in the future. | |
| 140 | - | ||
| 141 | - | Other protocols which extend the ext_foreign_toplevel_handle_v1 | |
| 142 | - | interface should require destructors for extension interfaces be | |
| 143 | - | called before allowing the toplevel handle to be destroyed. | |
| 144 | - | </description> | |
| 145 | - | </request> | |
| 146 | - | ||
| 147 | - | <event name="closed"> | |
| 148 | - | <description summary="the toplevel has been closed"> | |
| 149 | - | The server will emit no further events on the ext_foreign_toplevel_handle_v1 | |
| 150 | - | after this event. Any requests received aside from the destroy request must | |
| 151 | - | be ignored. Upon receiving this event, the client should destroy the handle. | |
| 152 | - | ||
| 153 | - | Other protocols which extend the ext_foreign_toplevel_handle_v1 | |
| 154 | - | interface must also ignore requests other than destructors. | |
| 155 | - | </description> | |
| 156 | - | </event> | |
| 157 | - | ||
| 158 | - | <event name="done"> | |
| 159 | - | <description summary="all information about the toplevel has been sent"> | |
| 160 | - | This event is sent after all changes in the toplevel state have | |
| 161 | - | been sent. | |
| 162 | - | ||
| 163 | - | This allows changes to the ext_foreign_toplevel_handle_v1 properties | |
| 164 | - | to be atomically applied. Other protocols which extend the | |
| 165 | - | ext_foreign_toplevel_handle_v1 interface may use this event to also | |
| 166 | - | atomically apply any pending state. | |
| 167 | - | ||
| 168 | - | This event must not be sent after the ext_foreign_toplevel_handle_v1.closed | |
| 169 | - | event. | |
| 170 | - | </description> | |
| 171 | - | </event> | |
| 172 | - | ||
| 173 | - | <event name="title"> | |
| 174 | - | <description summary="title change"> | |
| 175 | - | The title of the toplevel has changed. | |
| 176 | - | ||
| 177 | - | The configured state must not be applied immediately. See | |
| 178 | - | ext_foreign_toplevel_handle_v1.done for details. | |
| 179 | - | </description> | |
| 180 | - | <arg name="title" type="string"/> | |
| 181 | - | </event> | |
| 182 | - | ||
| 183 | - | <event name="app_id"> | |
| 184 | - | <description summary="app_id change"> | |
| 185 | - | The app id of the toplevel has changed. | |
| 186 | - | ||
| 187 | - | The configured state must not be applied immediately. See | |
| 188 | - | ext_foreign_toplevel_handle_v1.done for details. | |
| 189 | - | </description> | |
| 190 | - | <arg name="app_id" type="string"/> | |
| 191 | - | </event> | |
| 192 | - | ||
| 193 | - | <event name="identifier"> | |
| 194 | - | <description summary="a stable identifier for a toplevel"> | |
| 195 | - | This identifier is used to check if two or more toplevel handles belong | |
| 196 | - | to the same toplevel. | |
| 197 | - | ||
| 198 | - | The identifier is useful for command line tools or privileged clients | |
| 199 | - | which may need to reference an exact toplevel across processes or | |
| 200 | - | instances of the ext_foreign_toplevel_list_v1 global. | |
| 201 | - | ||
| 202 | - | The compositor must only send this event when the handle is created. | |
| 203 | - | ||
| 204 | - | The identifier must be unique per toplevel and its handles. Two different | |
| 205 | - | toplevels must not have the same identifier. The identifier is only valid | |
| 206 | - | as long as the toplevel is mapped. If the toplevel is unmapped the identifier | |
| 207 | - | must not be reused. An identifier must not be reused by the compositor to | |
| 208 | - | ensure there are no races when sharing identifiers between processes. | |
| 209 | - | ||
| 210 | - | An identifier is a string that contains up to 32 printable ASCII bytes. | |
| 211 | - | An identifier must not be an empty string. It is recommended that a | |
| 212 | - | compositor includes an opaque generation value in identifiers. How the | |
| 213 | - | generation value is used when generating the identifier is implementation | |
| 214 | - | dependent. | |
| 215 | - | </description> | |
| 216 | - | <arg name="identifier" type="string"/> | |
| 217 | - | </event> | |
| 218 | - | </interface> | |
| 219 | - | </protocol> | |
D protocol/extforeigntoplevel/ext-foreign-toplevel-list-v1_generated.go +0 -356
| @@ -1,356 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: ext_foreign_toplevel_list_v1 | |
| 3 | - | // Source: ext-foreign-toplevel-list-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2018 Ilia Bozhinov | |
| 7 | - | // Copyright © 2020 Isaac Freund | |
| 8 | - | // Copyright © 2022 wb9688 | |
| 9 | - | // Copyright © 2023 i509VCB | |
| 10 | - | // | |
| 11 | - | // Permission to use, copy, modify, distribute, and sell this | |
| 12 | - | // software and its documentation for any purpose is hereby granted | |
| 13 | - | // without fee, provided that the above copyright notice appear in | |
| 14 | - | // all copies and that both that copyright notice and this permission | |
| 15 | - | // notice appear in supporting documentation, and that the name of | |
| 16 | - | // the copyright holders not be used in advertising or publicity | |
| 17 | - | // pertaining to distribution of the software without specific, | |
| 18 | - | // written prior permission. The copyright holders make no | |
| 19 | - | // representations about the suitability of this software for any | |
| 20 | - | // purpose. It is provided "as is" without express or implied | |
| 21 | - | // warranty. | |
| 22 | - | // | |
| 23 | - | // THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | |
| 24 | - | // SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
| 25 | - | // FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 26 | - | // SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 27 | - | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |
| 28 | - | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
| 29 | - | // ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | |
| 30 | - | // THIS SOFTWARE. | |
| 31 | - | ||
| 32 | - | package extforeigntoplevel | |
| 33 | - | ||
| 34 | - | import ( | |
| 35 | - | "sync" | |
| 36 | - | ||
| 37 | - | "github.com/bnema/wlturbo/wl" | |
| 38 | - | ) | |
| 39 | - | ||
| 40 | - | // ExtForeignToplevelListInterface is the protocol interface name. | |
| 41 | - | const ExtForeignToplevelListInterface = "ext_foreign_toplevel_list_v1" | |
| 42 | - | ||
| 43 | - | // ExtForeignToplevelList is the generated binding for ext_foreign_toplevel_list_v1 version 1. | |
| 44 | - | type ExtForeignToplevelList struct { | |
| 45 | - | wl.BaseProxy | |
| 46 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 47 | - | // handlers while another goroutine dispatches events. | |
| 48 | - | handlersMu sync.Mutex | |
| 49 | - | onToplevel []func(toplevelObject *ExtForeignToplevelHandle) | |
| 50 | - | onFinished []func() | |
| 51 | - | } | |
| 52 | - | ||
| 53 | - | // NewExtForeignToplevelList returns an unbound ExtForeignToplevelList. | |
| 54 | - | func NewExtForeignToplevelList(ctx *wl.Context) *ExtForeignToplevelList { | |
| 55 | - | obj := &ExtForeignToplevelList{} | |
| 56 | - | obj.SetContext(ctx) | |
| 57 | - | ctx.Register(obj) | |
| 58 | - | return obj | |
| 59 | - | } | |
| 60 | - | ||
| 61 | - | // This request indicates that the client no longer wishes to receive events for new toplevels. The Wayland protocol is asynchronous, meaning the compositor may send further toplevel events until the stop request is processed. The client should wait for a ext_foreign_toplevel_list_v1.finished event before destroying this object. | |
| 62 | - | func (o *ExtForeignToplevelList) Stop() error { | |
| 63 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_foreign_toplevel_list_v1.stop"}); err != nil { | |
| 64 | - | return err | |
| 65 | - | } | |
| 66 | - | return nil | |
| 67 | - | } | |
| 68 | - | ||
| 69 | - | // This request should be called either when the client will no longer use the ext_foreign_toplevel_list_v1 or after the finished event has been received to allow destruction of the object. If a client wishes to destroy this object it should send a ext_foreign_toplevel_list_v1.stop request and wait for a ext_foreign_toplevel_list_v1.finished event, then destroy the handles and then this object. | |
| 70 | - | func (o *ExtForeignToplevelList) Destroy() error { | |
| 71 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_foreign_toplevel_list_v1.destroy", Destructor: true}); err != nil { | |
| 72 | - | return err | |
| 73 | - | } | |
| 74 | - | return nil | |
| 75 | - | } | |
| 76 | - | ||
| 77 | - | // OnToplevel registers a handler for the toplevel event. | |
| 78 | - | // | |
| 79 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 80 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 81 | - | func (o *ExtForeignToplevelList) OnToplevel(handler func(toplevelObject *ExtForeignToplevelHandle)) { | |
| 82 | - | if handler == nil { | |
| 83 | - | return | |
| 84 | - | } | |
| 85 | - | o.handlersMu.Lock() | |
| 86 | - | defer o.handlersMu.Unlock() | |
| 87 | - | o.onToplevel = append(o.onToplevel, handler) | |
| 88 | - | } | |
| 89 | - | ||
| 90 | - | // handlersForToplevel returns the handlers registered for toplevel, taken | |
| 91 | - | // under the lock so a handler may register another handler while events are | |
| 92 | - | // being dispatched. | |
| 93 | - | func (o *ExtForeignToplevelList) handlersForToplevel() []func(toplevelObject *ExtForeignToplevelHandle) { | |
| 94 | - | o.handlersMu.Lock() | |
| 95 | - | defer o.handlersMu.Unlock() | |
| 96 | - | return o.onToplevel | |
| 97 | - | } | |
| 98 | - | ||
| 99 | - | // OnFinished registers a handler for the finished event. | |
| 100 | - | // | |
| 101 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 102 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 103 | - | func (o *ExtForeignToplevelList) OnFinished(handler func()) { | |
| 104 | - | if handler == nil { | |
| 105 | - | return | |
| 106 | - | } | |
| 107 | - | o.handlersMu.Lock() | |
| 108 | - | defer o.handlersMu.Unlock() | |
| 109 | - | o.onFinished = append(o.onFinished, handler) | |
| 110 | - | } | |
| 111 | - | ||
| 112 | - | // handlersForFinished returns the handlers registered for finished, taken | |
| 113 | - | // under the lock so a handler may register another handler while events are | |
| 114 | - | // being dispatched. | |
| 115 | - | func (o *ExtForeignToplevelList) handlersForFinished() []func() { | |
| 116 | - | o.handlersMu.Lock() | |
| 117 | - | defer o.handlersMu.Unlock() | |
| 118 | - | return o.onFinished | |
| 119 | - | } | |
| 120 | - | ||
| 121 | - | // EventSignature returns the declared event argument types in wire order. | |
| 122 | - | func (o *ExtForeignToplevelList) EventSignature(opcode uint16) (string, bool) { | |
| 123 | - | switch opcode { | |
| 124 | - | case 0: | |
| 125 | - | return "new_id,", true | |
| 126 | - | case 1: | |
| 127 | - | return "", true | |
| 128 | - | default: | |
| 129 | - | return "", false | |
| 130 | - | } | |
| 131 | - | } | |
| 132 | - | ||
| 133 | - | // Dispatch decodes one event on ext_foreign_toplevel_list_v1 and calls the registered handlers. | |
| 134 | - | func (o *ExtForeignToplevelList) Dispatch(event *wl.Event) { | |
| 135 | - | switch event.Opcode { | |
| 136 | - | case 0: // toplevel | |
| 137 | - | toplevelID := event.Uint32() | |
| 138 | - | toplevelObject := &ExtForeignToplevelHandle{} | |
| 139 | - | toplevelObject.SetContext(o.Context()) | |
| 140 | - | toplevelObject.SetID(toplevelID) | |
| 141 | - | toplevelObject.SetVersion(o.Version()) | |
| 142 | - | o.Context().Register(toplevelObject) | |
| 143 | - | ||
| 144 | - | for i, handler := range o.handlersForToplevel() { | |
| 145 | - | _ = i | |
| 146 | - | handler(toplevelObject) | |
| 147 | - | } | |
| 148 | - | case 1: // finished | |
| 149 | - | ||
| 150 | - | for i, handler := range o.handlersForFinished() { | |
| 151 | - | _ = i | |
| 152 | - | handler() | |
| 153 | - | } | |
| 154 | - | default: | |
| 155 | - | } | |
| 156 | - | } | |
| 157 | - | ||
| 158 | - | // ExtForeignToplevelHandleInterface is the protocol interface name. | |
| 159 | - | const ExtForeignToplevelHandleInterface = "ext_foreign_toplevel_handle_v1" | |
| 160 | - | ||
| 161 | - | // ExtForeignToplevelHandle is the generated binding for ext_foreign_toplevel_handle_v1 version 1. | |
| 162 | - | type ExtForeignToplevelHandle struct { | |
| 163 | - | wl.BaseProxy | |
| 164 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 165 | - | // handlers while another goroutine dispatches events. | |
| 166 | - | handlersMu sync.Mutex | |
| 167 | - | onClosed []func() | |
| 168 | - | onDone []func() | |
| 169 | - | onTitle []func(title string) | |
| 170 | - | onAppId []func(appId string) | |
| 171 | - | onIdentifier []func(identifier string) | |
| 172 | - | } | |
| 173 | - | ||
| 174 | - | // NewExtForeignToplevelHandle returns an unbound ExtForeignToplevelHandle. | |
| 175 | - | func NewExtForeignToplevelHandle(ctx *wl.Context) *ExtForeignToplevelHandle { | |
| 176 | - | obj := &ExtForeignToplevelHandle{} | |
| 177 | - | obj.SetContext(ctx) | |
| 178 | - | ctx.Register(obj) | |
| 179 | - | return obj | |
| 180 | - | } | |
| 181 | - | ||
| 182 | - | // This request should be used when the client will no longer use the handle or after the closed event has been received to allow destruction of the object. When a handle is destroyed, a new handle may not be created by the server until the toplevel is unmapped and then remapped. Destroying a toplevel handle is not recommended unless the client is cleaning up child objects before destroying the ext_foreign_toplevel_list_v1 object, the toplevel was closed or the toplevel handle will not be used in the future. Other protocols which extend the ext_foreign_toplevel_handle_v1 interface should require destructors for extension interfaces be called before allowing the toplevel handle to be destroyed. | |
| 183 | - | func (o *ExtForeignToplevelHandle) Destroy() error { | |
| 184 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_foreign_toplevel_handle_v1.destroy", Destructor: true}); err != nil { | |
| 185 | - | return err | |
| 186 | - | } | |
| 187 | - | return nil | |
| 188 | - | } | |
| 189 | - | ||
| 190 | - | // OnClosed registers a handler for the closed event. | |
| 191 | - | // | |
| 192 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 193 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 194 | - | func (o *ExtForeignToplevelHandle) OnClosed(handler func()) { | |
| 195 | - | if handler == nil { | |
| 196 | - | return | |
| 197 | - | } | |
| 198 | - | o.handlersMu.Lock() | |
| 199 | - | defer o.handlersMu.Unlock() | |
| 200 | - | o.onClosed = append(o.onClosed, handler) | |
| 201 | - | } | |
| 202 | - | ||
| 203 | - | // handlersForClosed returns the handlers registered for closed, taken | |
| 204 | - | // under the lock so a handler may register another handler while events are | |
| 205 | - | // being dispatched. | |
| 206 | - | func (o *ExtForeignToplevelHandle) handlersForClosed() []func() { | |
| 207 | - | o.handlersMu.Lock() | |
| 208 | - | defer o.handlersMu.Unlock() | |
| 209 | - | return o.onClosed | |
| 210 | - | } | |
| 211 | - | ||
| 212 | - | // OnDone registers a handler for the done event. | |
| 213 | - | // | |
| 214 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 215 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 216 | - | func (o *ExtForeignToplevelHandle) OnDone(handler func()) { | |
| 217 | - | if handler == nil { | |
| 218 | - | return | |
| 219 | - | } | |
| 220 | - | o.handlersMu.Lock() | |
| 221 | - | defer o.handlersMu.Unlock() | |
| 222 | - | o.onDone = append(o.onDone, handler) | |
| 223 | - | } | |
| 224 | - | ||
| 225 | - | // handlersForDone returns the handlers registered for done, taken | |
| 226 | - | // under the lock so a handler may register another handler while events are | |
| 227 | - | // being dispatched. | |
| 228 | - | func (o *ExtForeignToplevelHandle) handlersForDone() []func() { | |
| 229 | - | o.handlersMu.Lock() | |
| 230 | - | defer o.handlersMu.Unlock() | |
| 231 | - | return o.onDone | |
| 232 | - | } | |
| 233 | - | ||
| 234 | - | // OnTitle registers a handler for the title event. | |
| 235 | - | // | |
| 236 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 237 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 238 | - | func (o *ExtForeignToplevelHandle) OnTitle(handler func(title string)) { | |
| 239 | - | if handler == nil { | |
| 240 | - | return | |
| 241 | - | } | |
| 242 | - | o.handlersMu.Lock() | |
| 243 | - | defer o.handlersMu.Unlock() | |
| 244 | - | o.onTitle = append(o.onTitle, handler) | |
| 245 | - | } | |
| 246 | - | ||
| 247 | - | // handlersForTitle returns the handlers registered for title, taken | |
| 248 | - | // under the lock so a handler may register another handler while events are | |
| 249 | - | // being dispatched. | |
| 250 | - | func (o *ExtForeignToplevelHandle) handlersForTitle() []func(title string) { | |
| 251 | - | o.handlersMu.Lock() | |
| 252 | - | defer o.handlersMu.Unlock() | |
| 253 | - | return o.onTitle | |
| 254 | - | } | |
| 255 | - | ||
| 256 | - | // OnAppId registers a handler for the app_id event. | |
| 257 | - | // | |
| 258 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 259 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 260 | - | func (o *ExtForeignToplevelHandle) OnAppId(handler func(appId string)) { | |
| 261 | - | if handler == nil { | |
| 262 | - | return | |
| 263 | - | } | |
| 264 | - | o.handlersMu.Lock() | |
| 265 | - | defer o.handlersMu.Unlock() | |
| 266 | - | o.onAppId = append(o.onAppId, handler) | |
| 267 | - | } | |
| 268 | - | ||
| 269 | - | // handlersForAppId returns the handlers registered for app_id, taken | |
| 270 | - | // under the lock so a handler may register another handler while events are | |
| 271 | - | // being dispatched. | |
| 272 | - | func (o *ExtForeignToplevelHandle) handlersForAppId() []func(appId string) { | |
| 273 | - | o.handlersMu.Lock() | |
| 274 | - | defer o.handlersMu.Unlock() | |
| 275 | - | return o.onAppId | |
| 276 | - | } | |
| 277 | - | ||
| 278 | - | // OnIdentifier registers a handler for the identifier event. | |
| 279 | - | // | |
| 280 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 281 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 282 | - | func (o *ExtForeignToplevelHandle) OnIdentifier(handler func(identifier string)) { | |
| 283 | - | if handler == nil { | |
| 284 | - | return | |
| 285 | - | } | |
| 286 | - | o.handlersMu.Lock() | |
| 287 | - | defer o.handlersMu.Unlock() | |
| 288 | - | o.onIdentifier = append(o.onIdentifier, handler) | |
| 289 | - | } | |
| 290 | - | ||
| 291 | - | // handlersForIdentifier returns the handlers registered for identifier, taken | |
| 292 | - | // under the lock so a handler may register another handler while events are | |
| 293 | - | // being dispatched. | |
| 294 | - | func (o *ExtForeignToplevelHandle) handlersForIdentifier() []func(identifier string) { | |
| 295 | - | o.handlersMu.Lock() | |
| 296 | - | defer o.handlersMu.Unlock() | |
| 297 | - | return o.onIdentifier | |
| 298 | - | } | |
| 299 | - | ||
| 300 | - | // EventSignature returns the declared event argument types in wire order. | |
| 301 | - | func (o *ExtForeignToplevelHandle) EventSignature(opcode uint16) (string, bool) { | |
| 302 | - | switch opcode { | |
| 303 | - | case 0: | |
| 304 | - | return "", true | |
| 305 | - | case 1: | |
| 306 | - | return "", true | |
| 307 | - | case 2: | |
| 308 | - | return "string,", true | |
| 309 | - | case 3: | |
| 310 | - | return "string,", true | |
| 311 | - | case 4: | |
| 312 | - | return "string,", true | |
| 313 | - | default: | |
| 314 | - | return "", false | |
| 315 | - | } | |
| 316 | - | } | |
| 317 | - | ||
| 318 | - | // Dispatch decodes one event on ext_foreign_toplevel_handle_v1 and calls the registered handlers. | |
| 319 | - | func (o *ExtForeignToplevelHandle) Dispatch(event *wl.Event) { | |
| 320 | - | switch event.Opcode { | |
| 321 | - | case 0: // closed | |
| 322 | - | ||
| 323 | - | for i, handler := range o.handlersForClosed() { | |
| 324 | - | _ = i | |
| 325 | - | handler() | |
| 326 | - | } | |
| 327 | - | case 1: // done | |
| 328 | - | ||
| 329 | - | for i, handler := range o.handlersForDone() { | |
| 330 | - | _ = i | |
| 331 | - | handler() | |
| 332 | - | } | |
| 333 | - | case 2: // title | |
| 334 | - | title := event.String() | |
| 335 | - | ||
| 336 | - | for i, handler := range o.handlersForTitle() { | |
| 337 | - | _ = i | |
| 338 | - | handler(title) | |
| 339 | - | } | |
| 340 | - | case 3: // app_id | |
| 341 | - | appId := event.String() | |
| 342 | - | ||
| 343 | - | for i, handler := range o.handlersForAppId() { | |
| 344 | - | _ = i | |
| 345 | - | handler(appId) | |
| 346 | - | } | |
| 347 | - | case 4: // identifier | |
| 348 | - | identifier := event.String() | |
| 349 | - | ||
| 350 | - | for i, handler := range o.handlersForIdentifier() { | |
| 351 | - | _ = i | |
| 352 | - | handler(identifier) | |
| 353 | - | } | |
| 354 | - | default: | |
| 355 | - | } | |
| 356 | - | } | |
D protocol/extforeigntoplevel/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package extforeigntoplevel | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p extforeigntoplevel -o ext-foreign-toplevel-list-v1_generated.go ext-foreign-toplevel-list-v1.xml | |
D protocol/extsessionlock/ext-session-lock-v1.xml +0 -328
| @@ -1,328 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="ext_session_lock_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright 2021 Isaac Freund | |
| 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 shall be included in | |
| 14 | - | all copies or substantial portions of the Software. | |
| 15 | - | ||
| 16 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 17 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 18 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 19 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 20 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 21 | - | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 22 | - | THE SOFTWARE. | |
| 23 | - | </copyright> | |
| 24 | - | ||
| 25 | - | <description summary="secure session locking with arbitrary graphics"> | |
| 26 | - | This protocol allows for a privileged Wayland client to lock the session | |
| 27 | - | and display arbitrary graphics while the session is locked. | |
| 28 | - | ||
| 29 | - | The compositor may choose to restrict this protocol to a special client | |
| 30 | - | launched by the compositor itself or expose it to all privileged clients, | |
| 31 | - | this is compositor policy. | |
| 32 | - | ||
| 33 | - | The client is responsible for performing authentication and informing the | |
| 34 | - | compositor when the session should be unlocked. If the client dies while | |
| 35 | - | the session is locked the session remains locked, possibly permanently | |
| 36 | - | depending on compositor policy. | |
| 37 | - | ||
| 38 | - | The key words "must", "must not", "required", "shall", "shall not", | |
| 39 | - | "should", "should not", "recommended", "may", and "optional" in this | |
| 40 | - | document are to be interpreted as described in IETF RFC 2119. | |
| 41 | - | ||
| 42 | - | Warning! The protocol described in this file is currently in the | |
| 43 | - | testing phase. Backward compatible changes may be added together with | |
| 44 | - | the corresponding interface version bump. Backward incompatible changes | |
| 45 | - | can only be done by creating a new major version of the extension. | |
| 46 | - | </description> | |
| 47 | - | ||
| 48 | - | <interface name="ext_session_lock_manager_v1" version="1"> | |
| 49 | - | <description summary="used to lock the session"> | |
| 50 | - | This interface is used to request that the session be locked. | |
| 51 | - | </description> | |
| 52 | - | ||
| 53 | - | <request name="destroy" type="destructor"> | |
| 54 | - | <description summary="destroy the session lock manager object"> | |
| 55 | - | This informs the compositor that the session lock manager object will | |
| 56 | - | no longer be used. Existing objects created through this interface | |
| 57 | - | remain valid. | |
| 58 | - | </description> | |
| 59 | - | </request> | |
| 60 | - | ||
| 61 | - | <request name="lock"> | |
| 62 | - | <description summary="attempt to lock the session"> | |
| 63 | - | This request creates a session lock and asks the compositor to lock the | |
| 64 | - | session. The compositor will send either the ext_session_lock_v1.locked | |
| 65 | - | or ext_session_lock_v1.finished event on the created object in | |
| 66 | - | response to this request. | |
| 67 | - | </description> | |
| 68 | - | <arg name="id" type="new_id" interface="ext_session_lock_v1"/> | |
| 69 | - | </request> | |
| 70 | - | </interface> | |
| 71 | - | ||
| 72 | - | <interface name="ext_session_lock_v1" version="1"> | |
| 73 | - | <description summary="manage lock state and create lock surfaces"> | |
| 74 | - | In response to the creation of this object the compositor must send | |
| 75 | - | either the locked or finished event. | |
| 76 | - | ||
| 77 | - | The locked event indicates that the session is locked. This means | |
| 78 | - | that the compositor must stop rendering and providing input to normal | |
| 79 | - | clients. Instead the compositor must blank all outputs with an opaque | |
| 80 | - | color such that their normal content is fully hidden. | |
| 81 | - | ||
| 82 | - | The only surfaces that should be rendered while the session is locked | |
| 83 | - | are the lock surfaces created through this interface and optionally, | |
| 84 | - | at the compositor's discretion, special privileged surfaces such as | |
| 85 | - | input methods or portions of desktop shell UIs. | |
| 86 | - | ||
| 87 | - | The locked event must not be sent until a new "locked" frame (either | |
| 88 | - | from a session lock surface or the compositor blanking the output) has | |
| 89 | - | been presented on all outputs and no security sensitive normal/unlocked | |
| 90 | - | content is possibly visible. | |
| 91 | - | ||
| 92 | - | The finished event should be sent immediately on creation of this | |
| 93 | - | object if the compositor decides that the locked event will not be sent. | |
| 94 | - | ||
| 95 | - | The compositor may wait for the client to create and render session lock | |
| 96 | - | surfaces before sending the locked event to avoid displaying intermediate | |
| 97 | - | blank frames. However, it must impose a reasonable time limit if | |
| 98 | - | waiting and send the locked event as soon as the hard requirements | |
| 99 | - | described above can be met if the time limit expires. Clients should | |
| 100 | - | immediately create lock surfaces for all outputs on creation of this | |
| 101 | - | object to make this possible. | |
| 102 | - | ||
| 103 | - | This behavior of the locked event is required in order to prevent | |
| 104 | - | possible race conditions with clients that wish to suspend the system | |
| 105 | - | or similar after locking the session. Without these semantics, clients | |
| 106 | - | triggering a suspend after receiving the locked event would race with | |
| 107 | - | the first "locked" frame being presented and normal/unlocked frames | |
| 108 | - | might be briefly visible as the system is resumed if the suspend | |
| 109 | - | operation wins the race. | |
| 110 | - | ||
| 111 | - | If the client dies while the session is locked, the compositor must not | |
| 112 | - | unlock the session in response. It is acceptable for the session to be | |
| 113 | - | permanently locked if this happens. The compositor may choose to continue | |
| 114 | - | to display the lock surfaces the client had mapped before it died or | |
| 115 | - | alternatively fall back to a solid color, this is compositor policy. | |
| 116 | - | ||
| 117 | - | Compositors may also allow a secure way to recover the session, the | |
| 118 | - | details of this are compositor policy. Compositors may allow a new | |
| 119 | - | client to create a ext_session_lock_v1 object and take responsibility | |
| 120 | - | for unlocking the session, they may even start a new lock client | |
| 121 | - | instance automatically. | |
| 122 | - | </description> | |
| 123 | - | ||
| 124 | - | <enum name="error"> | |
| 125 | - | <entry name="invalid_destroy" value="0" | |
| 126 | - | summary="attempted to destroy session lock while locked"/> | |
| 127 | - | <entry name="invalid_unlock" value="1" | |
| 128 | - | summary="unlock requested but locked event was never sent"/> | |
| 129 | - | <entry name="role" value="2" | |
| 130 | - | summary="given wl_surface already has a role"/> | |
| 131 | - | <entry name="duplicate_output" value="3" | |
| 132 | - | summary="given output already has a lock surface"/> | |
| 133 | - | <entry name="already_constructed" value="4" | |
| 134 | - | summary="given wl_surface has a buffer attached or committed"/> | |
| 135 | - | </enum> | |
| 136 | - | ||
| 137 | - | <request name="destroy" type="destructor"> | |
| 138 | - | <description summary="destroy the session lock"> | |
| 139 | - | This informs the compositor that the lock object will no longer be | |
| 140 | - | used. Existing objects created through this interface remain valid. | |
| 141 | - | ||
| 142 | - | After this request is made, lock surfaces created through this object | |
| 143 | - | should be destroyed by the client as they will no longer be used by | |
| 144 | - | the compositor. | |
| 145 | - | ||
| 146 | - | It is a protocol error to make this request if the locked event was | |
| 147 | - | sent, the unlock_and_destroy request must be used instead. | |
| 148 | - | </description> | |
| 149 | - | </request> | |
| 150 | - | ||
| 151 | - | <event name="locked"> | |
| 152 | - | <description summary="session successfully locked"> | |
| 153 | - | This client is now responsible for displaying graphics while the | |
| 154 | - | session is locked and deciding when to unlock the session. | |
| 155 | - | ||
| 156 | - | The locked event must not be sent until a new "locked" frame has been | |
| 157 | - | presented on all outputs and no security sensitive normal/unlocked | |
| 158 | - | content is possibly visible. | |
| 159 | - | ||
| 160 | - | If this event is sent, making the destroy request is a protocol error, | |
| 161 | - | the lock object must be destroyed using the unlock_and_destroy request. | |
| 162 | - | </description> | |
| 163 | - | </event> | |
| 164 | - | ||
| 165 | - | <event name="finished"> | |
| 166 | - | <description summary="the session lock object should be destroyed"> | |
| 167 | - | The compositor has decided that the session lock should be destroyed | |
| 168 | - | as it will no longer be used by the compositor. Exactly when this | |
| 169 | - | event is sent is compositor policy, but it must never be sent more | |
| 170 | - | than once for a given session lock object. | |
| 171 | - | ||
| 172 | - | This might be sent because there is already another ext_session_lock_v1 | |
| 173 | - | object held by a client, or the compositor has decided to deny the | |
| 174 | - | request to lock the session for some other reason. This might also | |
| 175 | - | be sent because the compositor implements some alternative, secure | |
| 176 | - | way to authenticate and unlock the session. | |
| 177 | - | ||
| 178 | - | The finished event should be sent immediately on creation of this | |
| 179 | - | object if the compositor decides that the locked event will not | |
| 180 | - | be sent. | |
| 181 | - | ||
| 182 | - | If the locked event is sent on creation of this object the finished | |
| 183 | - | event may still be sent at some later time in this object's | |
| 184 | - | lifetime. This is compositor policy. | |
| 185 | - | ||
| 186 | - | Upon receiving this event, the client should make either the destroy | |
| 187 | - | request or the unlock_and_destroy request, depending on whether or | |
| 188 | - | not the locked event was received on this object. | |
| 189 | - | </description> | |
| 190 | - | </event> | |
| 191 | - | ||
| 192 | - | <request name="get_lock_surface"> | |
| 193 | - | <description summary="create a lock surface for a given output"> | |
| 194 | - | The client is expected to create lock surfaces for all outputs | |
| 195 | - | currently present and any new outputs as they are advertised. These | |
| 196 | - | won't be displayed by the compositor unless the lock is successful | |
| 197 | - | and the locked event is sent. | |
| 198 | - | ||
| 199 | - | Providing a wl_surface which already has a role or already has a buffer | |
| 200 | - | attached or committed is a protocol error, as is attaching/committing | |
| 201 | - | a buffer before the first ext_session_lock_surface_v1.configure event. | |
| 202 | - | ||
| 203 | - | Attempting to create more than one lock surface for a given output | |
| 204 | - | is a duplicate_output protocol error. | |
| 205 | - | </description> | |
| 206 | - | <arg name="id" type="new_id" interface="ext_session_lock_surface_v1"/> | |
| 207 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 208 | - | <arg name="output" type="object" interface="wl_output"/> | |
| 209 | - | </request> | |
| 210 | - | ||
| 211 | - | <request name="unlock_and_destroy" type="destructor"> | |
| 212 | - | <description summary="unlock the session, destroying the object"> | |
| 213 | - | This request indicates that the session should be unlocked, for | |
| 214 | - | example because the user has entered their password and it has been | |
| 215 | - | verified by the client. | |
| 216 | - | ||
| 217 | - | This request also informs the compositor that the lock object will | |
| 218 | - | no longer be used and should be destroyed. Existing objects created | |
| 219 | - | through this interface remain valid. | |
| 220 | - | ||
| 221 | - | After this request is made, lock surfaces created through this object | |
| 222 | - | should be destroyed by the client as they will no longer be used by | |
| 223 | - | the compositor. | |
| 224 | - | ||
| 225 | - | It is a protocol error to make this request if the locked event has | |
| 226 | - | not been sent. In that case, the lock object must be destroyed using | |
| 227 | - | the destroy request. | |
| 228 | - | ||
| 229 | - | Note that a correct client that wishes to exit directly after unlocking | |
| 230 | - | the session must use the wl_display.sync request to ensure the server | |
| 231 | - | receives and processes the unlock_and_destroy request. Otherwise | |
| 232 | - | there is no guarantee that the server has unlocked the session due | |
| 233 | - | to the asynchronous nature of the Wayland protocol. For example, | |
| 234 | - | the server might terminate the client with a protocol error before | |
| 235 | - | it processes the unlock_and_destroy request. | |
| 236 | - | </description> | |
| 237 | - | </request> | |
| 238 | - | </interface> | |
| 239 | - | ||
| 240 | - | <interface name="ext_session_lock_surface_v1" version="1"> | |
| 241 | - | <description summary="a surface displayed while the session is locked"> | |
| 242 | - | The client may use lock surfaces to display a screensaver, render a | |
| 243 | - | dialog to enter a password and unlock the session, or however else it | |
| 244 | - | sees fit. | |
| 245 | - | ||
| 246 | - | On binding this interface the compositor will immediately send the | |
| 247 | - | first configure event. After making the ack_configure request in | |
| 248 | - | response to this event the client should attach and commit the first | |
| 249 | - | buffer. Committing the surface before acking the first configure is a | |
| 250 | - | protocol error. Committing the surface with a null buffer at any time | |
| 251 | - | is a protocol error. | |
| 252 | - | ||
| 253 | - | The compositor is free to handle keyboard/pointer focus for lock | |
| 254 | - | surfaces however it chooses. A reasonable way to do this would be to | |
| 255 | - | give the first lock surface created keyboard focus and change keyboard | |
| 256 | - | focus if the user clicks on other surfaces. | |
| 257 | - | </description> | |
| 258 | - | ||
| 259 | - | <enum name="error"> | |
| 260 | - | <entry name="commit_before_first_ack" value="0" | |
| 261 | - | summary="surface committed before first ack_configure request"/> | |
| 262 | - | <entry name="null_buffer" value="1" | |
| 263 | - | summary="surface committed with a null buffer"/> | |
| 264 | - | <entry name="dimensions_mismatch" value="2" | |
| 265 | - | summary="failed to match ack'd width/height"/> | |
| 266 | - | <entry name="invalid_serial" value="3" | |
| 267 | - | summary="serial provided in ack_configure is invalid"/> | |
| 268 | - | </enum> | |
| 269 | - | ||
| 270 | - | <request name="destroy" type="destructor"> | |
| 271 | - | <description summary="destroy the lock surface object"> | |
| 272 | - | This informs the compositor that the lock surface object will no | |
| 273 | - | longer be used. | |
| 274 | - | ||
| 275 | - | It is recommended for a lock client to destroy lock surfaces if | |
| 276 | - | their corresponding wl_output global is removed. | |
| 277 | - | ||
| 278 | - | If a lock surface on an active output is destroyed before the | |
| 279 | - | ext_session_lock_v1.unlock_and_destroy event is sent, the compositor | |
| 280 | - | must fall back to rendering a solid color. | |
| 281 | - | </description> | |
| 282 | - | </request> | |
| 283 | - | ||
| 284 | - | <request name="ack_configure"> | |
| 285 | - | <description summary="ack a configure event"> | |
| 286 | - | When a configure event is received, if a client commits the surface | |
| 287 | - | in response to the configure event, then the client must make an | |
| 288 | - | ack_configure request sometime before the commit request, passing | |
| 289 | - | along the serial of the configure event. | |
| 290 | - | ||
| 291 | - | If the client receives multiple configure events before it can | |
| 292 | - | respond to one, it only has to ack the last configure event. | |
| 293 | - | ||
| 294 | - | A client is not required to commit immediately after sending an | |
| 295 | - | ack_configure request - it may even ack_configure several times | |
| 296 | - | before its next surface commit. | |
| 297 | - | ||
| 298 | - | A client may send multiple ack_configure requests before committing, | |
| 299 | - | but only the last request sent before a commit indicates which | |
| 300 | - | configure event the client really is responding to. | |
| 301 | - | ||
| 302 | - | Sending an ack_configure request consumes the configure event | |
| 303 | - | referenced by the given serial, as well as all older configure events | |
| 304 | - | sent on this object. | |
| 305 | - | ||
| 306 | - | It is a protocol error to issue multiple ack_configure requests | |
| 307 | - | referencing the same configure event or to issue an ack_configure | |
| 308 | - | request referencing a configure event older than the last configure | |
| 309 | - | event acked for a given lock surface. | |
| 310 | - | </description> | |
| 311 | - | <arg name="serial" type="uint" summary="serial from the configure event"/> | |
| 312 | - | </request> | |
| 313 | - | ||
| 314 | - | <event name="configure"> | |
| 315 | - | <description summary="the client should resize its surface"> | |
| 316 | - | This event is sent once on binding the interface and may be sent again | |
| 317 | - | at the compositor's discretion, for example if output geometry changes. | |
| 318 | - | ||
| 319 | - | The width and height are in surface-local coordinates and are exact | |
| 320 | - | requirements. Failing to match these surface dimensions in the next | |
| 321 | - | commit after acking a configure is a protocol error. | |
| 322 | - | </description> | |
| 323 | - | <arg name="serial" type="uint" summary="serial for use in ack_configure"/> | |
| 324 | - | <arg name="width" type="uint"/> | |
| 325 | - | <arg name="height" type="uint"/> | |
| 326 | - | </event> | |
| 327 | - | </interface> | |
| 328 | - | </protocol> | |
D protocol/extsessionlock/ext-session-lock-v1_generated.go +0 -324
| @@ -1,324 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: ext_session_lock_v1 | |
| 3 | - | // Source: ext-session-lock-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright 2021 Isaac Freund | |
| 7 | - | // | |
| 8 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 9 | - | // copy of this software and associated documentation files (the "Software"), | |
| 10 | - | // to deal in the Software without restriction, including without limitation | |
| 11 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 12 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 13 | - | // Software is furnished to do so, subject to the following conditions: | |
| 14 | - | // | |
| 15 | - | // The above copyright notice and this permission notice shall be included in | |
| 16 | - | // all copies or substantial portions of the Software. | |
| 17 | - | // | |
| 18 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 23 | - | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 24 | - | // THE SOFTWARE. | |
| 25 | - | ||
| 26 | - | package extsessionlock | |
| 27 | - | ||
| 28 | - | import ( | |
| 29 | - | "sync" | |
| 30 | - | ||
| 31 | - | cross_wl_output "github.com/bnema/wlturbo/protocol/core" | |
| 32 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 33 | - | "github.com/bnema/wlturbo/wl" | |
| 34 | - | ) | |
| 35 | - | ||
| 36 | - | // ERROR_INVALID_DESTROY is the error invalid_destroy value. | |
| 37 | - | const ERROR_INVALID_DESTROY = 0 | |
| 38 | - | ||
| 39 | - | // ERROR_INVALID_UNLOCK is the error invalid_unlock value. | |
| 40 | - | const ERROR_INVALID_UNLOCK = 1 | |
| 41 | - | ||
| 42 | - | // ERROR_ROLE is the error role value. | |
| 43 | - | const ERROR_ROLE = 2 | |
| 44 | - | ||
| 45 | - | // ERROR_DUPLICATE_OUTPUT is the error duplicate_output value. | |
| 46 | - | const ERROR_DUPLICATE_OUTPUT = 3 | |
| 47 | - | ||
| 48 | - | // ERROR_ALREADY_CONSTRUCTED is the error already_constructed value. | |
| 49 | - | const ERROR_ALREADY_CONSTRUCTED = 4 | |
| 50 | - | ||
| 51 | - | // ERROR_COMMIT_BEFORE_FIRST_ACK is the error commit_before_first_ack value. | |
| 52 | - | const ERROR_COMMIT_BEFORE_FIRST_ACK = 0 | |
| 53 | - | ||
| 54 | - | // ERROR_NULL_BUFFER is the error null_buffer value. | |
| 55 | - | const ERROR_NULL_BUFFER = 1 | |
| 56 | - | ||
| 57 | - | // ERROR_DIMENSIONS_MISMATCH is the error dimensions_mismatch value. | |
| 58 | - | const ERROR_DIMENSIONS_MISMATCH = 2 | |
| 59 | - | ||
| 60 | - | // ERROR_INVALID_SERIAL is the error invalid_serial value. | |
| 61 | - | const ERROR_INVALID_SERIAL = 3 | |
| 62 | - | ||
| 63 | - | // ExtSessionLockManagerInterface is the protocol interface name. | |
| 64 | - | const ExtSessionLockManagerInterface = "ext_session_lock_manager_v1" | |
| 65 | - | ||
| 66 | - | // ExtSessionLockManager is the generated binding for ext_session_lock_manager_v1 version 1. | |
| 67 | - | type ExtSessionLockManager struct { | |
| 68 | - | wl.BaseProxy | |
| 69 | - | } | |
| 70 | - | ||
| 71 | - | // NewExtSessionLockManager returns an unbound ExtSessionLockManager. | |
| 72 | - | func NewExtSessionLockManager(ctx *wl.Context) *ExtSessionLockManager { | |
| 73 | - | obj := &ExtSessionLockManager{} | |
| 74 | - | obj.SetContext(ctx) | |
| 75 | - | ctx.Register(obj) | |
| 76 | - | return obj | |
| 77 | - | } | |
| 78 | - | ||
| 79 | - | // This informs the compositor that the session lock manager object will no longer be used. Existing objects created through this interface remain valid. | |
| 80 | - | func (o *ExtSessionLockManager) Destroy() error { | |
| 81 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_session_lock_manager_v1.destroy", Destructor: true}); err != nil { | |
| 82 | - | return err | |
| 83 | - | } | |
| 84 | - | return nil | |
| 85 | - | } | |
| 86 | - | ||
| 87 | - | // This request creates a session lock and asks the compositor to lock the session. The compositor will send either the ext_session_lock_v1.locked or ext_session_lock_v1.finished event on the created object in response to this request. | |
| 88 | - | func (o *ExtSessionLockManager) Lock() (*ExtSessionLock, error) { | |
| 89 | - | child := &ExtSessionLock{} | |
| 90 | - | child.SetContext(o.Context()) | |
| 91 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_session_lock_manager_v1.lock", Child: child}, wl.ArgObject(child)); err != nil { | |
| 92 | - | return nil, err | |
| 93 | - | } | |
| 94 | - | return child, nil | |
| 95 | - | } | |
| 96 | - | ||
| 97 | - | // EventSignature returns the declared event argument types in wire order. | |
| 98 | - | func (o *ExtSessionLockManager) EventSignature(opcode uint16) (string, bool) { | |
| 99 | - | switch opcode { | |
| 100 | - | default: | |
| 101 | - | return "", false | |
| 102 | - | } | |
| 103 | - | } | |
| 104 | - | ||
| 105 | - | // Dispatch decodes one event on ext_session_lock_manager_v1 and calls the registered handlers. | |
| 106 | - | func (o *ExtSessionLockManager) Dispatch(event *wl.Event) { | |
| 107 | - | switch event.Opcode { | |
| 108 | - | default: | |
| 109 | - | } | |
| 110 | - | } | |
| 111 | - | ||
| 112 | - | // ExtSessionLockInterface is the protocol interface name. | |
| 113 | - | const ExtSessionLockInterface = "ext_session_lock_v1" | |
| 114 | - | ||
| 115 | - | // ExtSessionLock is the generated binding for ext_session_lock_v1 version 1. | |
| 116 | - | type ExtSessionLock struct { | |
| 117 | - | wl.BaseProxy | |
| 118 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 119 | - | // handlers while another goroutine dispatches events. | |
| 120 | - | handlersMu sync.Mutex | |
| 121 | - | onLocked []func() | |
| 122 | - | onFinished []func() | |
| 123 | - | } | |
| 124 | - | ||
| 125 | - | // NewExtSessionLock returns an unbound ExtSessionLock. | |
| 126 | - | func NewExtSessionLock(ctx *wl.Context) *ExtSessionLock { | |
| 127 | - | obj := &ExtSessionLock{} | |
| 128 | - | obj.SetContext(ctx) | |
| 129 | - | ctx.Register(obj) | |
| 130 | - | return obj | |
| 131 | - | } | |
| 132 | - | ||
| 133 | - | // This informs the compositor that the lock object will no longer be used. Existing objects created through this interface remain valid. After this request is made, lock surfaces created through this object should be destroyed by the client as they will no longer be used by the compositor. It is a protocol error to make this request if the locked event was sent, the unlock_and_destroy request must be used instead. | |
| 134 | - | func (o *ExtSessionLock) Destroy() error { | |
| 135 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_session_lock_v1.destroy", Destructor: true}); err != nil { | |
| 136 | - | return err | |
| 137 | - | } | |
| 138 | - | return nil | |
| 139 | - | } | |
| 140 | - | ||
| 141 | - | // The client is expected to create lock surfaces for all outputs currently present and any new outputs as they are advertised. These won't be displayed by the compositor unless the lock is successful and the locked event is sent. Providing a wl_surface which already has a role or already has a buffer attached or committed is a protocol error, as is attaching/committing a buffer before the first ext_session_lock_surface_v1.configure event. Attempting to create more than one lock surface for a given output is a duplicate_output protocol error. | |
| 142 | - | func (o *ExtSessionLock) GetLockSurface(surface *cross_wl_surface.Surface, output *cross_wl_output.Output) (*ExtSessionLockSurface, error) { | |
| 143 | - | var arg1 wl.Object | |
| 144 | - | if surface != nil { | |
| 145 | - | arg1 = surface | |
| 146 | - | } | |
| 147 | - | var arg2 wl.Object | |
| 148 | - | if output != nil { | |
| 149 | - | arg2 = output | |
| 150 | - | } | |
| 151 | - | child := &ExtSessionLockSurface{} | |
| 152 | - | child.SetContext(o.Context()) | |
| 153 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_session_lock_v1.get_lock_surface", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1), wl.ArgObject(arg2)); err != nil { | |
| 154 | - | return nil, err | |
| 155 | - | } | |
| 156 | - | return child, nil | |
| 157 | - | } | |
| 158 | - | ||
| 159 | - | // This request indicates that the session should be unlocked, for example because the user has entered their password and it has been verified by the client. This request also informs the compositor that the lock object will no longer be used and should be destroyed. Existing objects created through this interface remain valid. After this request is made, lock surfaces created through this object should be destroyed by the client as they will no longer be used by the compositor. It is a protocol error to make this request if the locked event has not been sent. In that case, the lock object must be destroyed using the destroy request. Note that a correct client that wishes to exit directly after unlocking the session must use the wl_display.sync request to ensure the server receives and processes the unlock_and_destroy request. Otherwise there is no guarantee that the server has unlocked the session due to the asynchronous nature of the Wayland protocol. For example, the server might terminate the client with a protocol error before it processes the unlock_and_destroy request. | |
| 160 | - | func (o *ExtSessionLock) UnlockAndDestroy() error { | |
| 161 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "ext_session_lock_v1.unlock_and_destroy", Destructor: true}); err != nil { | |
| 162 | - | return err | |
| 163 | - | } | |
| 164 | - | return nil | |
| 165 | - | } | |
| 166 | - | ||
| 167 | - | // OnLocked registers a handler for the locked event. | |
| 168 | - | // | |
| 169 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 170 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 171 | - | func (o *ExtSessionLock) OnLocked(handler func()) { | |
| 172 | - | if handler == nil { | |
| 173 | - | return | |
| 174 | - | } | |
| 175 | - | o.handlersMu.Lock() | |
| 176 | - | defer o.handlersMu.Unlock() | |
| 177 | - | o.onLocked = append(o.onLocked, handler) | |
| 178 | - | } | |
| 179 | - | ||
| 180 | - | // handlersForLocked returns the handlers registered for locked, taken | |
| 181 | - | // under the lock so a handler may register another handler while events are | |
| 182 | - | // being dispatched. | |
| 183 | - | func (o *ExtSessionLock) handlersForLocked() []func() { | |
| 184 | - | o.handlersMu.Lock() | |
| 185 | - | defer o.handlersMu.Unlock() | |
| 186 | - | return o.onLocked | |
| 187 | - | } | |
| 188 | - | ||
| 189 | - | // OnFinished registers a handler for the finished event. | |
| 190 | - | // | |
| 191 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 192 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 193 | - | func (o *ExtSessionLock) OnFinished(handler func()) { | |
| 194 | - | if handler == nil { | |
| 195 | - | return | |
| 196 | - | } | |
| 197 | - | o.handlersMu.Lock() | |
| 198 | - | defer o.handlersMu.Unlock() | |
| 199 | - | o.onFinished = append(o.onFinished, handler) | |
| 200 | - | } | |
| 201 | - | ||
| 202 | - | // handlersForFinished returns the handlers registered for finished, taken | |
| 203 | - | // under the lock so a handler may register another handler while events are | |
| 204 | - | // being dispatched. | |
| 205 | - | func (o *ExtSessionLock) handlersForFinished() []func() { | |
| 206 | - | o.handlersMu.Lock() | |
| 207 | - | defer o.handlersMu.Unlock() | |
| 208 | - | return o.onFinished | |
| 209 | - | } | |
| 210 | - | ||
| 211 | - | // EventSignature returns the declared event argument types in wire order. | |
| 212 | - | func (o *ExtSessionLock) EventSignature(opcode uint16) (string, bool) { | |
| 213 | - | switch opcode { | |
| 214 | - | case 0: | |
| 215 | - | return "", true | |
| 216 | - | case 1: | |
| 217 | - | return "", true | |
| 218 | - | default: | |
| 219 | - | return "", false | |
| 220 | - | } | |
| 221 | - | } | |
| 222 | - | ||
| 223 | - | // Dispatch decodes one event on ext_session_lock_v1 and calls the registered handlers. | |
| 224 | - | func (o *ExtSessionLock) Dispatch(event *wl.Event) { | |
| 225 | - | switch event.Opcode { | |
| 226 | - | case 0: // locked | |
| 227 | - | ||
| 228 | - | for i, handler := range o.handlersForLocked() { | |
| 229 | - | _ = i | |
| 230 | - | handler() | |
| 231 | - | } | |
| 232 | - | case 1: // finished | |
| 233 | - | ||
| 234 | - | for i, handler := range o.handlersForFinished() { | |
| 235 | - | _ = i | |
| 236 | - | handler() | |
| 237 | - | } | |
| 238 | - | default: | |
| 239 | - | } | |
| 240 | - | } | |
| 241 | - | ||
| 242 | - | // ExtSessionLockSurfaceInterface is the protocol interface name. | |
| 243 | - | const ExtSessionLockSurfaceInterface = "ext_session_lock_surface_v1" | |
| 244 | - | ||
| 245 | - | // ExtSessionLockSurface is the generated binding for ext_session_lock_surface_v1 version 1. | |
| 246 | - | type ExtSessionLockSurface struct { | |
| 247 | - | wl.BaseProxy | |
| 248 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 249 | - | // handlers while another goroutine dispatches events. | |
| 250 | - | handlersMu sync.Mutex | |
| 251 | - | onConfigure []func(serial uint32, width uint32, height uint32) | |
| 252 | - | } | |
| 253 | - | ||
| 254 | - | // NewExtSessionLockSurface returns an unbound ExtSessionLockSurface. | |
| 255 | - | func NewExtSessionLockSurface(ctx *wl.Context) *ExtSessionLockSurface { | |
| 256 | - | obj := &ExtSessionLockSurface{} | |
| 257 | - | obj.SetContext(ctx) | |
| 258 | - | ctx.Register(obj) | |
| 259 | - | return obj | |
| 260 | - | } | |
| 261 | - | ||
| 262 | - | // This informs the compositor that the lock surface object will no longer be used. It is recommended for a lock client to destroy lock surfaces if their corresponding wl_output global is removed. If a lock surface on an active output is destroyed before the ext_session_lock_v1.unlock_and_destroy event is sent, the compositor must fall back to rendering a solid color. | |
| 263 | - | func (o *ExtSessionLockSurface) Destroy() error { | |
| 264 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_session_lock_surface_v1.destroy", Destructor: true}); err != nil { | |
| 265 | - | return err | |
| 266 | - | } | |
| 267 | - | return nil | |
| 268 | - | } | |
| 269 | - | ||
| 270 | - | // When a configure event is received, if a client commits the surface in response to the configure event, then the client must make an ack_configure request sometime before the commit request, passing along the serial of the configure event. If the client receives multiple configure events before it can respond to one, it only has to ack the last configure event. A client is not required to commit immediately after sending an ack_configure request - it may even ack_configure several times before its next surface commit. A client may send multiple ack_configure requests before committing, but only the last request sent before a commit indicates which configure event the client really is responding to. Sending an ack_configure request consumes the configure event referenced by the given serial, as well as all older configure events sent on this object. It is a protocol error to issue multiple ack_configure requests referencing the same configure event or to issue an ack_configure request referencing a configure event older than the last configure event acked for a given lock surface. | |
| 271 | - | func (o *ExtSessionLockSurface) AckConfigure(serial uint32) error { | |
| 272 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_session_lock_surface_v1.ack_configure"}, wl.ArgUint(serial)); err != nil { | |
| 273 | - | return err | |
| 274 | - | } | |
| 275 | - | return nil | |
| 276 | - | } | |
| 277 | - | ||
| 278 | - | // OnConfigure registers a handler for the configure event. | |
| 279 | - | // | |
| 280 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 281 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 282 | - | func (o *ExtSessionLockSurface) OnConfigure(handler func(serial uint32, width uint32, height uint32)) { | |
| 283 | - | if handler == nil { | |
| 284 | - | return | |
| 285 | - | } | |
| 286 | - | o.handlersMu.Lock() | |
| 287 | - | defer o.handlersMu.Unlock() | |
| 288 | - | o.onConfigure = append(o.onConfigure, handler) | |
| 289 | - | } | |
| 290 | - | ||
| 291 | - | // handlersForConfigure returns the handlers registered for configure, taken | |
| 292 | - | // under the lock so a handler may register another handler while events are | |
| 293 | - | // being dispatched. | |
| 294 | - | func (o *ExtSessionLockSurface) handlersForConfigure() []func(serial uint32, width uint32, height uint32) { | |
| 295 | - | o.handlersMu.Lock() | |
| 296 | - | defer o.handlersMu.Unlock() | |
| 297 | - | return o.onConfigure | |
| 298 | - | } | |
| 299 | - | ||
| 300 | - | // EventSignature returns the declared event argument types in wire order. | |
| 301 | - | func (o *ExtSessionLockSurface) EventSignature(opcode uint16) (string, bool) { | |
| 302 | - | switch opcode { | |
| 303 | - | case 0: | |
| 304 | - | return "uint,uint,uint,", true | |
| 305 | - | default: | |
| 306 | - | return "", false | |
| 307 | - | } | |
| 308 | - | } | |
| 309 | - | ||
| 310 | - | // Dispatch decodes one event on ext_session_lock_surface_v1 and calls the registered handlers. | |
| 311 | - | func (o *ExtSessionLockSurface) Dispatch(event *wl.Event) { | |
| 312 | - | switch event.Opcode { | |
| 313 | - | case 0: // configure | |
| 314 | - | serial := event.Uint32() | |
| 315 | - | width := event.Uint32() | |
| 316 | - | height := event.Uint32() | |
| 317 | - | ||
| 318 | - | for i, handler := range o.handlersForConfigure() { | |
| 319 | - | _ = i | |
| 320 | - | handler(serial, width, height) | |
| 321 | - | } | |
| 322 | - | default: | |
| 323 | - | } | |
| 324 | - | } | |
D protocol/extsessionlock/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package extsessionlock | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p extsessionlock -o ext-session-lock-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_output=github.com/bnema/wlturbo/protocol/core ext-session-lock-v1.xml | |
D protocol/fifo/fifo-v1.xml +0 -143
| @@ -1,143 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="fifo_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2023 Valve Corporation | |
| 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="wp_fifo_manager_v1" version="1"> | |
| 27 | - | <description summary="protocol for fifo constraints"> | |
| 28 | - | When a Wayland compositor considers applying a content update, | |
| 29 | - | it must ensure all the update's readiness constraints (fences, etc) | |
| 30 | - | are met. | |
| 31 | - | ||
| 32 | - | This protocol provides a way to use the completion of a display refresh | |
| 33 | - | cycle as an additional readiness constraint. | |
| 34 | - | ||
| 35 | - | Warning! The protocol described in this file is currently in the testing | |
| 36 | - | phase. Backward compatible changes may be added together with the | |
| 37 | - | corresponding interface version bump. Backward incompatible changes can | |
| 38 | - | only be done by creating a new major version of the extension. | |
| 39 | - | </description> | |
| 40 | - | ||
| 41 | - | <enum name="error"> | |
| 42 | - | <description summary="fatal presentation error"> | |
| 43 | - | These fatal protocol errors may be emitted in response to | |
| 44 | - | illegal requests. | |
| 45 | - | </description> | |
| 46 | - | <entry name="already_exists" value="0" | |
| 47 | - | summary="fifo manager already exists for surface"/> | |
| 48 | - | </enum> | |
| 49 | - | ||
| 50 | - | <request name="destroy" type="destructor"> | |
| 51 | - | <description summary="unbind from the manager interface"> | |
| 52 | - | Informs the server that the client will no longer be using | |
| 53 | - | this protocol object. Existing objects created by this object | |
| 54 | - | are not affected. | |
| 55 | - | </description> | |
| 56 | - | </request> | |
| 57 | - | ||
| 58 | - | <request name="get_fifo"> | |
| 59 | - | <description summary="request fifo interface for surface"> | |
| 60 | - | Establish a fifo object for a surface that may be used to add | |
| 61 | - | display refresh constraints to content updates. | |
| 62 | - | ||
| 63 | - | Only one such object may exist for a surface and attempting | |
| 64 | - | to create more than one will result in an already_exists | |
| 65 | - | protocol error. If a surface is acted on by multiple software | |
| 66 | - | components, general best practice is that only the component | |
| 67 | - | performing wl_surface.attach operations should use this protocol. | |
| 68 | - | </description> | |
| 69 | - | <arg name="id" type="new_id" interface="wp_fifo_v1"/> | |
| 70 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 71 | - | </request> | |
| 72 | - | </interface> | |
| 73 | - | ||
| 74 | - | <interface name="wp_fifo_v1" version="1"> | |
| 75 | - | <description summary="fifo interface"> | |
| 76 | - | A fifo object for a surface that may be used to add | |
| 77 | - | display refresh constraints to content updates. | |
| 78 | - | </description> | |
| 79 | - | ||
| 80 | - | <enum name="error"> | |
| 81 | - | <description summary="fatal error"> | |
| 82 | - | These fatal protocol errors may be emitted in response to | |
| 83 | - | illegal requests. | |
| 84 | - | </description> | |
| 85 | - | <entry name="surface_destroyed" value="0" | |
| 86 | - | summary="the associated surface no longer exists"/> | |
| 87 | - | </enum> | |
| 88 | - | ||
| 89 | - | <request name="set_barrier"> | |
| 90 | - | <description summary="sets the start point for a fifo constraint"> | |
| 91 | - | When the content update containing the "set_barrier" is applied, | |
| 92 | - | it sets a "fifo_barrier" condition on the surface associated with | |
| 93 | - | the fifo object. The condition is cleared immediately after the | |
| 94 | - | following latching deadline for non-tearing presentation. | |
| 95 | - | ||
| 96 | - | The compositor may clear the condition early if it must do so to | |
| 97 | - | ensure client forward progress assumptions. | |
| 98 | - | ||
| 99 | - | To wait for this condition to clear, use the "wait_barrier" request. | |
| 100 | - | ||
| 101 | - | "set_barrier" is double-buffered state, see wl_surface.commit. | |
| 102 | - | ||
| 103 | - | Requesting set_barrier after the fifo object's surface is | |
| 104 | - | destroyed will generate a "surface_destroyed" error. | |
| 105 | - | </description> | |
| 106 | - | </request> | |
| 107 | - | ||
| 108 | - | <request name="wait_barrier"> | |
| 109 | - | <description summary="adds a fifo constraint to a content update"> | |
| 110 | - | Indicate that this content update is not ready while a | |
| 111 | - | "fifo_barrier" condition is present on the surface. | |
| 112 | - | ||
| 113 | - | This means that when the content update containing "set_barrier" | |
| 114 | - | was made active at a latching deadline, it will be active for | |
| 115 | - | at least one refresh cycle. A content update which is allowed to | |
| 116 | - | tear might become active after a latching deadline if no content | |
| 117 | - | update became active at the deadline. | |
| 118 | - | ||
| 119 | - | The constraint must be ignored if the surface is a subsurface in | |
| 120 | - | synchronized mode. If the surface is not being updated by the | |
| 121 | - | compositor (off-screen, occluded) the compositor may ignore the | |
| 122 | - | constraint. Clients must use an additional mechanism such as | |
| 123 | - | frame callbacks or timestamps to ensure throttling occurs under | |
| 124 | - | all conditions. | |
| 125 | - | ||
| 126 | - | "wait_barrier" is double-buffered state, see wl_surface.commit. | |
| 127 | - | ||
| 128 | - | Requesting "wait_barrier" after the fifo object's surface is | |
| 129 | - | destroyed will generate a "surface_destroyed" error. | |
| 130 | - | </description> | |
| 131 | - | </request> | |
| 132 | - | ||
| 133 | - | <request name="destroy" type="destructor"> | |
| 134 | - | <description summary="destroy the fifo interface"> | |
| 135 | - | Informs the server that the client will no longer be using | |
| 136 | - | this protocol object. | |
| 137 | - | ||
| 138 | - | Surface state changes previously made by this protocol are | |
| 139 | - | unaffected by this object's destruction. | |
| 140 | - | </description> | |
| 141 | - | </request> | |
| 142 | - | </interface> | |
| 143 | - | </protocol> | |
D protocol/fifo/fifo-v1_generated.go +0 -146
| @@ -1,146 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: fifo_v1 | |
| 3 | - | // Source: fifo-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2023 Valve Corporation | |
| 7 | - | // | |
| 8 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 9 | - | // copy of this software and associated documentation files (the "Software"), | |
| 10 | - | // to deal in the Software without restriction, including without limitation | |
| 11 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 12 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 13 | - | // Software is furnished to do so, subject to the following conditions: | |
| 14 | - | // | |
| 15 | - | // The above copyright notice and this permission notice (including the next | |
| 16 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | // Software. | |
| 18 | - | // | |
| 19 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 22 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 24 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 25 | - | // DEALINGS IN THE SOFTWARE. | |
| 26 | - | ||
| 27 | - | package fifo | |
| 28 | - | ||
| 29 | - | import ( | |
| 30 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 31 | - | "github.com/bnema/wlturbo/wl" | |
| 32 | - | ) | |
| 33 | - | ||
| 34 | - | // ERROR_ALREADY_EXISTS is the error already_exists value. | |
| 35 | - | const ERROR_ALREADY_EXISTS = 0 | |
| 36 | - | ||
| 37 | - | // ERROR_SURFACE_DESTROYED is the error surface_destroyed value. | |
| 38 | - | const ERROR_SURFACE_DESTROYED = 0 | |
| 39 | - | ||
| 40 | - | // WpFifoManagerInterface is the protocol interface name. | |
| 41 | - | const WpFifoManagerInterface = "wp_fifo_manager_v1" | |
| 42 | - | ||
| 43 | - | // WpFifoManager is the generated binding for wp_fifo_manager_v1 version 1. | |
| 44 | - | type WpFifoManager struct { | |
| 45 | - | wl.BaseProxy | |
| 46 | - | } | |
| 47 | - | ||
| 48 | - | // NewWpFifoManager returns an unbound WpFifoManager. | |
| 49 | - | func NewWpFifoManager(ctx *wl.Context) *WpFifoManager { | |
| 50 | - | obj := &WpFifoManager{} | |
| 51 | - | obj.SetContext(ctx) | |
| 52 | - | ctx.Register(obj) | |
| 53 | - | return obj | |
| 54 | - | } | |
| 55 | - | ||
| 56 | - | // Informs the server that the client will no longer be using this protocol object. Existing objects created by this object are not affected. | |
| 57 | - | func (o *WpFifoManager) Destroy() error { | |
| 58 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_fifo_manager_v1.destroy", Destructor: true}); err != nil { | |
| 59 | - | return err | |
| 60 | - | } | |
| 61 | - | return nil | |
| 62 | - | } | |
| 63 | - | ||
| 64 | - | // Establish a fifo object for a surface that may be used to add display refresh constraints to content updates. Only one such object may exist for a surface and attempting to create more than one will result in an already_exists protocol error. If a surface is acted on by multiple software components, general best practice is that only the component performing wl_surface.attach operations should use this protocol. | |
| 65 | - | func (o *WpFifoManager) GetFifo(surface *cross_wl_surface.Surface) (*WpFifo, error) { | |
| 66 | - | var arg1 wl.Object | |
| 67 | - | if surface != nil { | |
| 68 | - | arg1 = surface | |
| 69 | - | } | |
| 70 | - | child := &WpFifo{} | |
| 71 | - | child.SetContext(o.Context()) | |
| 72 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_fifo_manager_v1.get_fifo", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 73 | - | return nil, err | |
| 74 | - | } | |
| 75 | - | return child, nil | |
| 76 | - | } | |
| 77 | - | ||
| 78 | - | // EventSignature returns the declared event argument types in wire order. | |
| 79 | - | func (o *WpFifoManager) EventSignature(opcode uint16) (string, bool) { | |
| 80 | - | switch opcode { | |
| 81 | - | default: | |
| 82 | - | return "", false | |
| 83 | - | } | |
| 84 | - | } | |
| 85 | - | ||
| 86 | - | // Dispatch decodes one event on wp_fifo_manager_v1 and calls the registered handlers. | |
| 87 | - | func (o *WpFifoManager) Dispatch(event *wl.Event) { | |
| 88 | - | switch event.Opcode { | |
| 89 | - | default: | |
| 90 | - | } | |
| 91 | - | } | |
| 92 | - | ||
| 93 | - | // WpFifoInterface is the protocol interface name. | |
| 94 | - | const WpFifoInterface = "wp_fifo_v1" | |
| 95 | - | ||
| 96 | - | // WpFifo is the generated binding for wp_fifo_v1 version 1. | |
| 97 | - | type WpFifo struct { | |
| 98 | - | wl.BaseProxy | |
| 99 | - | } | |
| 100 | - | ||
| 101 | - | // NewWpFifo returns an unbound WpFifo. | |
| 102 | - | func NewWpFifo(ctx *wl.Context) *WpFifo { | |
| 103 | - | obj := &WpFifo{} | |
| 104 | - | obj.SetContext(ctx) | |
| 105 | - | ctx.Register(obj) | |
| 106 | - | return obj | |
| 107 | - | } | |
| 108 | - | ||
| 109 | - | // When the content update containing the "set_barrier" is applied, it sets a "fifo_barrier" condition on the surface associated with the fifo object. The condition is cleared immediately after the following latching deadline for non-tearing presentation. The compositor may clear the condition early if it must do so to ensure client forward progress assumptions. To wait for this condition to clear, use the "wait_barrier" request. "set_barrier" is double-buffered state, see wl_surface.commit. Requesting set_barrier after the fifo object's surface is destroyed will generate a "surface_destroyed" error. | |
| 110 | - | func (o *WpFifo) SetBarrier() error { | |
| 111 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_fifo_v1.set_barrier"}); err != nil { | |
| 112 | - | return err | |
| 113 | - | } | |
| 114 | - | return nil | |
| 115 | - | } | |
| 116 | - | ||
| 117 | - | // Indicate that this content update is not ready while a "fifo_barrier" condition is present on the surface. This means that when the content update containing "set_barrier" was made active at a latching deadline, it will be active for at least one refresh cycle. A content update which is allowed to tear might become active after a latching deadline if no content update became active at the deadline. The constraint must be ignored if the surface is a subsurface in synchronized mode. If the surface is not being updated by the compositor (off-screen, occluded) the compositor may ignore the constraint. Clients must use an additional mechanism such as frame callbacks or timestamps to ensure throttling occurs under all conditions. "wait_barrier" is double-buffered state, see wl_surface.commit. Requesting "wait_barrier" after the fifo object's surface is destroyed will generate a "surface_destroyed" error. | |
| 118 | - | func (o *WpFifo) WaitBarrier() error { | |
| 119 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_fifo_v1.wait_barrier"}); err != nil { | |
| 120 | - | return err | |
| 121 | - | } | |
| 122 | - | return nil | |
| 123 | - | } | |
| 124 | - | ||
| 125 | - | // Informs the server that the client will no longer be using this protocol object. Surface state changes previously made by this protocol are unaffected by this object's destruction. | |
| 126 | - | func (o *WpFifo) Destroy() error { | |
| 127 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "wp_fifo_v1.destroy", Destructor: true}); err != nil { | |
| 128 | - | return err | |
| 129 | - | } | |
| 130 | - | return nil | |
| 131 | - | } | |
| 132 | - | ||
| 133 | - | // EventSignature returns the declared event argument types in wire order. | |
| 134 | - | func (o *WpFifo) EventSignature(opcode uint16) (string, bool) { | |
| 135 | - | switch opcode { | |
| 136 | - | default: | |
| 137 | - | return "", false | |
| 138 | - | } | |
| 139 | - | } | |
| 140 | - | ||
| 141 | - | // Dispatch decodes one event on wp_fifo_v1 and calls the registered handlers. | |
| 142 | - | func (o *WpFifo) Dispatch(event *wl.Event) { | |
| 143 | - | switch event.Opcode { | |
| 144 | - | default: | |
| 145 | - | } | |
| 146 | - | } | |
D protocol/fifo/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package fifo | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p fifo -o fifo-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core fifo-v1.xml | |
D protocol/foreigntoplevel/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package foreigntoplevel | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p foreigntoplevel -o wlr-foreign-toplevel-management-unstable-v1_generated.go -import wl_output=github.com/bnema/wlturbo/protocol/core -import wl_seat=github.com/bnema/wlturbo/protocol/core -import wl_surface=github.com/bnema/wlturbo/protocol/core wlr-foreign-toplevel-management-unstable-v1.xml | |
D protocol/foreigntoplevel/wlr-foreign-toplevel-management-unstable-v1.xml +0 -270
| @@ -1,270 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="wlr_foreign_toplevel_management_unstable_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2018 Ilia Bozhinov | |
| 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_foreign_toplevel_manager_v1" version="3"> | |
| 29 | - | <description summary="list and control opened apps"> | |
| 30 | - | The purpose of this protocol is to enable the creation of taskbars | |
| 31 | - | and docks by providing them with a list of opened applications and | |
| 32 | - | letting them request certain actions on them, like maximizing, etc. | |
| 33 | - | ||
| 34 | - | After a client binds the zwlr_foreign_toplevel_manager_v1, each opened | |
| 35 | - | toplevel window will be sent via the toplevel event | |
| 36 | - | </description> | |
| 37 | - | ||
| 38 | - | <event name="toplevel"> | |
| 39 | - | <description summary="a toplevel has been created"> | |
| 40 | - | This event is emitted whenever a new toplevel window is created. It | |
| 41 | - | is emitted for all toplevels, regardless of the app that has created | |
| 42 | - | them. | |
| 43 | - | ||
| 44 | - | All initial details of the toplevel(title, app_id, states, etc.) will | |
| 45 | - | be sent immediately after this event via the corresponding events in | |
| 46 | - | zwlr_foreign_toplevel_handle_v1. | |
| 47 | - | </description> | |
| 48 | - | <arg name="toplevel" type="new_id" interface="zwlr_foreign_toplevel_handle_v1"/> | |
| 49 | - | </event> | |
| 50 | - | ||
| 51 | - | <request name="stop"> | |
| 52 | - | <description summary="stop sending events"> | |
| 53 | - | Indicates the client no longer wishes to receive events for new toplevels. | |
| 54 | - | However the compositor may emit further toplevel_created events, until | |
| 55 | - | the finished event is emitted. | |
| 56 | - | ||
| 57 | - | The client must not send any more requests after this one. | |
| 58 | - | </description> | |
| 59 | - | </request> | |
| 60 | - | ||
| 61 | - | <event name="finished" type="destructor"> | |
| 62 | - | <description summary="the compositor has finished with the toplevel manager"> | |
| 63 | - | This event indicates that the compositor is done sending events to the | |
| 64 | - | zwlr_foreign_toplevel_manager_v1. The server will destroy the object | |
| 65 | - | immediately after sending this request, so it will become invalid and | |
| 66 | - | the client should free any resources associated with it. | |
| 67 | - | </description> | |
| 68 | - | </event> | |
| 69 | - | </interface> | |
| 70 | - | ||
| 71 | - | <interface name="zwlr_foreign_toplevel_handle_v1" version="3"> | |
| 72 | - | <description summary="an opened toplevel"> | |
| 73 | - | A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel | |
| 74 | - | window. Each app may have multiple opened toplevels. | |
| 75 | - | ||
| 76 | - | Each toplevel has a list of outputs it is visible on, conveyed to the | |
| 77 | - | client with the output_enter and output_leave events. | |
| 78 | - | </description> | |
| 79 | - | ||
| 80 | - | <event name="title"> | |
| 81 | - | <description summary="title change"> | |
| 82 | - | This event is emitted whenever the title of the toplevel changes. | |
| 83 | - | </description> | |
| 84 | - | <arg name="title" type="string"/> | |
| 85 | - | </event> | |
| 86 | - | ||
| 87 | - | <event name="app_id"> | |
| 88 | - | <description summary="app-id change"> | |
| 89 | - | This event is emitted whenever the app-id of the toplevel changes. | |
| 90 | - | </description> | |
| 91 | - | <arg name="app_id" type="string"/> | |
| 92 | - | </event> | |
| 93 | - | ||
| 94 | - | <event name="output_enter"> | |
| 95 | - | <description summary="toplevel entered an output"> | |
| 96 | - | This event is emitted whenever the toplevel becomes visible on | |
| 97 | - | the given output. A toplevel may be visible on multiple outputs. | |
| 98 | - | </description> | |
| 99 | - | <arg name="output" type="object" interface="wl_output"/> | |
| 100 | - | </event> | |
| 101 | - | ||
| 102 | - | <event name="output_leave"> | |
| 103 | - | <description summary="toplevel left an output"> | |
| 104 | - | This event is emitted whenever the toplevel stops being visible on | |
| 105 | - | the given output. It is guaranteed that an entered-output event | |
| 106 | - | with the same output has been emitted before this event. | |
| 107 | - | </description> | |
| 108 | - | <arg name="output" type="object" interface="wl_output"/> | |
| 109 | - | </event> | |
| 110 | - | ||
| 111 | - | <request name="set_maximized"> | |
| 112 | - | <description summary="requests that the toplevel be maximized"> | |
| 113 | - | Requests that the toplevel be maximized. If the maximized state actually | |
| 114 | - | changes, this will be indicated by the state event. | |
| 115 | - | </description> | |
| 116 | - | </request> | |
| 117 | - | ||
| 118 | - | <request name="unset_maximized"> | |
| 119 | - | <description summary="requests that the toplevel be unmaximized"> | |
| 120 | - | Requests that the toplevel be unmaximized. If the maximized state actually | |
| 121 | - | changes, this will be indicated by the state event. | |
| 122 | - | </description> | |
| 123 | - | </request> | |
| 124 | - | ||
| 125 | - | <request name="set_minimized"> | |
| 126 | - | <description summary="requests that the toplevel be minimized"> | |
| 127 | - | Requests that the toplevel be minimized. If the minimized state actually | |
| 128 | - | changes, this will be indicated by the state event. | |
| 129 | - | </description> | |
| 130 | - | </request> | |
| 131 | - | ||
| 132 | - | <request name="unset_minimized"> | |
| 133 | - | <description summary="requests that the toplevel be unminimized"> | |
| 134 | - | Requests that the toplevel be unminimized. If the minimized state actually | |
| 135 | - | changes, this will be indicated by the state event. | |
| 136 | - | </description> | |
| 137 | - | </request> | |
| 138 | - | ||
| 139 | - | <request name="activate"> | |
| 140 | - | <description summary="activate the toplevel"> | |
| 141 | - | Request that this toplevel be activated on the given seat. | |
| 142 | - | There is no guarantee the toplevel will be actually activated. | |
| 143 | - | </description> | |
| 144 | - | <arg name="seat" type="object" interface="wl_seat"/> | |
| 145 | - | </request> | |
| 146 | - | ||
| 147 | - | <enum name="state"> | |
| 148 | - | <description summary="types of states on the toplevel"> | |
| 149 | - | The different states that a toplevel can have. These have the same meaning | |
| 150 | - | as the states with the same names defined in xdg-toplevel | |
| 151 | - | </description> | |
| 152 | - | ||
| 153 | - | <entry name="maximized" value="0" summary="the toplevel is maximized"/> | |
| 154 | - | <entry name="minimized" value="1" summary="the toplevel is minimized"/> | |
| 155 | - | <entry name="activated" value="2" summary="the toplevel is active"/> | |
| 156 | - | <entry name="fullscreen" value="3" summary="the toplevel is fullscreen" since="2"/> | |
| 157 | - | </enum> | |
| 158 | - | ||
| 159 | - | <event name="state"> | |
| 160 | - | <description summary="the toplevel state changed"> | |
| 161 | - | This event is emitted immediately after the zlw_foreign_toplevel_handle_v1 | |
| 162 | - | is created and each time the toplevel state changes, either because of a | |
| 163 | - | compositor action or because of a request in this protocol. | |
| 164 | - | </description> | |
| 165 | - | ||
| 166 | - | <arg name="state" type="array"/> | |
| 167 | - | </event> | |
| 168 | - | ||
| 169 | - | <event name="done"> | |
| 170 | - | <description summary="all information about the toplevel has been sent"> | |
| 171 | - | This event is sent after all changes in the toplevel state have been | |
| 172 | - | sent. | |
| 173 | - | ||
| 174 | - | This allows changes to the zwlr_foreign_toplevel_handle_v1 properties | |
| 175 | - | to be seen as atomic, even if they happen via multiple events. | |
| 176 | - | </description> | |
| 177 | - | </event> | |
| 178 | - | ||
| 179 | - | <request name="close"> | |
| 180 | - | <description summary="request that the toplevel be closed"> | |
| 181 | - | Send a request to the toplevel to close itself. The compositor would | |
| 182 | - | typically use a shell-specific method to carry out this request, for | |
| 183 | - | example by sending the xdg_toplevel.close event. However, this gives | |
| 184 | - | no guarantees the toplevel will actually be destroyed. If and when | |
| 185 | - | this happens, the zwlr_foreign_toplevel_handle_v1.closed event will | |
| 186 | - | be emitted. | |
| 187 | - | </description> | |
| 188 | - | </request> | |
| 189 | - | ||
| 190 | - | <request name="set_rectangle"> | |
| 191 | - | <description summary="the rectangle which represents the toplevel"> | |
| 192 | - | The rectangle of the surface specified in this request corresponds to | |
| 193 | - | the place where the app using this protocol represents the given toplevel. | |
| 194 | - | It can be used by the compositor as a hint for some operations, e.g | |
| 195 | - | minimizing. The client is however not required to set this, in which | |
| 196 | - | case the compositor is free to decide some default value. | |
| 197 | - | ||
| 198 | - | If the client specifies more than one rectangle, only the last one is | |
| 199 | - | considered. | |
| 200 | - | ||
| 201 | - | The dimensions are given in surface-local coordinates. | |
| 202 | - | Setting width=height=0 removes the already-set rectangle. | |
| 203 | - | </description> | |
| 204 | - | ||
| 205 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 206 | - | <arg name="x" type="int"/> | |
| 207 | - | <arg name="y" type="int"/> | |
| 208 | - | <arg name="width" type="int"/> | |
| 209 | - | <arg name="height" type="int"/> | |
| 210 | - | </request> | |
| 211 | - | ||
| 212 | - | <enum name="error"> | |
| 213 | - | <entry name="invalid_rectangle" value="0" | |
| 214 | - | summary="the provided rectangle is invalid"/> | |
| 215 | - | </enum> | |
| 216 | - | ||
| 217 | - | <event name="closed"> | |
| 218 | - | <description summary="this toplevel has been destroyed"> | |
| 219 | - | This event means the toplevel has been destroyed. It is guaranteed there | |
| 220 | - | won't be any more events for this zwlr_foreign_toplevel_handle_v1. The | |
| 221 | - | toplevel itself becomes inert so any requests will be ignored except the | |
| 222 | - | destroy request. | |
| 223 | - | </description> | |
| 224 | - | </event> | |
| 225 | - | ||
| 226 | - | <request name="destroy" type="destructor"> | |
| 227 | - | <description summary="destroy the zwlr_foreign_toplevel_handle_v1 object"> | |
| 228 | - | Destroys the zwlr_foreign_toplevel_handle_v1 object. | |
| 229 | - | ||
| 230 | - | This request should be called either when the client does not want to | |
| 231 | - | use the toplevel anymore or after the closed event to finalize the | |
| 232 | - | destruction of the object. | |
| 233 | - | </description> | |
| 234 | - | </request> | |
| 235 | - | ||
| 236 | - | <!-- Version 2 additions --> | |
| 237 | - | ||
| 238 | - | <request name="set_fullscreen" since="2"> | |
| 239 | - | <description summary="request that the toplevel be fullscreened"> | |
| 240 | - | Requests that the toplevel be fullscreened on the given output. If the | |
| 241 | - | fullscreen state and/or the outputs the toplevel is visible on actually | |
| 242 | - | change, this will be indicated by the state and output_enter/leave | |
| 243 | - | events. | |
| 244 | - | ||
| 245 | - | The output parameter is only a hint to the compositor. Also, if output | |
| 246 | - | is NULL, the compositor should decide which output the toplevel will be | |
| 247 | - | fullscreened on, if at all. | |
| 248 | - | </description> | |
| 249 | - | <arg name="output" type="object" interface="wl_output" allow-null="true"/> | |
| 250 | - | </request> | |
| 251 | - | ||
| 252 | - | <request name="unset_fullscreen" since="2"> | |
| 253 | - | <description summary="request that the toplevel be unfullscreened"> | |
| 254 | - | Requests that the toplevel be unfullscreened. If the fullscreen state | |
| 255 | - | actually changes, this will be indicated by the state event. | |
| 256 | - | </description> | |
| 257 | - | </request> | |
| 258 | - | ||
| 259 | - | <!-- Version 3 additions --> | |
| 260 | - | ||
| 261 | - | <event name="parent" since="3"> | |
| 262 | - | <description summary="parent change"> | |
| 263 | - | This event is emitted whenever the parent of the toplevel changes. | |
| 264 | - | ||
| 265 | - | No event is emitted when the parent handle is destroyed by the client. | |
| 266 | - | </description> | |
| 267 | - | <arg name="parent" type="object" interface="zwlr_foreign_toplevel_handle_v1" allow-null="true"/> | |
| 268 | - | </event> | |
| 269 | - | </interface> | |
| 270 | - | </protocol> | |
D protocol/foreigntoplevel/wlr-foreign-toplevel-management-unstable-v1_generated.go +0 -544
| @@ -1,544 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: wlr_foreign_toplevel_management_unstable_v1 | |
| 3 | - | // Source: wlr-foreign-toplevel-management-unstable-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2018 Ilia Bozhinov | |
| 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 | - | ||
| 29 | - | package foreigntoplevel | |
| 30 | - | ||
| 31 | - | import ( | |
| 32 | - | "sync" | |
| 33 | - | ||
| 34 | - | cross_wl_output "github.com/bnema/wlturbo/protocol/core" | |
| 35 | - | cross_wl_seat "github.com/bnema/wlturbo/protocol/core" | |
| 36 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 37 | - | "github.com/bnema/wlturbo/wl" | |
| 38 | - | ) | |
| 39 | - | ||
| 40 | - | // STATE_MAXIMIZED is the state maximized value. | |
| 41 | - | const STATE_MAXIMIZED = 0 | |
| 42 | - | ||
| 43 | - | // STATE_MINIMIZED is the state minimized value. | |
| 44 | - | const STATE_MINIMIZED = 1 | |
| 45 | - | ||
| 46 | - | // STATE_ACTIVATED is the state activated value. | |
| 47 | - | const STATE_ACTIVATED = 2 | |
| 48 | - | ||
| 49 | - | // STATE_FULLSCREEN is the state fullscreen value. | |
| 50 | - | const STATE_FULLSCREEN = 3 | |
| 51 | - | ||
| 52 | - | // ERROR_INVALID_RECTANGLE is the error invalid_rectangle value. | |
| 53 | - | const ERROR_INVALID_RECTANGLE = 0 | |
| 54 | - | ||
| 55 | - | // ForeignToplevelManagerInterface is the protocol interface name. | |
| 56 | - | const ForeignToplevelManagerInterface = "zwlr_foreign_toplevel_manager_v1" | |
| 57 | - | ||
| 58 | - | // ForeignToplevelManager is the generated binding for zwlr_foreign_toplevel_manager_v1 version 3. | |
| 59 | - | type ForeignToplevelManager struct { | |
| 60 | - | wl.BaseProxy | |
| 61 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 62 | - | // handlers while another goroutine dispatches events. | |
| 63 | - | handlersMu sync.Mutex | |
| 64 | - | onToplevel []func(toplevelObject *ForeignToplevelHandle) | |
| 65 | - | onFinished []func() | |
| 66 | - | } | |
| 67 | - | ||
| 68 | - | // NewForeignToplevelManager returns an unbound ForeignToplevelManager. | |
| 69 | - | func NewForeignToplevelManager(ctx *wl.Context) *ForeignToplevelManager { | |
| 70 | - | obj := &ForeignToplevelManager{} | |
| 71 | - | obj.SetContext(ctx) | |
| 72 | - | ctx.Register(obj) | |
| 73 | - | return obj | |
| 74 | - | } | |
| 75 | - | ||
| 76 | - | // Indicates the client no longer wishes to receive events for new toplevels. However the compositor may emit further toplevel_created events, until the finished event is emitted. The client must not send any more requests after this one. | |
| 77 | - | func (o *ForeignToplevelManager) Stop() error { | |
| 78 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwlr_foreign_toplevel_manager_v1.stop"}); err != nil { | |
| 79 | - | return err | |
| 80 | - | } | |
| 81 | - | return nil | |
| 82 | - | } | |
| 83 | - | ||
| 84 | - | // OnToplevel registers a handler for the toplevel event. | |
| 85 | - | // | |
| 86 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 87 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 88 | - | func (o *ForeignToplevelManager) OnToplevel(handler func(toplevelObject *ForeignToplevelHandle)) { | |
| 89 | - | if handler == nil { | |
| 90 | - | return | |
| 91 | - | } | |
| 92 | - | o.handlersMu.Lock() | |
| 93 | - | defer o.handlersMu.Unlock() | |
| 94 | - | o.onToplevel = append(o.onToplevel, handler) | |
| 95 | - | } | |
| 96 | - | ||
| 97 | - | // handlersForToplevel returns the handlers registered for toplevel, taken | |
| 98 | - | // under the lock so a handler may register another handler while events are | |
| 99 | - | // being dispatched. | |
| 100 | - | func (o *ForeignToplevelManager) handlersForToplevel() []func(toplevelObject *ForeignToplevelHandle) { | |
| 101 | - | o.handlersMu.Lock() | |
| 102 | - | defer o.handlersMu.Unlock() | |
| 103 | - | return o.onToplevel | |
| 104 | - | } | |
| 105 | - | ||
| 106 | - | // OnFinished registers a handler for the finished event. | |
| 107 | - | // | |
| 108 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 109 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 110 | - | func (o *ForeignToplevelManager) OnFinished(handler func()) { | |
| 111 | - | if handler == nil { | |
| 112 | - | return | |
| 113 | - | } | |
| 114 | - | o.handlersMu.Lock() | |
| 115 | - | defer o.handlersMu.Unlock() | |
| 116 | - | o.onFinished = append(o.onFinished, handler) | |
| 117 | - | } | |
| 118 | - | ||
| 119 | - | // handlersForFinished returns the handlers registered for finished, taken | |
| 120 | - | // under the lock so a handler may register another handler while events are | |
| 121 | - | // being dispatched. | |
| 122 | - | func (o *ForeignToplevelManager) handlersForFinished() []func() { | |
| 123 | - | o.handlersMu.Lock() | |
| 124 | - | defer o.handlersMu.Unlock() | |
| 125 | - | return o.onFinished | |
| 126 | - | } | |
| 127 | - | ||
| 128 | - | // EventSignature returns the declared event argument types in wire order. | |
| 129 | - | func (o *ForeignToplevelManager) EventSignature(opcode uint16) (string, bool) { | |
| 130 | - | switch opcode { | |
| 131 | - | case 0: | |
| 132 | - | return "new_id,", true | |
| 133 | - | case 1: | |
| 134 | - | return "", true | |
| 135 | - | default: | |
| 136 | - | return "", false | |
| 137 | - | } | |
| 138 | - | } | |
| 139 | - | ||
| 140 | - | // Dispatch decodes one event on zwlr_foreign_toplevel_manager_v1 and calls the registered handlers. | |
| 141 | - | func (o *ForeignToplevelManager) Dispatch(event *wl.Event) { | |
| 142 | - | switch event.Opcode { | |
| 143 | - | case 0: // toplevel | |
| 144 | - | toplevelID := event.Uint32() | |
| 145 | - | toplevelObject := &ForeignToplevelHandle{} | |
| 146 | - | toplevelObject.SetContext(o.Context()) | |
| 147 | - | toplevelObject.SetID(toplevelID) | |
| 148 | - | toplevelObject.SetVersion(o.Version()) | |
| 149 | - | o.Context().Register(toplevelObject) | |
| 150 | - | ||
| 151 | - | for i, handler := range o.handlersForToplevel() { | |
| 152 | - | _ = i | |
| 153 | - | handler(toplevelObject) | |
| 154 | - | } | |
| 155 | - | case 1: // finished | |
| 156 | - | ||
| 157 | - | for i, handler := range o.handlersForFinished() { | |
| 158 | - | _ = i | |
| 159 | - | handler() | |
| 160 | - | } | |
| 161 | - | o.Context().Unregister(o) | |
| 162 | - | default: | |
| 163 | - | } | |
| 164 | - | } | |
| 165 | - | ||
| 166 | - | // ForeignToplevelHandleInterface is the protocol interface name. | |
| 167 | - | const ForeignToplevelHandleInterface = "zwlr_foreign_toplevel_handle_v1" | |
| 168 | - | ||
| 169 | - | // ForeignToplevelHandle is the generated binding for zwlr_foreign_toplevel_handle_v1 version 3. | |
| 170 | - | type ForeignToplevelHandle struct { | |
| 171 | - | wl.BaseProxy | |
| 172 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 173 | - | // handlers while another goroutine dispatches events. | |
| 174 | - | handlersMu sync.Mutex | |
| 175 | - | onTitle []func(title string) | |
| 176 | - | onAppId []func(appId string) | |
| 177 | - | onOutputEnter []func(outputID uint32) | |
| 178 | - | onOutputLeave []func(outputID uint32) | |
| 179 | - | onState []func(state []byte) | |
| 180 | - | onDone []func() | |
| 181 | - | onClosed []func() | |
| 182 | - | onParent []func(parentID uint32) | |
| 183 | - | } | |
| 184 | - | ||
| 185 | - | // NewForeignToplevelHandle returns an unbound ForeignToplevelHandle. | |
| 186 | - | func NewForeignToplevelHandle(ctx *wl.Context) *ForeignToplevelHandle { | |
| 187 | - | obj := &ForeignToplevelHandle{} | |
| 188 | - | obj.SetContext(ctx) | |
| 189 | - | ctx.Register(obj) | |
| 190 | - | return obj | |
| 191 | - | } | |
| 192 | - | ||
| 193 | - | // Requests that the toplevel be maximized. If the maximized state actually changes, this will be indicated by the state event. | |
| 194 | - | func (o *ForeignToplevelHandle) SetMaximized() error { | |
| 195 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwlr_foreign_toplevel_handle_v1.set_maximized"}); err != nil { | |
| 196 | - | return err | |
| 197 | - | } | |
| 198 | - | return nil | |
| 199 | - | } | |
| 200 | - | ||
| 201 | - | // Requests that the toplevel be unmaximized. If the maximized state actually changes, this will be indicated by the state event. | |
| 202 | - | func (o *ForeignToplevelHandle) UnsetMaximized() error { | |
| 203 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "zwlr_foreign_toplevel_handle_v1.unset_maximized"}); err != nil { | |
| 204 | - | return err | |
| 205 | - | } | |
| 206 | - | return nil | |
| 207 | - | } | |
| 208 | - | ||
| 209 | - | // Requests that the toplevel be minimized. If the minimized state actually changes, this will be indicated by the state event. | |
| 210 | - | func (o *ForeignToplevelHandle) SetMinimized() error { | |
| 211 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "zwlr_foreign_toplevel_handle_v1.set_minimized"}); err != nil { | |
| 212 | - | return err | |
| 213 | - | } | |
| 214 | - | return nil | |
| 215 | - | } | |
| 216 | - | ||
| 217 | - | // Requests that the toplevel be unminimized. If the minimized state actually changes, this will be indicated by the state event. | |
| 218 | - | func (o *ForeignToplevelHandle) UnsetMinimized() error { | |
| 219 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 3, Name: "zwlr_foreign_toplevel_handle_v1.unset_minimized"}); err != nil { | |
| 220 | - | return err | |
| 221 | - | } | |
| 222 | - | return nil | |
| 223 | - | } | |
| 224 | - | ||
| 225 | - | // Request that this toplevel be activated on the given seat. There is no guarantee the toplevel will be actually activated. | |
| 226 | - | func (o *ForeignToplevelHandle) Activate(seat *cross_wl_seat.Seat) error { | |
| 227 | - | var arg0 wl.Object | |
| 228 | - | if seat != nil { | |
| 229 | - | arg0 = seat | |
| 230 | - | } | |
| 231 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 4, Name: "zwlr_foreign_toplevel_handle_v1.activate"}, wl.ArgObject(arg0)); err != nil { | |
| 232 | - | return err | |
| 233 | - | } | |
| 234 | - | return nil | |
| 235 | - | } | |
| 236 | - | ||
| 237 | - | // Send a request to the toplevel to close itself. The compositor would typically use a shell-specific method to carry out this request, for example by sending the xdg_toplevel.close event. However, this gives no guarantees the toplevel will actually be destroyed. If and when this happens, the zwlr_foreign_toplevel_handle_v1.closed event will be emitted. | |
| 238 | - | func (o *ForeignToplevelHandle) Close() error { | |
| 239 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 5, Name: "zwlr_foreign_toplevel_handle_v1.close"}); err != nil { | |
| 240 | - | return err | |
| 241 | - | } | |
| 242 | - | return nil | |
| 243 | - | } | |
| 244 | - | ||
| 245 | - | // The rectangle of the surface specified in this request corresponds to the place where the app using this protocol represents the given toplevel. It can be used by the compositor as a hint for some operations, e.g minimizing. The client is however not required to set this, in which case the compositor is free to decide some default value. If the client specifies more than one rectangle, only the last one is considered. The dimensions are given in surface-local coordinates. Setting width=height=0 removes the already-set rectangle. | |
| 246 | - | func (o *ForeignToplevelHandle) SetRectangle(surface *cross_wl_surface.Surface, x int32, y int32, width int32, height int32) error { | |
| 247 | - | var arg0 wl.Object | |
| 248 | - | if surface != nil { | |
| 249 | - | arg0 = surface | |
| 250 | - | } | |
| 251 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 6, Name: "zwlr_foreign_toplevel_handle_v1.set_rectangle"}, wl.ArgObject(arg0), wl.ArgInt(x), wl.ArgInt(y), wl.ArgInt(width), wl.ArgInt(height)); err != nil { | |
| 252 | - | return err | |
| 253 | - | } | |
| 254 | - | return nil | |
| 255 | - | } | |
| 256 | - | ||
| 257 | - | // Destroys the zwlr_foreign_toplevel_handle_v1 object. This request should be called either when the client does not want to use the toplevel anymore or after the closed event to finalize the destruction of the object. | |
| 258 | - | func (o *ForeignToplevelHandle) Destroy() error { | |
| 259 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 7, Name: "zwlr_foreign_toplevel_handle_v1.destroy", Destructor: true}); err != nil { | |
| 260 | - | return err | |
| 261 | - | } | |
| 262 | - | return nil | |
| 263 | - | } | |
| 264 | - | ||
| 265 | - | // Requests that the toplevel be fullscreened on the given output. If the fullscreen state and/or the outputs the toplevel is visible on actually change, this will be indicated by the state and output_enter/leave events. The output parameter is only a hint to the compositor. Also, if output is NULL, the compositor should decide which output the toplevel will be fullscreened on, if at all. | |
| 266 | - | func (o *ForeignToplevelHandle) SetFullscreen(output *cross_wl_output.Output) error { | |
| 267 | - | var arg0 wl.Object | |
| 268 | - | if output != nil { | |
| 269 | - | arg0 = output | |
| 270 | - | } | |
| 271 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 8, Name: "zwlr_foreign_toplevel_handle_v1.set_fullscreen", Since: 2}, wl.ArgObject(arg0)); err != nil { | |
| 272 | - | return err | |
| 273 | - | } | |
| 274 | - | return nil | |
| 275 | - | } | |
| 276 | - | ||
| 277 | - | // Requests that the toplevel be unfullscreened. If the fullscreen state actually changes, this will be indicated by the state event. | |
| 278 | - | func (o *ForeignToplevelHandle) UnsetFullscreen() error { | |
| 279 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 9, Name: "zwlr_foreign_toplevel_handle_v1.unset_fullscreen", Since: 2}); err != nil { | |
| 280 | - | return err | |
| 281 | - | } | |
| 282 | - | return nil | |
| 283 | - | } | |
| 284 | - | ||
| 285 | - | // OnTitle registers a handler for the title event. | |
| 286 | - | // | |
| 287 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 288 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 289 | - | func (o *ForeignToplevelHandle) OnTitle(handler func(title string)) { | |
| 290 | - | if handler == nil { | |
| 291 | - | return | |
| 292 | - | } | |
| 293 | - | o.handlersMu.Lock() | |
| 294 | - | defer o.handlersMu.Unlock() | |
| 295 | - | o.onTitle = append(o.onTitle, handler) | |
| 296 | - | } | |
| 297 | - | ||
| 298 | - | // handlersForTitle returns the handlers registered for title, taken | |
| 299 | - | // under the lock so a handler may register another handler while events are | |
| 300 | - | // being dispatched. | |
| 301 | - | func (o *ForeignToplevelHandle) handlersForTitle() []func(title string) { | |
| 302 | - | o.handlersMu.Lock() | |
| 303 | - | defer o.handlersMu.Unlock() | |
| 304 | - | return o.onTitle | |
| 305 | - | } | |
| 306 | - | ||
| 307 | - | // OnAppId registers a handler for the app_id event. | |
| 308 | - | // | |
| 309 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 310 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 311 | - | func (o *ForeignToplevelHandle) OnAppId(handler func(appId string)) { | |
| 312 | - | if handler == nil { | |
| 313 | - | return | |
| 314 | - | } | |
| 315 | - | o.handlersMu.Lock() | |
| 316 | - | defer o.handlersMu.Unlock() | |
| 317 | - | o.onAppId = append(o.onAppId, handler) | |
| 318 | - | } | |
| 319 | - | ||
| 320 | - | // handlersForAppId returns the handlers registered for app_id, taken | |
| 321 | - | // under the lock so a handler may register another handler while events are | |
| 322 | - | // being dispatched. | |
| 323 | - | func (o *ForeignToplevelHandle) handlersForAppId() []func(appId string) { | |
| 324 | - | o.handlersMu.Lock() | |
| 325 | - | defer o.handlersMu.Unlock() | |
| 326 | - | return o.onAppId | |
| 327 | - | } | |
| 328 | - | ||
| 329 | - | // OnOutputEnter registers a handler for the output_enter event. | |
| 330 | - | // | |
| 331 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 332 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 333 | - | func (o *ForeignToplevelHandle) OnOutputEnter(handler func(outputID uint32)) { | |
| 334 | - | if handler == nil { | |
| 335 | - | return | |
| 336 | - | } | |
| 337 | - | o.handlersMu.Lock() | |
| 338 | - | defer o.handlersMu.Unlock() | |
| 339 | - | o.onOutputEnter = append(o.onOutputEnter, handler) | |
| 340 | - | } | |
| 341 | - | ||
| 342 | - | // handlersForOutputEnter returns the handlers registered for output_enter, taken | |
| 343 | - | // under the lock so a handler may register another handler while events are | |
| 344 | - | // being dispatched. | |
| 345 | - | func (o *ForeignToplevelHandle) handlersForOutputEnter() []func(outputID uint32) { | |
| 346 | - | o.handlersMu.Lock() | |
| 347 | - | defer o.handlersMu.Unlock() | |
| 348 | - | return o.onOutputEnter | |
| 349 | - | } | |
| 350 | - | ||
| 351 | - | // OnOutputLeave registers a handler for the output_leave event. | |
| 352 | - | // | |
| 353 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 354 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 355 | - | func (o *ForeignToplevelHandle) OnOutputLeave(handler func(outputID uint32)) { | |
| 356 | - | if handler == nil { | |
| 357 | - | return | |
| 358 | - | } | |
| 359 | - | o.handlersMu.Lock() | |
| 360 | - | defer o.handlersMu.Unlock() | |
| 361 | - | o.onOutputLeave = append(o.onOutputLeave, handler) | |
| 362 | - | } | |
| 363 | - | ||
| 364 | - | // handlersForOutputLeave returns the handlers registered for output_leave, taken | |
| 365 | - | // under the lock so a handler may register another handler while events are | |
| 366 | - | // being dispatched. | |
| 367 | - | func (o *ForeignToplevelHandle) handlersForOutputLeave() []func(outputID uint32) { | |
| 368 | - | o.handlersMu.Lock() | |
| 369 | - | defer o.handlersMu.Unlock() | |
| 370 | - | return o.onOutputLeave | |
| 371 | - | } | |
| 372 | - | ||
| 373 | - | // OnState registers a handler for the state event. | |
| 374 | - | // | |
| 375 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 376 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 377 | - | func (o *ForeignToplevelHandle) OnState(handler func(state []byte)) { | |
| 378 | - | if handler == nil { | |
| 379 | - | return | |
| 380 | - | } | |
| 381 | - | o.handlersMu.Lock() | |
| 382 | - | defer o.handlersMu.Unlock() | |
| 383 | - | o.onState = append(o.onState, handler) | |
| 384 | - | } | |
| 385 | - | ||
| 386 | - | // handlersForState returns the handlers registered for state, taken | |
| 387 | - | // under the lock so a handler may register another handler while events are | |
| 388 | - | // being dispatched. | |
| 389 | - | func (o *ForeignToplevelHandle) handlersForState() []func(state []byte) { | |
| 390 | - | o.handlersMu.Lock() | |
| 391 | - | defer o.handlersMu.Unlock() | |
| 392 | - | return o.onState | |
| 393 | - | } | |
| 394 | - | ||
| 395 | - | // OnDone registers a handler for the done event. | |
| 396 | - | // | |
| 397 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 398 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 399 | - | func (o *ForeignToplevelHandle) OnDone(handler func()) { | |
| 400 | - | if handler == nil { | |
| 401 | - | return | |
| 402 | - | } | |
| 403 | - | o.handlersMu.Lock() | |
| 404 | - | defer o.handlersMu.Unlock() | |
| 405 | - | o.onDone = append(o.onDone, handler) | |
| 406 | - | } | |
| 407 | - | ||
| 408 | - | // handlersForDone returns the handlers registered for done, taken | |
| 409 | - | // under the lock so a handler may register another handler while events are | |
| 410 | - | // being dispatched. | |
| 411 | - | func (o *ForeignToplevelHandle) handlersForDone() []func() { | |
| 412 | - | o.handlersMu.Lock() | |
| 413 | - | defer o.handlersMu.Unlock() | |
| 414 | - | return o.onDone | |
| 415 | - | } | |
| 416 | - | ||
| 417 | - | // OnClosed registers a handler for the closed event. | |
| 418 | - | // | |
| 419 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 420 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 421 | - | func (o *ForeignToplevelHandle) OnClosed(handler func()) { | |
| 422 | - | if handler == nil { | |
| 423 | - | return | |
| 424 | - | } | |
| 425 | - | o.handlersMu.Lock() | |
| 426 | - | defer o.handlersMu.Unlock() | |
| 427 | - | o.onClosed = append(o.onClosed, handler) | |
| 428 | - | } | |
| 429 | - | ||
| 430 | - | // handlersForClosed returns the handlers registered for closed, taken | |
| 431 | - | // under the lock so a handler may register another handler while events are | |
| 432 | - | // being dispatched. | |
| 433 | - | func (o *ForeignToplevelHandle) handlersForClosed() []func() { | |
| 434 | - | o.handlersMu.Lock() | |
| 435 | - | defer o.handlersMu.Unlock() | |
| 436 | - | return o.onClosed | |
| 437 | - | } | |
| 438 | - | ||
| 439 | - | // OnParent registers a handler for the parent event. | |
| 440 | - | // | |
| 441 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 442 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 443 | - | func (o *ForeignToplevelHandle) OnParent(handler func(parentID uint32)) { | |
| 444 | - | if handler == nil { | |
| 445 | - | return | |
| 446 | - | } | |
| 447 | - | o.handlersMu.Lock() | |
| 448 | - | defer o.handlersMu.Unlock() | |
| 449 | - | o.onParent = append(o.onParent, handler) | |
| 450 | - | } | |
| 451 | - | ||
| 452 | - | // handlersForParent returns the handlers registered for parent, taken | |
| 453 | - | // under the lock so a handler may register another handler while events are | |
| 454 | - | // being dispatched. | |
| 455 | - | func (o *ForeignToplevelHandle) handlersForParent() []func(parentID uint32) { | |
| 456 | - | o.handlersMu.Lock() | |
| 457 | - | defer o.handlersMu.Unlock() | |
| 458 | - | return o.onParent | |
| 459 | - | } | |
| 460 | - | ||
| 461 | - | // EventSignature returns the declared event argument types in wire order. | |
| 462 | - | func (o *ForeignToplevelHandle) EventSignature(opcode uint16) (string, bool) { | |
| 463 | - | switch opcode { | |
| 464 | - | case 0: | |
| 465 | - | return "string,", true | |
| 466 | - | case 1: | |
| 467 | - | return "string,", true | |
| 468 | - | case 2: | |
| 469 | - | return "object,", true | |
| 470 | - | case 3: | |
| 471 | - | return "object,", true | |
| 472 | - | case 4: | |
| 473 | - | return "array,", true | |
| 474 | - | case 5: | |
| 475 | - | return "", true | |
| 476 | - | case 6: | |
| 477 | - | return "", true | |
| 478 | - | case 7: | |
| 479 | - | return "object,", true | |
| 480 | - | default: | |
| 481 | - | return "", false | |
| 482 | - | } | |
| 483 | - | } | |
| 484 | - | ||
| 485 | - | // Dispatch decodes one event on zwlr_foreign_toplevel_handle_v1 and calls the registered handlers. | |
| 486 | - | func (o *ForeignToplevelHandle) Dispatch(event *wl.Event) { | |
| 487 | - | switch event.Opcode { | |
| 488 | - | case 0: // title | |
| 489 | - | title := event.String() | |
| 490 | - | ||
| 491 | - | for i, handler := range o.handlersForTitle() { | |
| 492 | - | _ = i | |
| 493 | - | handler(title) | |
| 494 | - | } | |
| 495 | - | case 1: // app_id | |
| 496 | - | appId := event.String() | |
| 497 | - | ||
| 498 | - | for i, handler := range o.handlersForAppId() { | |
| 499 | - | _ = i | |
| 500 | - | handler(appId) | |
| 501 | - | } | |
| 502 | - | case 2: // output_enter | |
| 503 | - | outputID := event.Uint32() | |
| 504 | - | ||
| 505 | - | for i, handler := range o.handlersForOutputEnter() { | |
| 506 | - | _ = i | |
| 507 | - | handler(outputID) | |
| 508 | - | } | |
| 509 | - | case 3: // output_leave | |
| 510 | - | outputID := event.Uint32() | |
| 511 | - | ||
| 512 | - | for i, handler := range o.handlersForOutputLeave() { | |
| 513 | - | _ = i | |
| 514 | - | handler(outputID) | |
| 515 | - | } | |
| 516 | - | case 4: // state | |
| 517 | - | state := event.Array() | |
| 518 | - | ||
| 519 | - | for i, handler := range o.handlersForState() { | |
| 520 | - | _ = i | |
| 521 | - | handler(state) | |
| 522 | - | } | |
| 523 | - | case 5: // done | |
| 524 | - | ||
| 525 | - | for i, handler := range o.handlersForDone() { | |
| 526 | - | _ = i | |
| 527 | - | handler() | |
| 528 | - | } | |
| 529 | - | case 6: // closed | |
| 530 | - | ||
| 531 | - | for i, handler := range o.handlersForClosed() { | |
| 532 | - | _ = i | |
| 533 | - | handler() | |
| 534 | - | } | |
| 535 | - | case 7: // parent | |
| 536 | - | parentID := event.Uint32() | |
| 537 | - | ||
| 538 | - | for i, handler := range o.handlersForParent() { | |
| 539 | - | _ = i | |
| 540 | - | handler(parentID) | |
| 541 | - | } | |
| 542 | - | default: | |
| 543 | - | } | |
| 544 | - | } | |
D protocol/format_table_test.go +0 -71
| @@ -1,71 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package protocol_test | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "errors" | |
| 7 | - | "github.com/bnema/wlturbo" | |
| 8 | - | "github.com/bnema/wlturbo/protocol/linuxdmabuf" | |
| 9 | - | "golang.org/x/sys/unix" | |
| 10 | - | "io" | |
| 11 | - | "os" | |
| 12 | - | "testing" | |
| 13 | - | ) | |
| 14 | - | ||
| 15 | - | // Exercise format_table through generated event dispatch so the received FD | |
| 16 | - | // has real transport ownership; verify closing by inspecting the taken FD. | |
| 17 | - | func TestMalformedFormatTables(t *testing.T) { | |
| 18 | - | for _, tc := range []struct { | |
| 19 | - | name string | |
| 20 | - | contents []byte | |
| 21 | - | size uint32 | |
| 22 | - | wantErr bool | |
| 23 | - | }{ | |
| 24 | - | {"unaligned", make([]byte, 16), 17, true}, | |
| 25 | - | {"truncated", make([]byte, 16), 32, true}, | |
| 26 | - | {"zero", nil, 0, false}, | |
| 27 | - | {"oversize", nil, (16 << 20) + 16, true}, | |
| 28 | - | } { | |
| 29 | - | t.Run(tc.name, func(t *testing.T) { | |
| 30 | - | c, p := pair(t) | |
| 31 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 32 | - | noerr(t, e) | |
| 33 | - | defer d.Close() | |
| 34 | - | request(t, p) | |
| 35 | - | fb := linuxdmabuf.NewLinuxDmabufFeedback(d.Context()) | |
| 36 | - | fb.SetID(d.AllocateID()) | |
| 37 | - | d.Context().Register(fb) | |
| 38 | - | file, e := os.CreateTemp(t.TempDir(), "table") | |
| 39 | - | noerr(t, e) | |
| 40 | - | defer file.Close() | |
| 41 | - | _, e = file.Write(tc.contents) | |
| 42 | - | noerr(t, e) | |
| 43 | - | called := false | |
| 44 | - | fb.OnFormatTable(func(fd *wlturbo.OwnedFD, size uint32) { | |
| 45 | - | called = true | |
| 46 | - | entries, err := linuxdmabuf.ReadFormatTable(fd, size) | |
| 47 | - | if (err != nil) != tc.wantErr { | |
| 48 | - | t.Fatalf("size=%d entries=%v err=%v", size, entries, err) | |
| 49 | - | } | |
| 50 | - | if tc.name == "truncated" && !errors.Is(err, io.ErrUnexpectedEOF) { | |
| 51 | - | t.Fatalf("short read: %v", err) | |
| 52 | - | } | |
| 53 | - | // Take/Close must be idempotent, including after a failed size check. | |
| 54 | - | if _, err = fd.Take(); err == nil { | |
| 55 | - | t.Fatal("already consumed fd still takeable") | |
| 56 | - | } | |
| 57 | - | noerr(t, fd.Close()) | |
| 58 | - | noerr(t, fd.Close()) | |
| 59 | - | }) | |
| 60 | - | send(t, p, msg(fb.ID(), 1, tc.size), int(file.Fd())) | |
| 61 | - | noerr(t, d.Dispatch()) | |
| 62 | - | if !called { | |
| 63 | - | t.Fatal("no callback") | |
| 64 | - | } | |
| 65 | - | // The transport FD was a duplicate: caller's descriptor is still open. | |
| 66 | - | if _, e = unix.FcntlInt(file.Fd(), unix.F_GETFD, 0); e != nil { | |
| 67 | - | t.Fatalf("sender fd closed: %v", e) | |
| 68 | - | } | |
| 69 | - | }) | |
| 70 | - | } | |
| 71 | - | } | |
D protocol/fractionalscale/fractional-scale-v1.xml +0 -102
| @@ -1,102 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="fractional_scale_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2022 Kenny Levinsen | |
| 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="Protocol for requesting fractional surface scales"> | |
| 27 | - | This protocol allows a compositor to suggest for surfaces to render at | |
| 28 | - | fractional scales. | |
| 29 | - | ||
| 30 | - | A client can submit scaled content by utilizing wp_viewport. This is done by | |
| 31 | - | creating a wp_viewport object for the surface and setting the destination | |
| 32 | - | rectangle to the surface size before the scale factor is applied. | |
| 33 | - | ||
| 34 | - | The buffer size is calculated by multiplying the surface size by the | |
| 35 | - | intended scale. | |
| 36 | - | ||
| 37 | - | The wl_surface buffer scale should remain set to 1. | |
| 38 | - | ||
| 39 | - | If a surface has a surface-local size of 100 px by 50 px and wishes to | |
| 40 | - | submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should | |
| 41 | - | be used and the wp_viewport destination rectangle should be 100 px by 50 px. | |
| 42 | - | ||
| 43 | - | For toplevel surfaces, the size is rounded halfway away from zero. The | |
| 44 | - | rounding algorithm for subsurface position and size is not defined. | |
| 45 | - | </description> | |
| 46 | - | ||
| 47 | - | <interface name="wp_fractional_scale_manager_v1" version="1"> | |
| 48 | - | <description summary="fractional surface scale information"> | |
| 49 | - | A global interface for requesting surfaces to use fractional scales. | |
| 50 | - | </description> | |
| 51 | - | ||
| 52 | - | <request name="destroy" type="destructor"> | |
| 53 | - | <description summary="unbind the fractional surface scale interface"> | |
| 54 | - | Informs the server that the client will not be using this protocol | |
| 55 | - | object anymore. This does not affect any other objects, | |
| 56 | - | wp_fractional_scale_v1 objects included. | |
| 57 | - | </description> | |
| 58 | - | </request> | |
| 59 | - | ||
| 60 | - | <enum name="error"> | |
| 61 | - | <entry name="fractional_scale_exists" value="0" | |
| 62 | - | summary="the surface already has a fractional_scale object associated"/> | |
| 63 | - | </enum> | |
| 64 | - | ||
| 65 | - | <request name="get_fractional_scale"> | |
| 66 | - | <description summary="extend surface interface for scale information"> | |
| 67 | - | Create an add-on object for the the wl_surface to let the compositor | |
| 68 | - | request fractional scales. If the given wl_surface already has a | |
| 69 | - | wp_fractional_scale_v1 object associated, the fractional_scale_exists | |
| 70 | - | protocol error is raised. | |
| 71 | - | </description> | |
| 72 | - | <arg name="id" type="new_id" interface="wp_fractional_scale_v1" | |
| 73 | - | summary="the new surface scale info interface id"/> | |
| 74 | - | <arg name="surface" type="object" interface="wl_surface" | |
| 75 | - | summary="the surface"/> | |
| 76 | - | </request> | |
| 77 | - | </interface> | |
| 78 | - | ||
| 79 | - | <interface name="wp_fractional_scale_v1" version="1"> | |
| 80 | - | <description summary="fractional scale interface to a wl_surface"> | |
| 81 | - | An additional interface to a wl_surface object which allows the compositor | |
| 82 | - | to inform the client of the preferred scale. | |
| 83 | - | </description> | |
| 84 | - | ||
| 85 | - | <request name="destroy" type="destructor"> | |
| 86 | - | <description summary="remove surface scale information for surface"> | |
| 87 | - | Destroy the fractional scale object. When this object is destroyed, | |
| 88 | - | preferred_scale events will no longer be sent. | |
| 89 | - | </description> | |
| 90 | - | </request> | |
| 91 | - | ||
| 92 | - | <event name="preferred_scale"> | |
| 93 | - | <description summary="notify of new preferred scale"> | |
| 94 | - | Notification of a new preferred scale for this surface that the | |
| 95 | - | compositor suggests that the client should use. | |
| 96 | - | ||
| 97 | - | The sent scale is the numerator of a fraction with a denominator of 120. | |
| 98 | - | </description> | |
| 99 | - | <arg name="scale" type="uint" summary="the new preferred scale"/> | |
| 100 | - | </event> | |
| 101 | - | </interface> | |
| 102 | - | </protocol> | |
D protocol/fractionalscale/fractional-scale-v1_generated.go +0 -164
| @@ -1,164 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: fractional_scale_v1 | |
| 3 | - | // Source: fractional-scale-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2022 Kenny Levinsen | |
| 7 | - | // | |
| 8 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 9 | - | // copy of this software and associated documentation files (the "Software"), | |
| 10 | - | // to deal in the Software without restriction, including without limitation | |
| 11 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 12 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 13 | - | // Software is furnished to do so, subject to the following conditions: | |
| 14 | - | // | |
| 15 | - | // The above copyright notice and this permission notice (including the next | |
| 16 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | // Software. | |
| 18 | - | // | |
| 19 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 22 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 24 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 25 | - | // DEALINGS IN THE SOFTWARE. | |
| 26 | - | ||
| 27 | - | package fractionalscale | |
| 28 | - | ||
| 29 | - | import ( | |
| 30 | - | "sync" | |
| 31 | - | ||
| 32 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 33 | - | "github.com/bnema/wlturbo/wl" | |
| 34 | - | ) | |
| 35 | - | ||
| 36 | - | // ERROR_FRACTIONAL_SCALE_EXISTS is the error fractional_scale_exists value. | |
| 37 | - | const ERROR_FRACTIONAL_SCALE_EXISTS = 0 | |
| 38 | - | ||
| 39 | - | // WpFractionalScaleManagerInterface is the protocol interface name. | |
| 40 | - | const WpFractionalScaleManagerInterface = "wp_fractional_scale_manager_v1" | |
| 41 | - | ||
| 42 | - | // WpFractionalScaleManager is the generated binding for wp_fractional_scale_manager_v1 version 1. | |
| 43 | - | type WpFractionalScaleManager struct { | |
| 44 | - | wl.BaseProxy | |
| 45 | - | } | |
| 46 | - | ||
| 47 | - | // NewWpFractionalScaleManager returns an unbound WpFractionalScaleManager. | |
| 48 | - | func NewWpFractionalScaleManager(ctx *wl.Context) *WpFractionalScaleManager { | |
| 49 | - | obj := &WpFractionalScaleManager{} | |
| 50 | - | obj.SetContext(ctx) | |
| 51 | - | ctx.Register(obj) | |
| 52 | - | return obj | |
| 53 | - | } | |
| 54 | - | ||
| 55 | - | // Informs the server that the client will not be using this protocol object anymore. This does not affect any other objects, wp_fractional_scale_v1 objects included. | |
| 56 | - | func (o *WpFractionalScaleManager) Destroy() error { | |
| 57 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_fractional_scale_manager_v1.destroy", Destructor: true}); err != nil { | |
| 58 | - | return err | |
| 59 | - | } | |
| 60 | - | return nil | |
| 61 | - | } | |
| 62 | - | ||
| 63 | - | // Create an add-on object for the the wl_surface to let the compositor request fractional scales. If the given wl_surface already has a wp_fractional_scale_v1 object associated, the fractional_scale_exists protocol error is raised. | |
| 64 | - | func (o *WpFractionalScaleManager) GetFractionalScale(surface *cross_wl_surface.Surface) (*WpFractionalScale, error) { | |
| 65 | - | var arg1 wl.Object | |
| 66 | - | if surface != nil { | |
| 67 | - | arg1 = surface | |
| 68 | - | } | |
| 69 | - | child := &WpFractionalScale{} | |
| 70 | - | child.SetContext(o.Context()) | |
| 71 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "wp_fractional_scale_manager_v1.get_fractional_scale", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 72 | - | return nil, err | |
| 73 | - | } | |
| 74 | - | return child, nil | |
| 75 | - | } | |
| 76 | - | ||
| 77 | - | // EventSignature returns the declared event argument types in wire order. | |
| 78 | - | func (o *WpFractionalScaleManager) EventSignature(opcode uint16) (string, bool) { | |
| 79 | - | switch opcode { | |
| 80 | - | default: | |
| 81 | - | return "", false | |
| 82 | - | } | |
| 83 | - | } | |
| 84 | - | ||
| 85 | - | // Dispatch decodes one event on wp_fractional_scale_manager_v1 and calls the registered handlers. | |
| 86 | - | func (o *WpFractionalScaleManager) Dispatch(event *wl.Event) { | |
| 87 | - | switch event.Opcode { | |
| 88 | - | default: | |
| 89 | - | } | |
| 90 | - | } | |
| 91 | - | ||
| 92 | - | // WpFractionalScaleInterface is the protocol interface name. | |
| 93 | - | const WpFractionalScaleInterface = "wp_fractional_scale_v1" | |
| 94 | - | ||
| 95 | - | // WpFractionalScale is the generated binding for wp_fractional_scale_v1 version 1. | |
| 96 | - | type WpFractionalScale struct { | |
| 97 | - | wl.BaseProxy | |
| 98 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 99 | - | // handlers while another goroutine dispatches events. | |
| 100 | - | handlersMu sync.Mutex | |
| 101 | - | onPreferredScale []func(scale uint32) | |
| 102 | - | } | |
| 103 | - | ||
| 104 | - | // NewWpFractionalScale returns an unbound WpFractionalScale. | |
| 105 | - | func NewWpFractionalScale(ctx *wl.Context) *WpFractionalScale { | |
| 106 | - | obj := &WpFractionalScale{} | |
| 107 | - | obj.SetContext(ctx) | |
| 108 | - | ctx.Register(obj) | |
| 109 | - | return obj | |
| 110 | - | } | |
| 111 | - | ||
| 112 | - | // Destroy the fractional scale object. When this object is destroyed, preferred_scale events will no longer be sent. | |
| 113 | - | func (o *WpFractionalScale) Destroy() error { | |
| 114 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "wp_fractional_scale_v1.destroy", Destructor: true}); err != nil { | |
| 115 | - | return err | |
| 116 | - | } | |
| 117 | - | return nil | |
| 118 | - | } | |
| 119 | - | ||
| 120 | - | // OnPreferredScale registers a handler for the preferred_scale event. | |
| 121 | - | // | |
| 122 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 123 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 124 | - | func (o *WpFractionalScale) OnPreferredScale(handler func(scale uint32)) { | |
| 125 | - | if handler == nil { | |
| 126 | - | return | |
| 127 | - | } | |
| 128 | - | o.handlersMu.Lock() | |
| 129 | - | defer o.handlersMu.Unlock() | |
| 130 | - | o.onPreferredScale = append(o.onPreferredScale, handler) | |
| 131 | - | } | |
| 132 | - | ||
| 133 | - | // handlersForPreferredScale returns the handlers registered for preferred_scale, taken | |
| 134 | - | // under the lock so a handler may register another handler while events are | |
| 135 | - | // being dispatched. | |
| 136 | - | func (o *WpFractionalScale) handlersForPreferredScale() []func(scale uint32) { | |
| 137 | - | o.handlersMu.Lock() | |
| 138 | - | defer o.handlersMu.Unlock() | |
| 139 | - | return o.onPreferredScale | |
| 140 | - | } | |
| 141 | - | ||
| 142 | - | // EventSignature returns the declared event argument types in wire order. | |
| 143 | - | func (o *WpFractionalScale) EventSignature(opcode uint16) (string, bool) { | |
| 144 | - | switch opcode { | |
| 145 | - | case 0: | |
| 146 | - | return "uint,", true | |
| 147 | - | default: | |
| 148 | - | return "", false | |
| 149 | - | } | |
| 150 | - | } | |
| 151 | - | ||
| 152 | - | // Dispatch decodes one event on wp_fractional_scale_v1 and calls the registered handlers. | |
| 153 | - | func (o *WpFractionalScale) Dispatch(event *wl.Event) { | |
| 154 | - | switch event.Opcode { | |
| 155 | - | case 0: // preferred_scale | |
| 156 | - | scale := event.Uint32() | |
| 157 | - | ||
| 158 | - | for i, handler := range o.handlersForPreferredScale() { | |
| 159 | - | _ = i | |
| 160 | - | handler(scale) | |
| 161 | - | } | |
| 162 | - | default: | |
| 163 | - | } | |
| 164 | - | } | |
D protocol/generate.go +0 -11
| @@ -1,11 +0,0 @@ | |||
| 1 | - | package protocol | |
| 2 | - | ||
| 3 | - | //go:generate go run ../cmd/wlturbo-scanner -p core -o core/wayland_generated.go wayland.xml | |
| 4 | - | //go:generate go run ../cmd/wlturbo-scanner -p xdgshell -o xdgshell/xdg-shell_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_seat=github.com/bnema/wlturbo/protocol/core -import wl_output=github.com/bnema/wlturbo/protocol/core xdgshell/xdg-shell.xml | |
| 5 | - | //go:generate go run ../cmd/wlturbo-scanner -p linuxdmabuf -o linuxdmabuf/linux-dmabuf-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_buffer=github.com/bnema/wlturbo/protocol/core linuxdmabuf/linux-dmabuf-v1.xml | |
| 6 | - | //go:generate go run ../cmd/wlturbo-scanner -p drmsyncobj -o drmsyncobj/linux-drm-syncobj-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core drmsyncobj/linux-drm-syncobj-v1.xml | |
| 7 | - | //go:generate go run ../cmd/wlturbo-scanner -p viewporter -o viewporter/viewporter_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core viewporter/viewporter.xml | |
| 8 | - | //go:generate go run ../cmd/wlturbo-scanner -p fractionalscale -o fractionalscale/fractional-scale-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core fractionalscale/fractional-scale-v1.xml | |
| 9 | - | //go:generate go run ../cmd/wlturbo-scanner -p tablet -o tablet/tablet-v2_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_seat=github.com/bnema/wlturbo/protocol/core tablet/tablet-v2.xml | |
| 10 | - | //go:generate go run ../cmd/wlturbo-scanner -p cursorshape -o cursorshape/cursor-shape-v1_generated.go -import wl_pointer=github.com/bnema/wlturbo/protocol/core -import zwp_tablet_tool_v2=github.com/bnema/wlturbo/protocol/tablet cursorshape/cursor-shape-v1.xml | |
| 11 | - | //go:generate go run ../cmd/wlturbo-scanner -p textinput -o textinput/text-input-unstable-v3_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_seat=github.com/bnema/wlturbo/protocol/core textinput/text-input-unstable-v3.xml | |
D protocol/headless_extensions_test.go +0 -430
| @@ -1,430 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package protocol_test | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "fmt" | |
| 7 | - | "sort" | |
| 8 | - | "testing" | |
| 9 | - | ||
| 10 | - | "github.com/bnema/wlturbo" | |
| 11 | - | "github.com/bnema/wlturbo/protocol/alphamodifier" | |
| 12 | - | "github.com/bnema/wlturbo/protocol/colormanagement" | |
| 13 | - | "github.com/bnema/wlturbo/protocol/colorrepresentation" | |
| 14 | - | "github.com/bnema/wlturbo/protocol/committiming" | |
| 15 | - | "github.com/bnema/wlturbo/protocol/contenttype" | |
| 16 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 17 | - | "github.com/bnema/wlturbo/protocol/cursorshape" | |
| 18 | - | "github.com/bnema/wlturbo/protocol/datacontrol" | |
| 19 | - | "github.com/bnema/wlturbo/protocol/drmlease" | |
| 20 | - | "github.com/bnema/wlturbo/protocol/drmsyncobj" | |
| 21 | - | "github.com/bnema/wlturbo/protocol/extforeigntoplevel" | |
| 22 | - | "github.com/bnema/wlturbo/protocol/fifo" | |
| 23 | - | "github.com/bnema/wlturbo/protocol/foreigntoplevel" | |
| 24 | - | "github.com/bnema/wlturbo/protocol/fractionalscale" | |
| 25 | - | "github.com/bnema/wlturbo/protocol/idleinhibit" | |
| 26 | - | "github.com/bnema/wlturbo/protocol/idlenotify" | |
| 27 | - | "github.com/bnema/wlturbo/protocol/imagecapturesource" | |
| 28 | - | "github.com/bnema/wlturbo/protocol/imagecopycapture" | |
| 29 | - | "github.com/bnema/wlturbo/protocol/inputmethod" | |
| 30 | - | "github.com/bnema/wlturbo/protocol/kdeserverdecoration" | |
| 31 | - | "github.com/bnema/wlturbo/protocol/layershell" | |
| 32 | - | "github.com/bnema/wlturbo/protocol/linuxdmabuf" | |
| 33 | - | "github.com/bnema/wlturbo/protocol/outputmanagement" | |
| 34 | - | "github.com/bnema/wlturbo/protocol/outputpower" | |
| 35 | - | "github.com/bnema/wlturbo/protocol/pointerconstraints" | |
| 36 | - | "github.com/bnema/wlturbo/protocol/pointerwarp" | |
| 37 | - | "github.com/bnema/wlturbo/protocol/presentation" | |
| 38 | - | "github.com/bnema/wlturbo/protocol/primaryselection" | |
| 39 | - | "github.com/bnema/wlturbo/protocol/relativepointer" | |
| 40 | - | "github.com/bnema/wlturbo/protocol/screencopy" | |
| 41 | - | "github.com/bnema/wlturbo/protocol/shortcutsinhibit" | |
| 42 | - | "github.com/bnema/wlturbo/protocol/tablet" | |
| 43 | - | "github.com/bnema/wlturbo/protocol/tearingcontrol" | |
| 44 | - | "github.com/bnema/wlturbo/protocol/textinput" | |
| 45 | - | "github.com/bnema/wlturbo/protocol/viewporter" | |
| 46 | - | "github.com/bnema/wlturbo/protocol/virtualkeyboard" | |
| 47 | - | "github.com/bnema/wlturbo/protocol/workspace" | |
| 48 | - | "github.com/bnema/wlturbo/protocol/xdgactivation" | |
| 49 | - | "github.com/bnema/wlturbo/protocol/xdgdecoration" | |
| 50 | - | "github.com/bnema/wlturbo/protocol/xdgoutput" | |
| 51 | - | "github.com/bnema/wlturbo/protocol/xdgshell" | |
| 52 | - | "golang.org/x/sys/unix" | |
| 53 | - | ) | |
| 54 | - | ||
| 55 | - | // headlessBinding is one generated root object and the highest version its | |
| 56 | - | // package supports (the XML interface version). | |
| 57 | - | type headlessBinding struct { | |
| 58 | - | iface string | |
| 59 | - | supported uint32 | |
| 60 | - | make func(*wlturbo.Context) wlturbo.Proxy | |
| 61 | - | // optional marks globals that depend on GPU, DRM or input devices, or that | |
| 62 | - | // this NeferWL build does not advertise headless: absence is logged, not | |
| 63 | - | // a failure. Everything else must be announced. | |
| 64 | - | optional bool | |
| 65 | - | } | |
| 66 | - | ||
| 67 | - | func headlessBindings() []headlessBinding { | |
| 68 | - | return []headlessBinding{ | |
| 69 | - | {core.CompositorInterface, 7, func(c *wlturbo.Context) wlturbo.Proxy { return core.NewCompositor(c) }, false}, | |
| 70 | - | {core.SubcompositorInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return core.NewSubcompositor(c) }, false}, | |
| 71 | - | {core.ShmInterface, 3, func(c *wlturbo.Context) wlturbo.Proxy { return core.NewShm(c) }, false}, | |
| 72 | - | {core.SeatInterface, 11, func(c *wlturbo.Context) wlturbo.Proxy { return core.NewSeat(c) }, false}, | |
| 73 | - | {core.OutputInterface, 4, func(c *wlturbo.Context) wlturbo.Proxy { return core.NewOutput(c) }, false}, | |
| 74 | - | {core.DataDeviceManagerInterface, 4, func(c *wlturbo.Context) wlturbo.Proxy { return core.NewDataDeviceManager(c) }, false}, | |
| 75 | - | {xdgshell.XdgWmBaseInterface, 7, func(c *wlturbo.Context) wlturbo.Proxy { return xdgshell.NewXdgWmBase(c) }, false}, | |
| 76 | - | {linuxdmabuf.LinuxDmabufInterface, 6, func(c *wlturbo.Context) wlturbo.Proxy { return linuxdmabuf.NewLinuxDmabuf(c) }, true}, | |
| 77 | - | {drmsyncobj.WpLinuxDrmSyncobjManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return drmsyncobj.NewWpLinuxDrmSyncobjManager(c) }, true}, | |
| 78 | - | {viewporter.WpViewporterInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return viewporter.NewWpViewporter(c) }, false}, | |
| 79 | - | {fractionalscale.WpFractionalScaleManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return fractionalscale.NewWpFractionalScaleManager(c) }, false}, | |
| 80 | - | {cursorshape.WpCursorShapeManagerInterface, 2, func(c *wlturbo.Context) wlturbo.Proxy { return cursorshape.NewWpCursorShapeManager(c) }, false}, | |
| 81 | - | {tablet.TabletManagerInterface, 2, func(c *wlturbo.Context) wlturbo.Proxy { return tablet.NewTabletManager(c) }, true}, | |
| 82 | - | {textinput.TextInputManagerV3Interface, 2, func(c *wlturbo.Context) wlturbo.Proxy { return textinput.NewTextInputManagerV3(c) }, false}, | |
| 83 | - | {alphamodifier.WpAlphaModifierInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return alphamodifier.NewWpAlphaModifier(c) }, false}, | |
| 84 | - | {colormanagement.WpColorManagerInterface, 3, func(c *wlturbo.Context) wlturbo.Proxy { return colormanagement.NewWpColorManager(c) }, false}, | |
| 85 | - | {colorrepresentation.WpColorRepresentationManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return colorrepresentation.NewWpColorRepresentationManager(c) }, false}, | |
| 86 | - | {committiming.WpCommitTimingManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return committiming.NewWpCommitTimingManager(c) }, false}, | |
| 87 | - | {contenttype.WpContentTypeManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return contenttype.NewWpContentTypeManager(c) }, false}, | |
| 88 | - | {datacontrol.ExtDataControlManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return datacontrol.NewExtDataControlManager(c) }, false}, | |
| 89 | - | {drmlease.WpDrmLeaseDeviceInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return drmlease.NewWpDrmLeaseDevice(c) }, true}, | |
| 90 | - | {extforeigntoplevel.ExtForeignToplevelListInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return extforeigntoplevel.NewExtForeignToplevelList(c) }, true}, | |
| 91 | - | {fifo.WpFifoManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return fifo.NewWpFifoManager(c) }, false}, | |
| 92 | - | {foreigntoplevel.ForeignToplevelManagerInterface, 3, func(c *wlturbo.Context) wlturbo.Proxy { return foreigntoplevel.NewForeignToplevelManager(c) }, false}, | |
| 93 | - | {idleinhibit.IdleInhibitManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return idleinhibit.NewIdleInhibitManager(c) }, false}, | |
| 94 | - | {idlenotify.ExtIdleNotifierInterface, 2, func(c *wlturbo.Context) wlturbo.Proxy { return idlenotify.NewExtIdleNotifier(c) }, false}, | |
| 95 | - | {imagecapturesource.ExtOutputImageCaptureSourceManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { | |
| 96 | - | return imagecapturesource.NewExtOutputImageCaptureSourceManager(c) | |
| 97 | - | }, false}, | |
| 98 | - | {imagecapturesource.ExtForeignToplevelImageCaptureSourceManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { | |
| 99 | - | return imagecapturesource.NewExtForeignToplevelImageCaptureSourceManager(c) | |
| 100 | - | }, true}, | |
| 101 | - | {imagecopycapture.ExtImageCopyCaptureManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return imagecopycapture.NewExtImageCopyCaptureManager(c) }, false}, | |
| 102 | - | {inputmethod.InputMethodManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return inputmethod.NewInputMethodManager(c) }, false}, | |
| 103 | - | {kdeserverdecoration.OrgKdeKwinServerDecorationManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { | |
| 104 | - | return kdeserverdecoration.NewOrgKdeKwinServerDecorationManager(c) | |
| 105 | - | }, false}, | |
| 106 | - | {layershell.LayerShellInterface, 5, func(c *wlturbo.Context) wlturbo.Proxy { return layershell.NewLayerShell(c) }, false}, | |
| 107 | - | {outputmanagement.OutputManagerInterface, 4, func(c *wlturbo.Context) wlturbo.Proxy { return outputmanagement.NewOutputManager(c) }, false}, | |
| 108 | - | {outputpower.OutputPowerManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return outputpower.NewOutputPowerManager(c) }, false}, | |
| 109 | - | {pointerconstraints.PointerConstraintsInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return pointerconstraints.NewPointerConstraints(c) }, false}, | |
| 110 | - | {pointerwarp.WpPointerWarpInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return pointerwarp.NewWpPointerWarp(c) }, false}, | |
| 111 | - | {presentation.WpPresentationInterface, 2, func(c *wlturbo.Context) wlturbo.Proxy { return presentation.NewWpPresentation(c) }, false}, | |
| 112 | - | {primaryselection.PrimarySelectionDeviceManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return primaryselection.NewPrimarySelectionDeviceManager(c) }, false}, | |
| 113 | - | {relativepointer.RelativePointerManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return relativepointer.NewRelativePointerManager(c) }, false}, | |
| 114 | - | {screencopy.ScreencopyManagerInterface, 3, func(c *wlturbo.Context) wlturbo.Proxy { return screencopy.NewScreencopyManager(c) }, false}, | |
| 115 | - | {shortcutsinhibit.KeyboardShortcutsInhibitManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return shortcutsinhibit.NewKeyboardShortcutsInhibitManager(c) }, false}, | |
| 116 | - | {tearingcontrol.WpTearingControlManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return tearingcontrol.NewWpTearingControlManager(c) }, false}, | |
| 117 | - | {virtualkeyboard.VirtualKeyboardManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return virtualkeyboard.NewVirtualKeyboardManager(c) }, false}, | |
| 118 | - | {workspace.ExtWorkspaceManagerInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return workspace.NewExtWorkspaceManager(c) }, false}, | |
| 119 | - | {xdgactivation.XdgActivationInterface, 1, func(c *wlturbo.Context) wlturbo.Proxy { return xdgactivation.NewXdgActivation(c) }, false}, | |
| 120 | - | {xdgdecoration.ZxdgDecorationManagerInterface, 2, func(c *wlturbo.Context) wlturbo.Proxy { return xdgdecoration.NewZxdgDecorationManager(c) }, false}, | |
| 121 | - | {xdgoutput.ZxdgOutputManagerInterface, 3, func(c *wlturbo.Context) wlturbo.Proxy { return xdgoutput.NewZxdgOutputManager(c) }, false}, | |
| 122 | - | } | |
| 123 | - | } | |
| 124 | - | ||
| 125 | - | // waitGlobal blocks in Dispatch until iface is announced. wl_output is added | |
| 126 | - | // by the compositor after startup, so it can follow the first roundtrip. The | |
| 127 | - | // instance context ends a wait that never completes. | |
| 128 | - | func (h *headlessInstance) waitGlobal(t *testing.T, d *wlturbo.Display, iface string) { | |
| 129 | - | t.Helper() | |
| 130 | - | for { | |
| 131 | - | if _, ok := d.Registry().FindGlobal(iface); ok { | |
| 132 | - | return | |
| 133 | - | } | |
| 134 | - | if e := d.Dispatch(); e != nil { | |
| 135 | - | t.Fatalf("waiting for %s: %v (ctx %v)\n%s", iface, e, h.ctx.Err(), h.Log()) | |
| 136 | - | } | |
| 137 | - | } | |
| 138 | - | } | |
| 139 | - | ||
| 140 | - | // bindOne binds a global at its negotiated version and fails on any error. | |
| 141 | - | func (h *headlessInstance) bindOne(t *testing.T, d *wlturbo.Display, iface string, supported uint32, p wlturbo.Proxy) uint32 { | |
| 142 | - | t.Helper() | |
| 143 | - | v, e := d.Registry().BindNegotiated(iface, supported, p) | |
| 144 | - | if e != nil { | |
| 145 | - | t.Fatalf("bind %s: %v\n%s", iface, e, h.Log()) | |
| 146 | - | } | |
| 147 | - | return v | |
| 148 | - | } | |
| 149 | - | ||
| 150 | - | func TestHeadlessExtensions(t *testing.T) { | |
| 151 | - | h := startHeadless(t) | |
| 152 | - | ||
| 153 | - | t.Run("bind announced globals", func(t *testing.T) { | |
| 154 | - | d := h.connect(t) | |
| 155 | - | h.waitGlobal(t, d, core.OutputInterface) | |
| 156 | - | for _, b := range headlessBindings() { | |
| 157 | - | g, ok := d.Registry().FindGlobal(b.iface) | |
| 158 | - | if !ok { | |
| 159 | - | if b.optional { | |
| 160 | - | t.Logf("%s absent (optional: hardware, device or build dependent)", b.iface) | |
| 161 | - | } else { | |
| 162 | - | t.Errorf("%s not announced", b.iface) | |
| 163 | - | } | |
| 164 | - | continue | |
| 165 | - | } | |
| 166 | - | p := b.make(d.Context()) | |
| 167 | - | v, e := d.Registry().BindNegotiated(b.iface, b.supported, p) | |
| 168 | - | if e != nil { | |
| 169 | - | t.Errorf("bind %s: %v", b.iface, e) | |
| 170 | - | continue | |
| 171 | - | } | |
| 172 | - | want := min(g.Version, b.supported) | |
| 173 | - | if v != want || v == 0 { | |
| 174 | - | t.Errorf("%s negotiated %d, announced %d supported %d", b.iface, v, g.Version, b.supported) | |
| 175 | - | } | |
| 176 | - | if pv, ok := p.(interface{ Version() uint32 }); ok && pv.Version() != v { | |
| 177 | - | t.Errorf("%s proxy version %d, negotiated %d", b.iface, pv.Version(), v) | |
| 178 | - | } | |
| 179 | - | t.Logf("%s announced=%d supported=%d negotiated=%d", b.iface, g.Version, b.supported, v) | |
| 180 | - | } | |
| 181 | - | // Every bind request is validated by the compositor before this returns. | |
| 182 | - | h.sync(t, d, "bind all") | |
| 183 | - | // Report announced globals that no generated package covers. | |
| 184 | - | known := map[string]bool{"wl_fixes": true} | |
| 185 | - | for _, b := range headlessBindings() { | |
| 186 | - | known[b.iface] = true | |
| 187 | - | } | |
| 188 | - | var extra []string | |
| 189 | - | for _, g := range d.Registry().GetGlobals() { | |
| 190 | - | if !known[g.Interface] { | |
| 191 | - | extra = append(extra, g.Interface) | |
| 192 | - | } | |
| 193 | - | } | |
| 194 | - | sort.Strings(extra) | |
| 195 | - | t.Logf("announced without a client binding: %v", extra) | |
| 196 | - | }) | |
| 197 | - | ||
| 198 | - | t.Run("output description", func(t *testing.T) { | |
| 199 | - | d := h.connect(t) | |
| 200 | - | h.waitGlobal(t, d, core.OutputInterface) | |
| 201 | - | out := core.NewOutput(d.Context()) | |
| 202 | - | h.bindOne(t, d, core.OutputInterface, 4, out) | |
| 203 | - | xm := xdgoutput.NewZxdgOutputManager(d.Context()) | |
| 204 | - | h.bindOne(t, d, xdgoutput.ZxdgOutputManagerInterface, 3, xm) | |
| 205 | - | xo, e := xm.GetXdgOutput(out) | |
| 206 | - | noerr(t, e) | |
| 207 | - | var lw, lh int32 | |
| 208 | - | var name string | |
| 209 | - | var wlDone, xdgDone bool | |
| 210 | - | var modes int | |
| 211 | - | out.OnMode(func(flags uint32, w, h, refresh int32) { modes++ }) | |
| 212 | - | out.OnDone(func() { wlDone = true }) | |
| 213 | - | xo.OnLogicalSize(func(w, h int32) { lw, lh = w, h }) | |
| 214 | - | xo.OnName(func(n string) { name = n }) | |
| 215 | - | xo.OnDone(func() { xdgDone = true }) | |
| 216 | - | // Registered after the bind request but before any event is read. | |
| 217 | - | h.sync(t, d, "xdg_output") | |
| 218 | - | if lw != 640 || lh != 480 || name == "" || modes == 0 || !(wlDone || xdgDone) { | |
| 219 | - | t.Fatalf("logical=%dx%d name=%q modes=%d wl_done=%t xdg_done=%t\n%s", lw, lh, name, modes, wlDone, xdgDone, h.Log()) | |
| 220 | - | } | |
| 221 | - | t.Logf("output %q logical %dx%d", name, lw, lh) | |
| 222 | - | ||
| 223 | - | // wlr-output-management lists the same output as a head with modes. | |
| 224 | - | om := outputmanagement.NewOutputManager(d.Context()) | |
| 225 | - | h.bindOne(t, d, outputmanagement.OutputManagerInterface, 4, om) | |
| 226 | - | // Head events arrive in any order, so each head keeps its own record. | |
| 227 | - | type head struct { | |
| 228 | - | name string | |
| 229 | - | modes int | |
| 230 | - | } | |
| 231 | - | var heads []*head | |
| 232 | - | done := false | |
| 233 | - | om.OnHead(func(hd *outputmanagement.OutputHead) { | |
| 234 | - | rec := &head{} | |
| 235 | - | heads = append(heads, rec) | |
| 236 | - | hd.OnName(func(s string) { rec.name = s }) | |
| 237 | - | hd.OnMode(func(*outputmanagement.OutputMode) { rec.modes++ }) | |
| 238 | - | }) | |
| 239 | - | om.OnDone(func(serial uint32) { done = true }) | |
| 240 | - | h.sync(t, d, "output manager") | |
| 241 | - | found := false | |
| 242 | - | for _, rec := range heads { | |
| 243 | - | found = found || (rec.name == name && rec.modes > 0) | |
| 244 | - | } | |
| 245 | - | if !done || !found { | |
| 246 | - | t.Fatalf("done=%t want head %q with modes; heads:%s\n%s", done, name, func() (s string) { | |
| 247 | - | for _, rec := range heads { | |
| 248 | - | s += fmt.Sprintf(" %q/%d", rec.name, rec.modes) | |
| 249 | - | } | |
| 250 | - | return | |
| 251 | - | }(), h.Log()) | |
| 252 | - | } | |
| 253 | - | noerr(t, xo.Destroy()) | |
| 254 | - | noerr(t, om.Stop()) | |
| 255 | - | h.sync(t, d, "output teardown") | |
| 256 | - | }) | |
| 257 | - | ||
| 258 | - | t.Run("decoration negotiation", func(t *testing.T) { | |
| 259 | - | d := h.connect(t) | |
| 260 | - | compositor := core.NewCompositor(d.Context()) | |
| 261 | - | h.bindOne(t, d, core.CompositorInterface, 6, compositor) | |
| 262 | - | wm := xdgshell.NewXdgWmBase(d.Context()) | |
| 263 | - | h.bindOne(t, d, xdgshell.XdgWmBaseInterface, 6, wm) | |
| 264 | - | dm := xdgdecoration.NewZxdgDecorationManager(d.Context()) | |
| 265 | - | h.bindOne(t, d, xdgdecoration.ZxdgDecorationManagerInterface, 2, dm) | |
| 266 | - | kde := kdeserverdecoration.NewOrgKdeKwinServerDecorationManager(d.Context()) | |
| 267 | - | var kdeDefault uint32 = 99 | |
| 268 | - | kde.OnDefaultMode(func(m uint32) { kdeDefault = m }) | |
| 269 | - | h.bindOne(t, d, kdeserverdecoration.OrgKdeKwinServerDecorationManagerInterface, 1, kde) | |
| 270 | - | ||
| 271 | - | surface, e := compositor.CreateSurface() | |
| 272 | - | noerr(t, e) | |
| 273 | - | xs, e := wm.GetXdgSurface(surface) | |
| 274 | - | noerr(t, e) | |
| 275 | - | top, e := xs.GetToplevel() | |
| 276 | - | noerr(t, e) | |
| 277 | - | deco, e := dm.GetToplevelDecoration(top) | |
| 278 | - | noerr(t, e) | |
| 279 | - | var modes []uint32 | |
| 280 | - | deco.OnConfigure(func(m uint32) { modes = append(modes, m) }) | |
| 281 | - | // A client asking for client-side is answered with the compositor's server-side mode. | |
| 282 | - | noerr(t, deco.SetMode(xdgdecoration.MODE_CLIENT_SIDE)) | |
| 283 | - | xs.OnConfigure(func(serial uint32) { noerr(t, xs.AckConfigure(serial)) }) | |
| 284 | - | // The initial empty commit lets the compositor send xdg_surface.configure. | |
| 285 | - | noerr(t, surface.Commit()) | |
| 286 | - | h.sync(t, d, "decoration") | |
| 287 | - | if len(modes) == 0 || modes[len(modes)-1] != xdgdecoration.MODE_SERVER_SIDE { | |
| 288 | - | t.Fatalf("xdg decoration modes %v\n%s", modes, h.Log()) | |
| 289 | - | } | |
| 290 | - | kdeDeco, e := kde.Create(surface) | |
| 291 | - | noerr(t, e) | |
| 292 | - | var kdeMode uint32 = 99 | |
| 293 | - | kdeDeco.OnMode(func(m uint32) { kdeMode = m }) | |
| 294 | - | h.sync(t, d, "kde decoration") | |
| 295 | - | if kdeDefault != kdeserverdecoration.ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER || kdeMode != kdeserverdecoration.ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER { | |
| 296 | - | t.Fatalf("kde default=%d mode=%d", kdeDefault, kdeMode) | |
| 297 | - | } | |
| 298 | - | noerr(t, kdeDeco.Release()) | |
| 299 | - | noerr(t, deco.Destroy()) | |
| 300 | - | noerr(t, top.Destroy()) | |
| 301 | - | noerr(t, xs.Destroy()) | |
| 302 | - | noerr(t, surface.Destroy()) | |
| 303 | - | h.sync(t, d, "decoration teardown") | |
| 304 | - | }) | |
| 305 | - | ||
| 306 | - | t.Run("workspaces", func(t *testing.T) { | |
| 307 | - | d := h.connect(t) | |
| 308 | - | wsm := workspace.NewExtWorkspaceManager(d.Context()) | |
| 309 | - | groups, workspaces, done, finished := 0, 0, false, false | |
| 310 | - | names := map[string]bool{} | |
| 311 | - | wsm.OnWorkspaceGroup(func(*workspace.ExtWorkspaceGroupHandle) { groups++ }) | |
| 312 | - | wsm.OnWorkspace(func(w *workspace.ExtWorkspaceHandle) { | |
| 313 | - | workspaces++ | |
| 314 | - | w.OnName(func(n string) { names[n] = true }) | |
| 315 | - | }) | |
| 316 | - | wsm.OnDone(func() { done = true }) | |
| 317 | - | wsm.OnFinished(func() { finished = true }) | |
| 318 | - | h.bindOne(t, d, workspace.ExtWorkspaceManagerInterface, 1, wsm) | |
| 319 | - | h.sync(t, d, "workspace snapshot") | |
| 320 | - | if !done || groups == 0 || workspaces == 0 || len(names) == 0 { | |
| 321 | - | t.Fatalf("done=%t groups=%d workspaces=%d names=%v\n%s", done, groups, workspaces, names, h.Log()) | |
| 322 | - | } | |
| 323 | - | t.Logf("workspaces: groups=%d workspaces=%d names=%v", groups, workspaces, names) | |
| 324 | - | // stop is answered by finished; wait for it with the blocking dispatch. | |
| 325 | - | noerr(t, wsm.Stop()) | |
| 326 | - | for !finished { | |
| 327 | - | if e := d.Dispatch(); e != nil { | |
| 328 | - | t.Fatalf("waiting for finished: %v\n%s", e, h.Log()) | |
| 329 | - | } | |
| 330 | - | } | |
| 331 | - | }) | |
| 332 | - | ||
| 333 | - | t.Run("color capabilities", func(t *testing.T) { | |
| 334 | - | d := h.connect(t) | |
| 335 | - | cm := colormanagement.NewWpColorManager(d.Context()) | |
| 336 | - | intents, features, tfs, prims := map[uint32]bool{}, map[uint32]bool{}, map[uint32]bool{}, map[uint32]bool{} | |
| 337 | - | cmDone := false | |
| 338 | - | cm.OnSupportedIntent(func(v uint32) { intents[v] = true }) | |
| 339 | - | cm.OnSupportedFeature(func(v uint32) { features[v] = true }) | |
| 340 | - | cm.OnSupportedTfNamed(func(v uint32) { tfs[v] = true }) | |
| 341 | - | cm.OnSupportedPrimariesNamed(func(v uint32) { prims[v] = true }) | |
| 342 | - | cm.OnDone(func() { cmDone = true }) | |
| 343 | - | version := h.bindOne(t, d, colormanagement.WpColorManagerInterface, 3, cm) | |
| 344 | - | ||
| 345 | - | cr := colorrepresentation.NewWpColorRepresentationManager(d.Context()) | |
| 346 | - | alpha, crDone := map[uint32]bool{}, false | |
| 347 | - | cr.OnSupportedAlphaMode(func(v uint32) { alpha[v] = true }) | |
| 348 | - | cr.OnDone(func() { crDone = true }) | |
| 349 | - | h.bindOne(t, d, colorrepresentation.WpColorRepresentationManagerInterface, 1, cr) | |
| 350 | - | h.sync(t, d, "color capabilities") | |
| 351 | - | ||
| 352 | - | if !cmDone || !intents[colormanagement.RENDER_INTENT_PERCEPTUAL] || !features[colormanagement.FEATURE_PARAMETRIC] || | |
| 353 | - | !tfs[colormanagement.TRANSFER_FUNCTION_SRGB] || !prims[colormanagement.PRIMARIES_SRGB] { | |
| 354 | - | t.Fatalf("color manager v%d done=%t intents=%v features=%v tf=%v primaries=%v\n%s", version, cmDone, intents, features, tfs, prims, h.Log()) | |
| 355 | - | } | |
| 356 | - | if !crDone || len(alpha) == 0 { | |
| 357 | - | t.Fatalf("color representation done=%t alpha=%v", crDone, alpha) | |
| 358 | - | } | |
| 359 | - | t.Logf("color v%d intents=%v features=%v tf=%v primaries=%v alpha=%v", version, intents, features, tfs, prims, alpha) | |
| 360 | - | }) | |
| 361 | - | ||
| 362 | - | t.Run("presentation clock", func(t *testing.T) { | |
| 363 | - | d := h.connect(t) | |
| 364 | - | p := presentation.NewWpPresentation(d.Context()) | |
| 365 | - | clock, got := uint32(0), false | |
| 366 | - | p.OnClockId(func(id uint32) { clock, got = id, true }) | |
| 367 | - | h.bindOne(t, d, presentation.WpPresentationInterface, 2, p) | |
| 368 | - | h.sync(t, d, "presentation clock") | |
| 369 | - | // An empty commit produces no frame, so only the clock is asserted. | |
| 370 | - | if !got || clock != unix.CLOCK_MONOTONIC { | |
| 371 | - | t.Fatalf("clock_id got=%t %d, want CLOCK_MONOTONIC", got, clock) | |
| 372 | - | } | |
| 373 | - | noerr(t, p.Destroy()) | |
| 374 | - | h.sync(t, d, "presentation teardown") | |
| 375 | - | }) | |
| 376 | - | ||
| 377 | - | t.Run("layer surface configure", func(t *testing.T) { | |
| 378 | - | d := h.connect(t) | |
| 379 | - | h.waitGlobal(t, d, core.OutputInterface) | |
| 380 | - | compositor := core.NewCompositor(d.Context()) | |
| 381 | - | h.bindOne(t, d, core.CompositorInterface, 6, compositor) | |
| 382 | - | shell := layershell.NewLayerShell(d.Context()) | |
| 383 | - | h.bindOne(t, d, layershell.LayerShellInterface, 5, shell) | |
| 384 | - | surface, e := compositor.CreateSurface() | |
| 385 | - | noerr(t, e) | |
| 386 | - | ls, e := shell.GetLayerSurface(surface, nil, layershell.LAYER_TOP, "wlturbo-test") | |
| 387 | - | noerr(t, e) | |
| 388 | - | noerr(t, ls.SetAnchor(layershell.ANCHOR_TOP|layershell.ANCHOR_LEFT|layershell.ANCHOR_RIGHT)) | |
| 389 | - | noerr(t, ls.SetSize(0, 30)) | |
| 390 | - | var serial, w, hgt uint32 | |
| 391 | - | configured := false | |
| 392 | - | ls.OnConfigure(func(s, cw, ch uint32) { serial, w, hgt, configured = s, cw, ch, true }) | |
| 393 | - | // The initial empty commit asks the compositor for the first configure. | |
| 394 | - | noerr(t, surface.Commit()) | |
| 395 | - | h.sync(t, d, "layer configure") | |
| 396 | - | if !configured || w != 640 || hgt != 30 { | |
| 397 | - | t.Fatalf("configured=%t %dx%d\n%s", configured, w, hgt, h.Log()) | |
| 398 | - | } | |
| 399 | - | noerr(t, ls.AckConfigure(serial)) | |
| 400 | - | noerr(t, ls.Destroy()) | |
| 401 | - | noerr(t, surface.Destroy()) | |
| 402 | - | h.sync(t, d, "layer teardown") | |
| 403 | - | }) | |
| 404 | - | ||
| 405 | - | t.Run("relative pointer object", func(t *testing.T) { | |
| 406 | - | d := h.connect(t) | |
| 407 | - | seat := core.NewSeat(d.Context()) | |
| 408 | - | var caps uint32 | |
| 409 | - | seat.OnCapabilities(func(c uint32) { caps = c }) | |
| 410 | - | h.bindOne(t, d, core.SeatInterface, 8, seat) | |
| 411 | - | rm := relativepointer.NewRelativePointerManager(d.Context()) | |
| 412 | - | h.bindOne(t, d, relativepointer.RelativePointerManagerInterface, 1, rm) | |
| 413 | - | h.sync(t, d, "seat capabilities") | |
| 414 | - | if caps&core.CAPABILITY_POINTER == 0 { | |
| 415 | - | t.Skipf("seat has no pointer (caps %d); headless input capability dependent", caps) | |
| 416 | - | } | |
| 417 | - | ptr, e := seat.GetPointer() | |
| 418 | - | noerr(t, e) | |
| 419 | - | rp, e := rm.GetRelativePointer(ptr) | |
| 420 | - | noerr(t, e) | |
| 421 | - | // Motion needs pointer focus on a mapped surface, which an empty | |
| 422 | - | // commit cannot provide; creation and teardown must still be valid. | |
| 423 | - | rp.OnRelativeMotion(func(uint32, uint32, wlturbo.Fixed, wlturbo.Fixed, wlturbo.Fixed, wlturbo.Fixed) {}) | |
| 424 | - | h.sync(t, d, "relative pointer") | |
| 425 | - | noerr(t, rp.Destroy()) | |
| 426 | - | noerr(t, ptr.Release()) | |
| 427 | - | noerr(t, rm.Destroy()) | |
| 428 | - | h.sync(t, d, "relative pointer teardown") | |
| 429 | - | }) | |
| 430 | - | } | |
D protocol/headless_test.go +0 -319
| @@ -1,319 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package protocol_test | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "context" | |
| 7 | - | "errors" | |
| 8 | - | "fmt" | |
| 9 | - | "net" | |
| 10 | - | "os" | |
| 11 | - | "os/exec" | |
| 12 | - | "path/filepath" | |
| 13 | - | "strings" | |
| 14 | - | "syscall" | |
| 15 | - | "testing" | |
| 16 | - | "time" | |
| 17 | - | ||
| 18 | - | "github.com/bnema/wlturbo" | |
| 19 | - | "github.com/bnema/wlturbo/protocol/core" | |
| 20 | - | "github.com/bnema/wlturbo/protocol/drmsyncobj" | |
| 21 | - | "github.com/bnema/wlturbo/protocol/fractionalscale" | |
| 22 | - | "github.com/bnema/wlturbo/protocol/linuxdmabuf" | |
| 23 | - | "github.com/bnema/wlturbo/protocol/viewporter" | |
| 24 | - | "github.com/bnema/wlturbo/protocol/xdgshell" | |
| 25 | - | "golang.org/x/sys/unix" | |
| 26 | - | ) | |
| 27 | - | ||
| 28 | - | func TestHeadlessNeferWL(t *testing.T) { | |
| 29 | - | h := startHeadless(t) | |
| 30 | - | d := h.connect(t) | |
| 31 | - | bind := h.binder(t, d) | |
| 32 | - | ctx := h.ctx | |
| 33 | - | compositor := core.NewCompositor(d.Context()) | |
| 34 | - | bind(core.CompositorInterface, 6, compositor) | |
| 35 | - | wm := xdgshell.NewXdgWmBase(d.Context()) | |
| 36 | - | bind(xdgshell.XdgWmBaseInterface, 7, wm) | |
| 37 | - | dm := linuxdmabuf.NewLinuxDmabuf(d.Context()) | |
| 38 | - | if bind(linuxdmabuf.LinuxDmabufInterface, 4, dm) < 4 { | |
| 39 | - | t.Fatal("dmabuf feedback requires v4") | |
| 40 | - | } | |
| 41 | - | syncManager := drmsyncobj.NewWpLinuxDrmSyncobjManager(d.Context()) | |
| 42 | - | bind(drmsyncobj.WpLinuxDrmSyncobjManagerInterface, 1, syncManager) | |
| 43 | - | dataManager := core.NewDataDeviceManager(d.Context()) | |
| 44 | - | dataVersion := bind(core.DataDeviceManagerInterface, 4, dataManager) | |
| 45 | - | vp := viewporter.NewWpViewporter(d.Context()) | |
| 46 | - | bind(viewporter.WpViewporterInterface, 1, vp) | |
| 47 | - | if g, ok := d.Registry().FindGlobal(fractionalscale.WpFractionalScaleManagerInterface); ok { | |
| 48 | - | fs := fractionalscale.NewWpFractionalScaleManager(d.Context()) | |
| 49 | - | v := bind(g.Interface, 1, fs) | |
| 50 | - | if v != 1 { | |
| 51 | - | t.Fatalf("fractional scale version %d", v) | |
| 52 | - | } | |
| 53 | - | noerr(t, fs.Destroy()) | |
| 54 | - | } else { | |
| 55 | - | t.Log("fractional scale absent") | |
| 56 | - | } | |
| 57 | - | surface, e := compositor.CreateSurface() | |
| 58 | - | noerr(t, e) | |
| 59 | - | xs, e := wm.GetXdgSurface(surface) | |
| 60 | - | noerr(t, e) | |
| 61 | - | top, e := xs.GetToplevel() | |
| 62 | - | noerr(t, e) | |
| 63 | - | feedback, e := dm.GetSurfaceFeedback(surface) | |
| 64 | - | noerr(t, e) | |
| 65 | - | ss, e := syncManager.GetSurface(surface) | |
| 66 | - | noerr(t, e) | |
| 67 | - | configured, done, mainDevice, tableOK := false, false, false, false | |
| 68 | - | top.OnConfigure(func(w, h int32, states []byte) { t.Logf("xdg_toplevel.configure %dx%d", w, h) }) | |
| 69 | - | xs.OnConfigure(func(serial uint32) { | |
| 70 | - | noerr(t, xs.AckConfigure(serial)) | |
| 71 | - | configured = true | |
| 72 | - | t.Logf("xdg_surface.configure ack=%d", serial) | |
| 73 | - | }) | |
| 74 | - | feedback.OnMainDevice(func(b []byte) { mainDevice = len(b) == 8; t.Logf("main_device=%x", b) }) | |
| 75 | - | feedback.OnFormatTable(func(fd *wlturbo.OwnedFD, size uint32) { | |
| 76 | - | entries, e := linuxdmabuf.ReadFormatTable(fd, size) | |
| 77 | - | if e != nil { | |
| 78 | - | t.Errorf("format table: %v", e) | |
| 79 | - | } else { | |
| 80 | - | tableOK = len(entries) > 0 | |
| 81 | - | t.Logf("format-table entries=%d", len(entries)) | |
| 82 | - | } | |
| 83 | - | }) | |
| 84 | - | feedback.OnDone(func() { done = true }) | |
| 85 | - | // Initial empty commit requests xdg configure; no buffer or window is shown. | |
| 86 | - | noerr(t, surface.Commit()) | |
| 87 | - | for (!configured || !done) && ctx.Err() == nil { | |
| 88 | - | if e := d.Dispatch(); e != nil { | |
| 89 | - | t.Fatalf("dispatch: %v\n%s", e, h.Log()) | |
| 90 | - | } | |
| 91 | - | } | |
| 92 | - | if !configured || !done || !mainDevice || !tableOK { | |
| 93 | - | t.Fatalf("configure=%t feedback=%t main_device=%t table=%t: %v\n%s", configured, done, mainDevice, tableOK, ctx.Err(), h.Log()) | |
| 94 | - | } | |
| 95 | - | noerr(t, surface.Commit()) | |
| 96 | - | // Drop all child objects while their parents are still alive. | |
| 97 | - | noerr(t, ss.Destroy()) | |
| 98 | - | noerr(t, feedback.Destroy()) | |
| 99 | - | noerr(t, top.Destroy()) | |
| 100 | - | noerr(t, xs.Destroy()) | |
| 101 | - | noerr(t, surface.Destroy()) | |
| 102 | - | noerr(t, vp.Destroy()) | |
| 103 | - | if dataVersion >= 4 { | |
| 104 | - | noerr(t, dataManager.Release()) | |
| 105 | - | } | |
| 106 | - | noerr(t, syncManager.Destroy()) | |
| 107 | - | noerr(t, dm.Destroy()) | |
| 108 | - | noerr(t, wm.Destroy()) | |
| 109 | - | noerr(t, d.Close()) | |
| 110 | - | } | |
| 111 | - | ||
| 112 | - | // headlessInstance is one isolated NeferWL process with its own runtime, | |
| 113 | - | // config, data and state directories. Cleanup kills the whole process group | |
| 114 | - | // and reaps it. ctx expires at the test deadline or when the process exits, so | |
| 115 | - | // a blocking Dispatch on a connection made by connect always returns. | |
| 116 | - | type headlessInstance struct { | |
| 117 | - | ctx context.Context | |
| 118 | - | socket string | |
| 119 | - | logf *os.File | |
| 120 | - | done chan struct{} // closed after the process is reaped | |
| 121 | - | waitErr error // valid once done is closed | |
| 122 | - | } | |
| 123 | - | ||
| 124 | - | // startHeadless launches WLTURBO_HEADLESS or skips the test when it is unset. | |
| 125 | - | // It returns once the compositor socket exists, or fails with the process log | |
| 126 | - | // if the process exits early or the 18s test deadline expires. | |
| 127 | - | func startHeadless(t *testing.T) *headlessInstance { | |
| 128 | - | t.Helper() | |
| 129 | - | binary := os.Getenv("WLTURBO_HEADLESS") | |
| 130 | - | if binary == "" { | |
| 131 | - | t.Skip("set WLTURBO_HEADLESS to a NeferWL binary") | |
| 132 | - | } | |
| 133 | - | binary, e := filepath.Abs(binary) | |
| 134 | - | noerr(t, e) | |
| 135 | - | root := t.TempDir() | |
| 136 | - | dirs := map[string]string{} | |
| 137 | - | for _, name := range []string{"run", "config", "data", "state"} { | |
| 138 | - | dirs[name] = filepath.Join(root, name) | |
| 139 | - | noerr(t, os.Mkdir(dirs[name], 0700)) | |
| 140 | - | } | |
| 141 | - | ctx, cancel := context.WithTimeout(context.Background(), 18*time.Second) | |
| 142 | - | t.Cleanup(cancel) | |
| 143 | - | logf, e := os.Create(filepath.Join(root, "neferwl.log")) | |
| 144 | - | noerr(t, e) | |
| 145 | - | t.Cleanup(func() { _ = logf.Close() }) | |
| 146 | - | h := &headlessInstance{logf: logf, done: make(chan struct{})} | |
| 147 | - | // Watch the runtime directory before starting so the socket creation cannot be missed. | |
| 148 | - | // Non-blocking makes os.File use the poller, so Close unblocks the reader goroutine. | |
| 149 | - | ifd, e := unix.InotifyInit1(unix.IN_NONBLOCK | unix.IN_CLOEXEC) | |
| 150 | - | noerr(t, e) | |
| 151 | - | watch := os.NewFile(uintptr(ifd), "inotify") | |
| 152 | - | t.Cleanup(func() { _ = watch.Close() }) | |
| 153 | - | _, e = unix.InotifyAddWatch(ifd, dirs["run"], unix.IN_CREATE|unix.IN_ATTRIB) | |
| 154 | - | noerr(t, e) | |
| 155 | - | cmd := exec.Command(binary, "--backend=headless", "--no-terminal", "--no-xwayland", "--size", "640x480", "--timeout", "20s") | |
| 156 | - | cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} | |
| 157 | - | cmd.Env = append(cleanDisplayEnv(os.Environ()), | |
| 158 | - | "XDG_RUNTIME_DIR="+dirs["run"], "XDG_CONFIG_HOME="+dirs["config"], | |
| 159 | - | "XDG_DATA_HOME="+dirs["data"], "XDG_STATE_HOME="+dirs["state"]) | |
| 160 | - | cmd.Stdout = logf | |
| 161 | - | cmd.Stderr = logf | |
| 162 | - | noerr(t, cmd.Start()) | |
| 163 | - | // A failed startup must still terminate the process group and reap it. | |
| 164 | - | t.Cleanup(func() { | |
| 165 | - | _ = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) | |
| 166 | - | <-h.done | |
| 167 | - | }) | |
| 168 | - | // Process exit cancels ctx, which also unblocks any Dispatch (see connect). | |
| 169 | - | ctx, stopCtx := context.WithCancel(ctx) | |
| 170 | - | t.Cleanup(stopCtx) | |
| 171 | - | h.ctx = ctx | |
| 172 | - | go func() { | |
| 173 | - | h.waitErr = cmd.Wait() | |
| 174 | - | close(h.done) | |
| 175 | - | stopCtx() | |
| 176 | - | }() | |
| 177 | - | events := make(chan struct{}, 1) | |
| 178 | - | go func() { | |
| 179 | - | buf := make([]byte, 4096) | |
| 180 | - | for { | |
| 181 | - | if _, e := watch.Read(buf); e != nil { | |
| 182 | - | return | |
| 183 | - | } | |
| 184 | - | select { | |
| 185 | - | case events <- struct{}{}: | |
| 186 | - | default: | |
| 187 | - | } | |
| 188 | - | } | |
| 189 | - | }() | |
| 190 | - | find := func() string { | |
| 191 | - | paths, _ := filepath.Glob(filepath.Join(dirs["run"], "wayland-*")) | |
| 192 | - | for _, path := range paths { | |
| 193 | - | if info, e := os.Stat(path); e == nil && info.Mode()&os.ModeSocket != 0 { | |
| 194 | - | return path | |
| 195 | - | } | |
| 196 | - | } | |
| 197 | - | return "" | |
| 198 | - | } | |
| 199 | - | for h.socket = find(); h.socket == ""; h.socket = find() { | |
| 200 | - | select { | |
| 201 | - | case <-events: | |
| 202 | - | case <-h.done: | |
| 203 | - | t.Fatalf("neferwl exited before serving: %v\n%s", h.waitErr, h.Log()) | |
| 204 | - | case <-ctx.Done(): | |
| 205 | - | t.Fatalf("headless socket timeout: %v\n%s", ctx.Err(), h.Log()) | |
| 206 | - | } | |
| 207 | - | } | |
| 208 | - | return h | |
| 209 | - | } | |
| 210 | - | ||
| 211 | - | // Log returns the tail of the compositor output. | |
| 212 | - | func (h *headlessInstance) Log() string { return headlessLog(h.logf) } | |
| 213 | - | ||
| 214 | - | // connect dials the compositor and completes the initial registry roundtrip. | |
| 215 | - | // The instance context closes the connection when the test deadline expires or | |
| 216 | - | // the compositor exits, so a blocking Dispatch returns instead of hanging. | |
| 217 | - | func (h *headlessInstance) connect(t *testing.T) *wlturbo.Display { | |
| 218 | - | t.Helper() | |
| 219 | - | var conn net.Conn | |
| 220 | - | for { | |
| 221 | - | var e error | |
| 222 | - | conn, e = (&net.Dialer{Timeout: time.Second}).DialContext(h.ctx, "unix", h.socket) | |
| 223 | - | if e == nil { | |
| 224 | - | break | |
| 225 | - | } | |
| 226 | - | // The socket file appears at bind(); listen() follows immediately, so | |
| 227 | - | // a refused dial is transient unless the compositor is gone. | |
| 228 | - | if !errors.Is(e, syscall.ECONNREFUSED) { | |
| 229 | - | t.Fatalf("dial: %v\n%s", e, h.Log()) | |
| 230 | - | } | |
| 231 | - | select { | |
| 232 | - | case <-h.done: | |
| 233 | - | t.Fatalf("neferwl exited before accepting: %v\n%s", h.waitErr, h.Log()) | |
| 234 | - | case <-h.ctx.Done(): | |
| 235 | - | t.Fatalf("dial timeout: %v\n%s", h.ctx.Err(), h.Log()) | |
| 236 | - | case <-time.After(5 * time.Millisecond): | |
| 237 | - | } | |
| 238 | - | } | |
| 239 | - | d, e := wlturbo.ConnectFromConn(conn) | |
| 240 | - | if e != nil { | |
| 241 | - | _ = conn.Close() | |
| 242 | - | t.Fatal(e) | |
| 243 | - | } | |
| 244 | - | t.Cleanup(func() { _ = d.Close() }) | |
| 245 | - | stop := context.AfterFunc(h.ctx, func() { _ = d.Close() }) | |
| 246 | - | t.Cleanup(func() { stop() }) | |
| 247 | - | h.sync(t, d, "registry roundtrip") | |
| 248 | - | return d | |
| 249 | - | } | |
| 250 | - | ||
| 251 | - | // binder returns a bind function that fails the test with the compositor log. | |
| 252 | - | func (h *headlessInstance) binder(t *testing.T, d *wlturbo.Display) func(string, uint32, wlturbo.Proxy) uint32 { | |
| 253 | - | return func(iface string, supported uint32, proxy wlturbo.Proxy) uint32 { | |
| 254 | - | t.Helper() | |
| 255 | - | v, err := d.Registry().BindNegotiated(iface, supported, proxy) | |
| 256 | - | if err != nil { | |
| 257 | - | t.Fatalf("bind %s: %v\n%s", iface, err, h.Log()) | |
| 258 | - | } | |
| 259 | - | t.Logf("%s negotiated=%d", iface, v) | |
| 260 | - | return v | |
| 261 | - | } | |
| 262 | - | } | |
| 263 | - | ||
| 264 | - | // sync completes a roundtrip, reporting compositor protocol errors with its log. | |
| 265 | - | func (h *headlessInstance) sync(t *testing.T, d *wlturbo.Display, what string) { | |
| 266 | - | t.Helper() | |
| 267 | - | if e := d.Roundtrip(); e != nil { | |
| 268 | - | t.Fatalf("%s: %v (ctx %v)\n%s", what, e, h.ctx.Err(), h.Log()) | |
| 269 | - | } | |
| 270 | - | } | |
| 271 | - | ||
| 272 | - | // headlessEnvDrop lists the environment prefixes the child must not inherit: | |
| 273 | - | // anything that could attach it to, or make it act on, the caller's session, | |
| 274 | - | // plus NeferWL's own configuration. The test client's own environment is not | |
| 275 | - | // changed; only the child process is isolated. | |
| 276 | - | var headlessEnvDrop = []string{"DISPLAY=", "WAYLAND_DISPLAY=", "WAYLAND_SOCKET=", "NOTIFY_SOCKET=", "DBUS_SESSION_BUS_ADDRESS=", | |
| 277 | - | "XDG_RUNTIME_DIR=", "XDG_CONFIG_HOME=", "XDG_DATA_HOME=", "XDG_STATE_HOME=", "XDG_SESSION_", "XDG_VTNR=", "XDG_SEAT=", | |
| 278 | - | "XDG_CURRENT_DESKTOP=", "NIRI_SOCKET=", "SWAYSOCK=", "HYPRLAND_INSTANCE_SIGNATURE=", "NEFERWL_"} | |
| 279 | - | ||
| 280 | - | func cleanDisplayEnv(in []string) []string { | |
| 281 | - | out := make([]string, 0, len(in)) | |
| 282 | - | next: | |
| 283 | - | for _, e := range in { | |
| 284 | - | for _, p := range headlessEnvDrop { | |
| 285 | - | if strings.HasPrefix(e, p) { | |
| 286 | - | continue next | |
| 287 | - | } | |
| 288 | - | } | |
| 289 | - | out = append(out, e) | |
| 290 | - | } | |
| 291 | - | return out | |
| 292 | - | } | |
| 293 | - | ||
| 294 | - | func TestCleanDisplayEnv(t *testing.T) { | |
| 295 | - | keep := []string{"PATH=/bin", "HOME=/h", "DISPLAYS=x", "XDG_DATA_DIRS=/d", "MY_NEFERWL_X=1"} | |
| 296 | - | in := append([]string(nil), keep...) | |
| 297 | - | for _, p := range headlessEnvDrop { | |
| 298 | - | e := p + "placeholder" | |
| 299 | - | if !strings.HasSuffix(p, "=") { | |
| 300 | - | e += "=1" // a prefix such as XDG_SESSION_ names a family of variables | |
| 301 | - | } | |
| 302 | - | in = append(in, e) | |
| 303 | - | } | |
| 304 | - | got := cleanDisplayEnv(in) | |
| 305 | - | if strings.Join(got, "\n") != strings.Join(keep, "\n") { | |
| 306 | - | t.Fatalf("cleanDisplayEnv = %q, want %q", got, keep) | |
| 307 | - | } | |
| 308 | - | } | |
| 309 | - | ||
| 310 | - | func headlessLog(f *os.File) string { | |
| 311 | - | b, e := os.ReadFile(f.Name()) | |
| 312 | - | if e != nil { | |
| 313 | - | return fmt.Sprint(e) | |
| 314 | - | } | |
| 315 | - | if len(b) > 8192 { | |
| 316 | - | b = b[len(b)-8192:] | |
| 317 | - | } | |
| 318 | - | return string(b) | |
| 319 | - | } | |
D protocol/idleinhibit/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package idleinhibit | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p idleinhibit -o idle-inhibit-unstable-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core idle-inhibit-unstable-v1.xml | |
D protocol/idleinhibit/idle-inhibit-unstable-v1.xml +0 -83
| @@ -1,83 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="idle_inhibit_unstable_v1"> | |
| 3 | - | ||
| 4 | - | <copyright> | |
| 5 | - | Copyright © 2015 Samsung Electronics Co., Ltd | |
| 6 | - | ||
| 7 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 8 | - | copy of this software and associated documentation files (the "Software"), | |
| 9 | - | to deal in the Software without restriction, including without limitation | |
| 10 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 11 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 12 | - | Software is furnished to do so, subject to the following conditions: | |
| 13 | - | ||
| 14 | - | The above copyright notice and this permission notice (including the next | |
| 15 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 16 | - | Software. | |
| 17 | - | ||
| 18 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 23 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 24 | - | DEALINGS IN THE SOFTWARE. | |
| 25 | - | </copyright> | |
| 26 | - | ||
| 27 | - | <interface name="zwp_idle_inhibit_manager_v1" version="1"> | |
| 28 | - | <description summary="control behavior when display idles"> | |
| 29 | - | This interface permits inhibiting the idle behavior such as screen | |
| 30 | - | blanking, locking, and screensaving. The client binds the idle manager | |
| 31 | - | globally, then creates idle-inhibitor objects for each surface. | |
| 32 | - | ||
| 33 | - | Warning! The protocol described in this file is experimental and | |
| 34 | - | backward incompatible changes may be made. Backward compatible changes | |
| 35 | - | may be added together with the corresponding interface version bump. | |
| 36 | - | Backward incompatible changes are done by bumping the version number in | |
| 37 | - | the protocol and interface names and resetting the interface version. | |
| 38 | - | Once the protocol is to be declared stable, the 'z' prefix and the | |
| 39 | - | version number in the protocol and interface names are removed and the | |
| 40 | - | interface version number is reset. | |
| 41 | - | </description> | |
| 42 | - | ||
| 43 | - | <request name="destroy" type="destructor"> | |
| 44 | - | <description summary="destroy the idle inhibitor object"> | |
| 45 | - | Destroy the inhibit manager. | |
| 46 | - | </description> | |
| 47 | - | </request> | |
| 48 | - | ||
| 49 | - | <request name="create_inhibitor"> | |
| 50 | - | <description summary="create a new inhibitor object"> | |
| 51 | - | Create a new inhibitor object associated with the given surface. | |
| 52 | - | </description> | |
| 53 | - | <arg name="id" type="new_id" interface="zwp_idle_inhibitor_v1"/> | |
| 54 | - | <arg name="surface" type="object" interface="wl_surface" | |
| 55 | - | summary="the surface that inhibits the idle behavior"/> | |
| 56 | - | </request> | |
| 57 | - | ||
| 58 | - | </interface> | |
| 59 | - | ||
| 60 | - | <interface name="zwp_idle_inhibitor_v1" version="1"> | |
| 61 | - | <description summary="context object for inhibiting idle behavior"> | |
| 62 | - | An idle inhibitor prevents the output that the associated surface is | |
| 63 | - | visible on from being set to a state where it is not visually usable due | |
| 64 | - | to lack of user interaction (e.g. blanked, dimmed, locked, set to power | |
| 65 | - | save, etc.) Any screensaver processes are also blocked from displaying. | |
| 66 | - | ||
| 67 | - | If the surface is destroyed, unmapped, becomes occluded, loses | |
| 68 | - | visibility, or otherwise becomes not visually relevant for the user, the | |
| 69 | - | idle inhibitor will not be honored by the compositor; if the surface | |
| 70 | - | subsequently regains visibility the inhibitor takes effect once again. | |
| 71 | - | Likewise, the inhibitor isn't honored if the system was already idled at | |
| 72 | - | the time the inhibitor was established, although if the system later | |
| 73 | - | de-idles and re-idles the inhibitor will take effect. | |
| 74 | - | </description> | |
| 75 | - | ||
| 76 | - | <request name="destroy" type="destructor"> | |
| 77 | - | <description summary="destroy the idle inhibitor object"> | |
| 78 | - | Remove the inhibitor effect from the associated wl_surface. | |
| 79 | - | </description> | |
| 80 | - | </request> | |
| 81 | - | ||
| 82 | - | </interface> | |
| 83 | - | </protocol> | |
D protocol/idleinhibit/idle-inhibit-unstable-v1_generated.go +0 -124
| @@ -1,124 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: idle_inhibit_unstable_v1 | |
| 3 | - | // Source: idle-inhibit-unstable-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2015 Samsung Electronics Co., Ltd | |
| 7 | - | // | |
| 8 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 9 | - | // copy of this software and associated documentation files (the "Software"), | |
| 10 | - | // to deal in the Software without restriction, including without limitation | |
| 11 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 12 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 13 | - | // Software is furnished to do so, subject to the following conditions: | |
| 14 | - | // | |
| 15 | - | // The above copyright notice and this permission notice (including the next | |
| 16 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | // Software. | |
| 18 | - | // | |
| 19 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 22 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 24 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 25 | - | // DEALINGS IN THE SOFTWARE. | |
| 26 | - | ||
| 27 | - | package idleinhibit | |
| 28 | - | ||
| 29 | - | import ( | |
| 30 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 31 | - | "github.com/bnema/wlturbo/wl" | |
| 32 | - | ) | |
| 33 | - | ||
| 34 | - | // IdleInhibitManagerInterface is the protocol interface name. | |
| 35 | - | const IdleInhibitManagerInterface = "zwp_idle_inhibit_manager_v1" | |
| 36 | - | ||
| 37 | - | // IdleInhibitManager is the generated binding for zwp_idle_inhibit_manager_v1 version 1. | |
| 38 | - | type IdleInhibitManager struct { | |
| 39 | - | wl.BaseProxy | |
| 40 | - | } | |
| 41 | - | ||
| 42 | - | // NewIdleInhibitManager returns an unbound IdleInhibitManager. | |
| 43 | - | func NewIdleInhibitManager(ctx *wl.Context) *IdleInhibitManager { | |
| 44 | - | obj := &IdleInhibitManager{} | |
| 45 | - | obj.SetContext(ctx) | |
| 46 | - | ctx.Register(obj) | |
| 47 | - | return obj | |
| 48 | - | } | |
| 49 | - | ||
| 50 | - | // Destroy the inhibit manager. | |
| 51 | - | func (o *IdleInhibitManager) Destroy() error { | |
| 52 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwp_idle_inhibit_manager_v1.destroy", Destructor: true}); err != nil { | |
| 53 | - | return err | |
| 54 | - | } | |
| 55 | - | return nil | |
| 56 | - | } | |
| 57 | - | ||
| 58 | - | // Create a new inhibitor object associated with the given surface. | |
| 59 | - | func (o *IdleInhibitManager) CreateInhibitor(surface *cross_wl_surface.Surface) (*IdleInhibitor, error) { | |
| 60 | - | var arg1 wl.Object | |
| 61 | - | if surface != nil { | |
| 62 | - | arg1 = surface | |
| 63 | - | } | |
| 64 | - | child := &IdleInhibitor{} | |
| 65 | - | child.SetContext(o.Context()) | |
| 66 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "zwp_idle_inhibit_manager_v1.create_inhibitor", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 67 | - | return nil, err | |
| 68 | - | } | |
| 69 | - | return child, nil | |
| 70 | - | } | |
| 71 | - | ||
| 72 | - | // EventSignature returns the declared event argument types in wire order. | |
| 73 | - | func (o *IdleInhibitManager) EventSignature(opcode uint16) (string, bool) { | |
| 74 | - | switch opcode { | |
| 75 | - | default: | |
| 76 | - | return "", false | |
| 77 | - | } | |
| 78 | - | } | |
| 79 | - | ||
| 80 | - | // Dispatch decodes one event on zwp_idle_inhibit_manager_v1 and calls the registered handlers. | |
| 81 | - | func (o *IdleInhibitManager) Dispatch(event *wl.Event) { | |
| 82 | - | switch event.Opcode { | |
| 83 | - | default: | |
| 84 | - | } | |
| 85 | - | } | |
| 86 | - | ||
| 87 | - | // IdleInhibitorInterface is the protocol interface name. | |
| 88 | - | const IdleInhibitorInterface = "zwp_idle_inhibitor_v1" | |
| 89 | - | ||
| 90 | - | // IdleInhibitor is the generated binding for zwp_idle_inhibitor_v1 version 1. | |
| 91 | - | type IdleInhibitor struct { | |
| 92 | - | wl.BaseProxy | |
| 93 | - | } | |
| 94 | - | ||
| 95 | - | // NewIdleInhibitor returns an unbound IdleInhibitor. | |
| 96 | - | func NewIdleInhibitor(ctx *wl.Context) *IdleInhibitor { | |
| 97 | - | obj := &IdleInhibitor{} | |
| 98 | - | obj.SetContext(ctx) | |
| 99 | - | ctx.Register(obj) | |
| 100 | - | return obj | |
| 101 | - | } | |
| 102 | - | ||
| 103 | - | // Remove the inhibitor effect from the associated wl_surface. | |
| 104 | - | func (o *IdleInhibitor) Destroy() error { | |
| 105 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwp_idle_inhibitor_v1.destroy", Destructor: true}); err != nil { | |
| 106 | - | return err | |
| 107 | - | } | |
| 108 | - | return nil | |
| 109 | - | } | |
| 110 | - | ||
| 111 | - | // EventSignature returns the declared event argument types in wire order. | |
| 112 | - | func (o *IdleInhibitor) EventSignature(opcode uint16) (string, bool) { | |
| 113 | - | switch opcode { | |
| 114 | - | default: | |
| 115 | - | return "", false | |
| 116 | - | } | |
| 117 | - | } | |
| 118 | - | ||
| 119 | - | // Dispatch decodes one event on zwp_idle_inhibitor_v1 and calls the registered handlers. | |
| 120 | - | func (o *IdleInhibitor) Dispatch(event *wl.Event) { | |
| 121 | - | switch event.Opcode { | |
| 122 | - | default: | |
| 123 | - | } | |
| 124 | - | } | |
D protocol/idlenotify/ext-idle-notify-v1.xml +0 -131
| @@ -1,131 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="ext_idle_notify_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2015 Martin Gräßlin | |
| 5 | - | Copyright © 2022 Simon Ser | |
| 6 | - | ||
| 7 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 8 | - | copy of this software and associated documentation files (the "Software"), | |
| 9 | - | to deal in the Software without restriction, including without limitation | |
| 10 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 11 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 12 | - | Software is furnished to do so, subject to the following conditions: | |
| 13 | - | ||
| 14 | - | The above copyright notice and this permission notice (including the next | |
| 15 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 16 | - | Software. | |
| 17 | - | ||
| 18 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 23 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 24 | - | DEALINGS IN THE SOFTWARE. | |
| 25 | - | </copyright> | |
| 26 | - | ||
| 27 | - | <interface name="ext_idle_notifier_v1" version="2"> | |
| 28 | - | <description summary="idle notification manager"> | |
| 29 | - | This interface allows clients to monitor user idle status. | |
| 30 | - | ||
| 31 | - | After binding to this global, clients can create ext_idle_notification_v1 | |
| 32 | - | objects to get notified when the user is idle for a given amount of time. | |
| 33 | - | </description> | |
| 34 | - | ||
| 35 | - | <request name="destroy" type="destructor"> | |
| 36 | - | <description summary="destroy the manager"> | |
| 37 | - | Destroy the manager object. All objects created via this interface | |
| 38 | - | remain valid. | |
| 39 | - | </description> | |
| 40 | - | </request> | |
| 41 | - | ||
| 42 | - | <request name="get_idle_notification"> | |
| 43 | - | <description summary="create a notification object"> | |
| 44 | - | Create a new idle notification object. | |
| 45 | - | ||
| 46 | - | The notification object has a minimum timeout duration and is tied to a | |
| 47 | - | seat. The client will be notified if the seat is inactive for at least | |
| 48 | - | the provided timeout. See ext_idle_notification_v1 for more details. | |
| 49 | - | ||
| 50 | - | A zero timeout is valid and means the client wants to be notified as | |
| 51 | - | soon as possible when the seat is inactive. | |
| 52 | - | </description> | |
| 53 | - | <arg name="id" type="new_id" interface="ext_idle_notification_v1"/> | |
| 54 | - | <arg name="timeout" type="uint" summary="minimum idle timeout in msec"/> | |
| 55 | - | <arg name="seat" type="object" interface="wl_seat"/> | |
| 56 | - | </request> | |
| 57 | - | ||
| 58 | - | <!-- Version 2 additions --> | |
| 59 | - | ||
| 60 | - | <request name="get_input_idle_notification" since="2"> | |
| 61 | - | <description summary="create a notification object"> | |
| 62 | - | Create a new idle notification object to track input from the | |
| 63 | - | user, such as keyboard and mouse movement. Because this object is | |
| 64 | - | meant to track user input alone, it ignores idle inhibitors. | |
| 65 | - | ||
| 66 | - | The notification object has a minimum timeout duration and is tied to a | |
| 67 | - | seat. The client will be notified if the seat is inactive for at least | |
| 68 | - | the provided timeout. See ext_idle_notification_v1 for more details. | |
| 69 | - | ||
| 70 | - | A zero timeout is valid and means the client wants to be notified as | |
| 71 | - | soon as possible when the seat is inactive. | |
| 72 | - | </description> | |
| 73 | - | <arg name="id" type="new_id" interface="ext_idle_notification_v1"/> | |
| 74 | - | <arg name="timeout" type="uint" summary="minimum idle timeout in msec"/> | |
| 75 | - | <arg name="seat" type="object" interface="wl_seat"/> | |
| 76 | - | </request> | |
| 77 | - | ||
| 78 | - | </interface> | |
| 79 | - | ||
| 80 | - | <interface name="ext_idle_notification_v1" version="2"> | |
| 81 | - | <description summary="idle notification"> | |
| 82 | - | This interface is used by the compositor to send idle notification events | |
| 83 | - | to clients. | |
| 84 | - | ||
| 85 | - | Initially the notification object is not idle. The notification object | |
| 86 | - | becomes idle when no user activity has happened for at least the timeout | |
| 87 | - | duration, starting from the creation of the notification object. User | |
| 88 | - | activity may include input events or a presence sensor, but is | |
| 89 | - | compositor-specific. | |
| 90 | - | ||
| 91 | - | How this notification responds to idle inhibitors depends on how | |
| 92 | - | it was constructed. If constructed from the | |
| 93 | - | get_idle_notification request, then if an idle inhibitor is | |
| 94 | - | active (e.g. another client has created a zwp_idle_inhibitor_v1 | |
| 95 | - | on a visible surface), the compositor must not make the | |
| 96 | - | notification object idle. However, if constructed from the | |
| 97 | - | get_input_idle_notification request, then idle inhibitors are | |
| 98 | - | ignored, and only input from the user, e.g. from a keyboard or | |
| 99 | - | mouse, counts as activity. | |
| 100 | - | ||
| 101 | - | When the notification object becomes idle, an idled event is sent. When | |
| 102 | - | user activity starts again, the notification object stops being idle, | |
| 103 | - | a resumed event is sent and the timeout is restarted. | |
| 104 | - | </description> | |
| 105 | - | ||
| 106 | - | <request name="destroy" type="destructor"> | |
| 107 | - | <description summary="destroy the notification object"> | |
| 108 | - | Destroy the notification object. | |
| 109 | - | </description> | |
| 110 | - | </request> | |
| 111 | - | ||
| 112 | - | <event name="idled"> | |
| 113 | - | <description summary="notification object is idle"> | |
| 114 | - | This event is sent when the notification object becomes idle. | |
| 115 | - | ||
| 116 | - | It's a compositor protocol error to send this event twice without a | |
| 117 | - | resumed event in-between. | |
| 118 | - | </description> | |
| 119 | - | </event> | |
| 120 | - | ||
| 121 | - | <event name="resumed"> | |
| 122 | - | <description summary="notification object is no longer idle"> | |
| 123 | - | This event is sent when the notification object stops being idle. | |
| 124 | - | ||
| 125 | - | It's a compositor protocol error to send this event twice without an | |
| 126 | - | idled event in-between. It's a compositor protocol error to send this | |
| 127 | - | event prior to any idled event. | |
| 128 | - | </description> | |
| 129 | - | </event> | |
| 130 | - | </interface> | |
| 131 | - | </protocol> | |
D protocol/idlenotify/ext-idle-notify-v1_generated.go +0 -206
| @@ -1,206 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: ext_idle_notify_v1 | |
| 3 | - | // Source: ext-idle-notify-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2015 Martin Gräßlin | |
| 7 | - | // Copyright © 2022 Simon Ser | |
| 8 | - | // | |
| 9 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 | - | // copy of this software and associated documentation files (the "Software"), | |
| 11 | - | // to deal in the Software without restriction, including without limitation | |
| 12 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 14 | - | // Software is furnished to do so, subject to the following conditions: | |
| 15 | - | // | |
| 16 | - | // The above copyright notice and this permission notice (including the next | |
| 17 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 18 | - | // Software. | |
| 19 | - | // | |
| 20 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 23 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 25 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 26 | - | // DEALINGS IN THE SOFTWARE. | |
| 27 | - | ||
| 28 | - | package idlenotify | |
| 29 | - | ||
| 30 | - | import ( | |
| 31 | - | "sync" | |
| 32 | - | ||
| 33 | - | cross_wl_seat "github.com/bnema/wlturbo/protocol/core" | |
| 34 | - | "github.com/bnema/wlturbo/wl" | |
| 35 | - | ) | |
| 36 | - | ||
| 37 | - | // ExtIdleNotifierInterface is the protocol interface name. | |
| 38 | - | const ExtIdleNotifierInterface = "ext_idle_notifier_v1" | |
| 39 | - | ||
| 40 | - | // ExtIdleNotifier is the generated binding for ext_idle_notifier_v1 version 2. | |
| 41 | - | type ExtIdleNotifier struct { | |
| 42 | - | wl.BaseProxy | |
| 43 | - | } | |
| 44 | - | ||
| 45 | - | // NewExtIdleNotifier returns an unbound ExtIdleNotifier. | |
| 46 | - | func NewExtIdleNotifier(ctx *wl.Context) *ExtIdleNotifier { | |
| 47 | - | obj := &ExtIdleNotifier{} | |
| 48 | - | obj.SetContext(ctx) | |
| 49 | - | ctx.Register(obj) | |
| 50 | - | return obj | |
| 51 | - | } | |
| 52 | - | ||
| 53 | - | // Destroy the manager object. All objects created via this interface remain valid. | |
| 54 | - | func (o *ExtIdleNotifier) Destroy() error { | |
| 55 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_idle_notifier_v1.destroy", Destructor: true}); err != nil { | |
| 56 | - | return err | |
| 57 | - | } | |
| 58 | - | return nil | |
| 59 | - | } | |
| 60 | - | ||
| 61 | - | // Create a new idle notification object. The notification object has a minimum timeout duration and is tied to a seat. The client will be notified if the seat is inactive for at least the provided timeout. See ext_idle_notification_v1 for more details. A zero timeout is valid and means the client wants to be notified as soon as possible when the seat is inactive. | |
| 62 | - | func (o *ExtIdleNotifier) GetIdleNotification(timeout uint32, seat *cross_wl_seat.Seat) (*ExtIdleNotification, error) { | |
| 63 | - | var arg2 wl.Object | |
| 64 | - | if seat != nil { | |
| 65 | - | arg2 = seat | |
| 66 | - | } | |
| 67 | - | child := &ExtIdleNotification{} | |
| 68 | - | child.SetContext(o.Context()) | |
| 69 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_idle_notifier_v1.get_idle_notification", Child: child}, wl.ArgObject(child), wl.ArgUint(timeout), wl.ArgObject(arg2)); err != nil { | |
| 70 | - | return nil, err | |
| 71 | - | } | |
| 72 | - | return child, nil | |
| 73 | - | } | |
| 74 | - | ||
| 75 | - | // Create a new idle notification object to track input from the user, such as keyboard and mouse movement. Because this object is meant to track user input alone, it ignores idle inhibitors. The notification object has a minimum timeout duration and is tied to a seat. The client will be notified if the seat is inactive for at least the provided timeout. See ext_idle_notification_v1 for more details. A zero timeout is valid and means the client wants to be notified as soon as possible when the seat is inactive. | |
| 76 | - | func (o *ExtIdleNotifier) GetInputIdleNotification(timeout uint32, seat *cross_wl_seat.Seat) (*ExtIdleNotification, error) { | |
| 77 | - | var arg2 wl.Object | |
| 78 | - | if seat != nil { | |
| 79 | - | arg2 = seat | |
| 80 | - | } | |
| 81 | - | child := &ExtIdleNotification{} | |
| 82 | - | child.SetContext(o.Context()) | |
| 83 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "ext_idle_notifier_v1.get_input_idle_notification", Since: 2, Child: child}, wl.ArgObject(child), wl.ArgUint(timeout), wl.ArgObject(arg2)); err != nil { | |
| 84 | - | return nil, err | |
| 85 | - | } | |
| 86 | - | return child, nil | |
| 87 | - | } | |
| 88 | - | ||
| 89 | - | // EventSignature returns the declared event argument types in wire order. | |
| 90 | - | func (o *ExtIdleNotifier) EventSignature(opcode uint16) (string, bool) { | |
| 91 | - | switch opcode { | |
| 92 | - | default: | |
| 93 | - | return "", false | |
| 94 | - | } | |
| 95 | - | } | |
| 96 | - | ||
| 97 | - | // Dispatch decodes one event on ext_idle_notifier_v1 and calls the registered handlers. | |
| 98 | - | func (o *ExtIdleNotifier) Dispatch(event *wl.Event) { | |
| 99 | - | switch event.Opcode { | |
| 100 | - | default: | |
| 101 | - | } | |
| 102 | - | } | |
| 103 | - | ||
| 104 | - | // ExtIdleNotificationInterface is the protocol interface name. | |
| 105 | - | const ExtIdleNotificationInterface = "ext_idle_notification_v1" | |
| 106 | - | ||
| 107 | - | // ExtIdleNotification is the generated binding for ext_idle_notification_v1 version 2. | |
| 108 | - | type ExtIdleNotification struct { | |
| 109 | - | wl.BaseProxy | |
| 110 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 111 | - | // handlers while another goroutine dispatches events. | |
| 112 | - | handlersMu sync.Mutex | |
| 113 | - | onIdled []func() | |
| 114 | - | onResumed []func() | |
| 115 | - | } | |
| 116 | - | ||
| 117 | - | // NewExtIdleNotification returns an unbound ExtIdleNotification. | |
| 118 | - | func NewExtIdleNotification(ctx *wl.Context) *ExtIdleNotification { | |
| 119 | - | obj := &ExtIdleNotification{} | |
| 120 | - | obj.SetContext(ctx) | |
| 121 | - | ctx.Register(obj) | |
| 122 | - | return obj | |
| 123 | - | } | |
| 124 | - | ||
| 125 | - | // Destroy the notification object. | |
| 126 | - | func (o *ExtIdleNotification) Destroy() error { | |
| 127 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_idle_notification_v1.destroy", Destructor: true}); err != nil { | |
| 128 | - | return err | |
| 129 | - | } | |
| 130 | - | return nil | |
| 131 | - | } | |
| 132 | - | ||
| 133 | - | // OnIdled registers a handler for the idled event. | |
| 134 | - | // | |
| 135 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 136 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 137 | - | func (o *ExtIdleNotification) OnIdled(handler func()) { | |
| 138 | - | if handler == nil { | |
| 139 | - | return | |
| 140 | - | } | |
| 141 | - | o.handlersMu.Lock() | |
| 142 | - | defer o.handlersMu.Unlock() | |
| 143 | - | o.onIdled = append(o.onIdled, handler) | |
| 144 | - | } | |
| 145 | - | ||
| 146 | - | // handlersForIdled returns the handlers registered for idled, taken | |
| 147 | - | // under the lock so a handler may register another handler while events are | |
| 148 | - | // being dispatched. | |
| 149 | - | func (o *ExtIdleNotification) handlersForIdled() []func() { | |
| 150 | - | o.handlersMu.Lock() | |
| 151 | - | defer o.handlersMu.Unlock() | |
| 152 | - | return o.onIdled | |
| 153 | - | } | |
| 154 | - | ||
| 155 | - | // OnResumed registers a handler for the resumed event. | |
| 156 | - | // | |
| 157 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 158 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 159 | - | func (o *ExtIdleNotification) OnResumed(handler func()) { | |
| 160 | - | if handler == nil { | |
| 161 | - | return | |
| 162 | - | } | |
| 163 | - | o.handlersMu.Lock() | |
| 164 | - | defer o.handlersMu.Unlock() | |
| 165 | - | o.onResumed = append(o.onResumed, handler) | |
| 166 | - | } | |
| 167 | - | ||
| 168 | - | // handlersForResumed returns the handlers registered for resumed, taken | |
| 169 | - | // under the lock so a handler may register another handler while events are | |
| 170 | - | // being dispatched. | |
| 171 | - | func (o *ExtIdleNotification) handlersForResumed() []func() { | |
| 172 | - | o.handlersMu.Lock() | |
| 173 | - | defer o.handlersMu.Unlock() | |
| 174 | - | return o.onResumed | |
| 175 | - | } | |
| 176 | - | ||
| 177 | - | // EventSignature returns the declared event argument types in wire order. | |
| 178 | - | func (o *ExtIdleNotification) EventSignature(opcode uint16) (string, bool) { | |
| 179 | - | switch opcode { | |
| 180 | - | case 0: | |
| 181 | - | return "", true | |
| 182 | - | case 1: | |
| 183 | - | return "", true | |
| 184 | - | default: | |
| 185 | - | return "", false | |
| 186 | - | } | |
| 187 | - | } | |
| 188 | - | ||
| 189 | - | // Dispatch decodes one event on ext_idle_notification_v1 and calls the registered handlers. | |
| 190 | - | func (o *ExtIdleNotification) Dispatch(event *wl.Event) { | |
| 191 | - | switch event.Opcode { | |
| 192 | - | case 0: // idled | |
| 193 | - | ||
| 194 | - | for i, handler := range o.handlersForIdled() { | |
| 195 | - | _ = i | |
| 196 | - | handler() | |
| 197 | - | } | |
| 198 | - | case 1: // resumed | |
| 199 | - | ||
| 200 | - | for i, handler := range o.handlersForResumed() { | |
| 201 | - | _ = i | |
| 202 | - | handler() | |
| 203 | - | } | |
| 204 | - | default: | |
| 205 | - | } | |
| 206 | - | } | |
D protocol/idlenotify/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package idlenotify | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p idlenotify -o ext-idle-notify-v1_generated.go -import wl_seat=github.com/bnema/wlturbo/protocol/core ext-idle-notify-v1.xml | |
D protocol/imagecapturesource/ext-image-capture-source-v1.xml +0 -109
| @@ -1,109 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="ext_image_capture_source_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2022 Andri Yngvason | |
| 5 | - | Copyright © 2024 Simon Ser | |
| 6 | - | ||
| 7 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 8 | - | copy of this software and associated documentation files (the "Software"), | |
| 9 | - | to deal in the Software without restriction, including without limitation | |
| 10 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 11 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 12 | - | Software is furnished to do so, subject to the following conditions: | |
| 13 | - | ||
| 14 | - | The above copyright notice and this permission notice (including the next | |
| 15 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 16 | - | Software. | |
| 17 | - | ||
| 18 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 23 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 24 | - | DEALINGS IN THE SOFTWARE. | |
| 25 | - | </copyright> | |
| 26 | - | ||
| 27 | - | <description summary="opaque image capture source objects"> | |
| 28 | - | This protocol serves as an intermediary between capturing protocols and | |
| 29 | - | potential image capture sources such as outputs and toplevels. | |
| 30 | - | ||
| 31 | - | This protocol may be extended to support more image capture sources in the | |
| 32 | - | future, thereby adding those image capture sources to other protocols that | |
| 33 | - | use the image capture source object without having to modify those | |
| 34 | - | protocols. | |
| 35 | - | ||
| 36 | - | Warning! The protocol described in this file is currently in the testing | |
| 37 | - | phase. Backward compatible changes may be added together with the | |
| 38 | - | corresponding interface version bump. Backward incompatible changes can | |
| 39 | - | only be done by creating a new major version of the extension. | |
| 40 | - | </description> | |
| 41 | - | ||
| 42 | - | <interface name="ext_image_capture_source_v1" version="1" frozen="true"> | |
| 43 | - | <description summary="opaque image capture source object"> | |
| 44 | - | The image capture source object is an opaque descriptor for a capturable | |
| 45 | - | resource. This resource may be any sort of entity from which an image | |
| 46 | - | may be derived. | |
| 47 | - | ||
| 48 | - | Note, because ext_image_capture_source_v1 objects are created from multiple | |
| 49 | - | independent factory interfaces, the ext_image_capture_source_v1 interface is | |
| 50 | - | frozen at version 1. | |
| 51 | - | </description> | |
| 52 | - | ||
| 53 | - | <request name="destroy" type="destructor"> | |
| 54 | - | <description summary="delete this object"> | |
| 55 | - | Destroys the image capture source. This request may be sent at any time | |
| 56 | - | by the client. | |
| 57 | - | </description> | |
| 58 | - | </request> | |
| 59 | - | </interface> | |
| 60 | - | ||
| 61 | - | <interface name="ext_output_image_capture_source_manager_v1" version="1"> | |
| 62 | - | <description summary="image capture source manager for outputs"> | |
| 63 | - | A manager for creating image capture source objects for wl_output objects. | |
| 64 | - | </description> | |
| 65 | - | ||
| 66 | - | <request name="create_source"> | |
| 67 | - | <description summary="create source object for output"> | |
| 68 | - | Creates a source object for an output. Images captured from this source | |
| 69 | - | will show the same content as the output. Some elements may be omitted, | |
| 70 | - | such as cursors and overlays that have been marked as transparent to | |
| 71 | - | capturing. | |
| 72 | - | </description> | |
| 73 | - | <arg name="source" type="new_id" interface="ext_image_capture_source_v1"/> | |
| 74 | - | <arg name="output" type="object" interface="wl_output"/> | |
| 75 | - | </request> | |
| 76 | - | ||
| 77 | - | <request name="destroy" type="destructor"> | |
| 78 | - | <description summary="delete this object"> | |
| 79 | - | Destroys the manager. This request may be sent at any time by the client | |
| 80 | - | and objects created by the manager will remain valid after its | |
| 81 | - | destruction. | |
| 82 | - | </description> | |
| 83 | - | </request> | |
| 84 | - | </interface> | |
| 85 | - | ||
| 86 | - | <interface name="ext_foreign_toplevel_image_capture_source_manager_v1" version="1"> | |
| 87 | - | <description summary="image capture source manager for foreign toplevels"> | |
| 88 | - | A manager for creating image capture source objects for | |
| 89 | - | ext_foreign_toplevel_handle_v1 objects. | |
| 90 | - | </description> | |
| 91 | - | ||
| 92 | - | <request name="create_source"> | |
| 93 | - | <description summary="create source object for foreign toplevel"> | |
| 94 | - | Creates a source object for a foreign toplevel handle. Images captured | |
| 95 | - | from this source will show the same content as the toplevel. | |
| 96 | - | </description> | |
| 97 | - | <arg name="source" type="new_id" interface="ext_image_capture_source_v1"/> | |
| 98 | - | <arg name="toplevel_handle" type="object" interface="ext_foreign_toplevel_handle_v1"/> | |
| 99 | - | </request> | |
| 100 | - | ||
| 101 | - | <request name="destroy" type="destructor"> | |
| 102 | - | <description summary="delete this object"> | |
| 103 | - | Destroys the manager. This request may be sent at any time by the client | |
| 104 | - | and objects created by the manager will remain valid after its | |
| 105 | - | destruction. | |
| 106 | - | </description> | |
| 107 | - | </request> | |
| 108 | - | </interface> | |
| 109 | - | </protocol> | |
D protocol/imagecapturesource/ext-image-capture-source-v1_generated.go +0 -179
| @@ -1,179 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: ext_image_capture_source_v1 | |
| 3 | - | // Source: ext-image-capture-source-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2022 Andri Yngvason | |
| 7 | - | // Copyright © 2024 Simon Ser | |
| 8 | - | // | |
| 9 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 | - | // copy of this software and associated documentation files (the "Software"), | |
| 11 | - | // to deal in the Software without restriction, including without limitation | |
| 12 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 14 | - | // Software is furnished to do so, subject to the following conditions: | |
| 15 | - | // | |
| 16 | - | // The above copyright notice and this permission notice (including the next | |
| 17 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 18 | - | // Software. | |
| 19 | - | // | |
| 20 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 23 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 25 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 26 | - | // DEALINGS IN THE SOFTWARE. | |
| 27 | - | ||
| 28 | - | package imagecapturesource | |
| 29 | - | ||
| 30 | - | import ( | |
| 31 | - | cross_wl_output "github.com/bnema/wlturbo/protocol/core" | |
| 32 | - | cross_ext_foreign_toplevel_handle_v1 "github.com/bnema/wlturbo/protocol/extforeigntoplevel" | |
| 33 | - | "github.com/bnema/wlturbo/wl" | |
| 34 | - | ) | |
| 35 | - | ||
| 36 | - | // ExtImageCaptureSourceInterface is the protocol interface name. | |
| 37 | - | const ExtImageCaptureSourceInterface = "ext_image_capture_source_v1" | |
| 38 | - | ||
| 39 | - | // ExtImageCaptureSource is the generated binding for ext_image_capture_source_v1 version 1. | |
| 40 | - | type ExtImageCaptureSource struct { | |
| 41 | - | wl.BaseProxy | |
| 42 | - | } | |
| 43 | - | ||
| 44 | - | // NewExtImageCaptureSource returns an unbound ExtImageCaptureSource. | |
| 45 | - | func NewExtImageCaptureSource(ctx *wl.Context) *ExtImageCaptureSource { | |
| 46 | - | obj := &ExtImageCaptureSource{} | |
| 47 | - | obj.SetContext(ctx) | |
| 48 | - | ctx.Register(obj) | |
| 49 | - | return obj | |
| 50 | - | } | |
| 51 | - | ||
| 52 | - | // Destroys the image capture source. This request may be sent at any time by the client. | |
| 53 | - | func (o *ExtImageCaptureSource) Destroy() error { | |
| 54 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_image_capture_source_v1.destroy", Destructor: true}); err != nil { | |
| 55 | - | return err | |
| 56 | - | } | |
| 57 | - | return nil | |
| 58 | - | } | |
| 59 | - | ||
| 60 | - | // EventSignature returns the declared event argument types in wire order. | |
| 61 | - | func (o *ExtImageCaptureSource) EventSignature(opcode uint16) (string, bool) { | |
| 62 | - | switch opcode { | |
| 63 | - | default: | |
| 64 | - | return "", false | |
| 65 | - | } | |
| 66 | - | } | |
| 67 | - | ||
| 68 | - | // Dispatch decodes one event on ext_image_capture_source_v1 and calls the registered handlers. | |
| 69 | - | func (o *ExtImageCaptureSource) Dispatch(event *wl.Event) { | |
| 70 | - | switch event.Opcode { | |
| 71 | - | default: | |
| 72 | - | } | |
| 73 | - | } | |
| 74 | - | ||
| 75 | - | // ExtOutputImageCaptureSourceManagerInterface is the protocol interface name. | |
| 76 | - | const ExtOutputImageCaptureSourceManagerInterface = "ext_output_image_capture_source_manager_v1" | |
| 77 | - | ||
| 78 | - | // ExtOutputImageCaptureSourceManager is the generated binding for ext_output_image_capture_source_manager_v1 version 1. | |
| 79 | - | type ExtOutputImageCaptureSourceManager struct { | |
| 80 | - | wl.BaseProxy | |
| 81 | - | } | |
| 82 | - | ||
| 83 | - | // NewExtOutputImageCaptureSourceManager returns an unbound ExtOutputImageCaptureSourceManager. | |
| 84 | - | func NewExtOutputImageCaptureSourceManager(ctx *wl.Context) *ExtOutputImageCaptureSourceManager { | |
| 85 | - | obj := &ExtOutputImageCaptureSourceManager{} | |
| 86 | - | obj.SetContext(ctx) | |
| 87 | - | ctx.Register(obj) | |
| 88 | - | return obj | |
| 89 | - | } | |
| 90 | - | ||
| 91 | - | // Creates a source object for an output. Images captured from this source will show the same content as the output. Some elements may be omitted, such as cursors and overlays that have been marked as transparent to capturing. | |
| 92 | - | func (o *ExtOutputImageCaptureSourceManager) CreateSource(output *cross_wl_output.Output) (*ExtImageCaptureSource, error) { | |
| 93 | - | var arg1 wl.Object | |
| 94 | - | if output != nil { | |
| 95 | - | arg1 = output | |
| 96 | - | } | |
| 97 | - | child := &ExtImageCaptureSource{} | |
| 98 | - | child.SetContext(o.Context()) | |
| 99 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_output_image_capture_source_manager_v1.create_source", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 100 | - | return nil, err | |
| 101 | - | } | |
| 102 | - | return child, nil | |
| 103 | - | } | |
| 104 | - | ||
| 105 | - | // Destroys the manager. This request may be sent at any time by the client and objects created by the manager will remain valid after its destruction. | |
| 106 | - | func (o *ExtOutputImageCaptureSourceManager) Destroy() error { | |
| 107 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_output_image_capture_source_manager_v1.destroy", Destructor: true}); err != nil { | |
| 108 | - | return err | |
| 109 | - | } | |
| 110 | - | return nil | |
| 111 | - | } | |
| 112 | - | ||
| 113 | - | // EventSignature returns the declared event argument types in wire order. | |
| 114 | - | func (o *ExtOutputImageCaptureSourceManager) EventSignature(opcode uint16) (string, bool) { | |
| 115 | - | switch opcode { | |
| 116 | - | default: | |
| 117 | - | return "", false | |
| 118 | - | } | |
| 119 | - | } | |
| 120 | - | ||
| 121 | - | // Dispatch decodes one event on ext_output_image_capture_source_manager_v1 and calls the registered handlers. | |
| 122 | - | func (o *ExtOutputImageCaptureSourceManager) Dispatch(event *wl.Event) { | |
| 123 | - | switch event.Opcode { | |
| 124 | - | default: | |
| 125 | - | } | |
| 126 | - | } | |
| 127 | - | ||
| 128 | - | // ExtForeignToplevelImageCaptureSourceManagerInterface is the protocol interface name. | |
| 129 | - | const ExtForeignToplevelImageCaptureSourceManagerInterface = "ext_foreign_toplevel_image_capture_source_manager_v1" | |
| 130 | - | ||
| 131 | - | // ExtForeignToplevelImageCaptureSourceManager is the generated binding for ext_foreign_toplevel_image_capture_source_manager_v1 version 1. | |
| 132 | - | type ExtForeignToplevelImageCaptureSourceManager struct { | |
| 133 | - | wl.BaseProxy | |
| 134 | - | } | |
| 135 | - | ||
| 136 | - | // NewExtForeignToplevelImageCaptureSourceManager returns an unbound ExtForeignToplevelImageCaptureSourceManager. | |
| 137 | - | func NewExtForeignToplevelImageCaptureSourceManager(ctx *wl.Context) *ExtForeignToplevelImageCaptureSourceManager { | |
| 138 | - | obj := &ExtForeignToplevelImageCaptureSourceManager{} | |
| 139 | - | obj.SetContext(ctx) | |
| 140 | - | ctx.Register(obj) | |
| 141 | - | return obj | |
| 142 | - | } | |
| 143 | - | ||
| 144 | - | // Creates a source object for a foreign toplevel handle. Images captured from this source will show the same content as the toplevel. | |
| 145 | - | func (o *ExtForeignToplevelImageCaptureSourceManager) CreateSource(toplevelHandle *cross_ext_foreign_toplevel_handle_v1.ExtForeignToplevelHandle) (*ExtImageCaptureSource, error) { | |
| 146 | - | var arg1 wl.Object | |
| 147 | - | if toplevelHandle != nil { | |
| 148 | - | arg1 = toplevelHandle | |
| 149 | - | } | |
| 150 | - | child := &ExtImageCaptureSource{} | |
| 151 | - | child.SetContext(o.Context()) | |
| 152 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_foreign_toplevel_image_capture_source_manager_v1.create_source", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 153 | - | return nil, err | |
| 154 | - | } | |
| 155 | - | return child, nil | |
| 156 | - | } | |
| 157 | - | ||
| 158 | - | // Destroys the manager. This request may be sent at any time by the client and objects created by the manager will remain valid after its destruction. | |
| 159 | - | func (o *ExtForeignToplevelImageCaptureSourceManager) Destroy() error { | |
| 160 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_foreign_toplevel_image_capture_source_manager_v1.destroy", Destructor: true}); err != nil { | |
| 161 | - | return err | |
| 162 | - | } | |
| 163 | - | return nil | |
| 164 | - | } | |
| 165 | - | ||
| 166 | - | // EventSignature returns the declared event argument types in wire order. | |
| 167 | - | func (o *ExtForeignToplevelImageCaptureSourceManager) EventSignature(opcode uint16) (string, bool) { | |
| 168 | - | switch opcode { | |
| 169 | - | default: | |
| 170 | - | return "", false | |
| 171 | - | } | |
| 172 | - | } | |
| 173 | - | ||
| 174 | - | // Dispatch decodes one event on ext_foreign_toplevel_image_capture_source_manager_v1 and calls the registered handlers. | |
| 175 | - | func (o *ExtForeignToplevelImageCaptureSourceManager) Dispatch(event *wl.Event) { | |
| 176 | - | switch event.Opcode { | |
| 177 | - | default: | |
| 178 | - | } | |
| 179 | - | } | |
D protocol/imagecapturesource/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package imagecapturesource | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p imagecapturesource -import ext_foreign_toplevel_handle_v1=github.com/bnema/wlturbo/protocol/extforeigntoplevel -o ext-image-capture-source-v1_generated.go -import wl_output=github.com/bnema/wlturbo/protocol/core ext-image-capture-source-v1.xml | |
D protocol/imagecopycapture/ext-image-copy-capture-v1.xml +0 -456
| @@ -1,456 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="ext_image_copy_capture_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2021-2023 Andri Yngvason | |
| 5 | - | Copyright © 2024 Simon Ser | |
| 6 | - | ||
| 7 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 8 | - | copy of this software and associated documentation files (the "Software"), | |
| 9 | - | to deal in the Software without restriction, including without limitation | |
| 10 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 11 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 12 | - | Software is furnished to do so, subject to the following conditions: | |
| 13 | - | ||
| 14 | - | The above copyright notice and this permission notice (including the next | |
| 15 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 16 | - | Software. | |
| 17 | - | ||
| 18 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 23 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 24 | - | DEALINGS IN THE SOFTWARE. | |
| 25 | - | </copyright> | |
| 26 | - | ||
| 27 | - | <description summary="image capturing into client buffers"> | |
| 28 | - | This protocol allows clients to ask the compositor to capture image sources | |
| 29 | - | such as outputs and toplevels into user submitted buffers. | |
| 30 | - | ||
| 31 | - | Warning! The protocol described in this file is currently in the testing | |
| 32 | - | phase. Backward compatible changes may be added together with the | |
| 33 | - | corresponding interface version bump. Backward incompatible changes can | |
| 34 | - | only be done by creating a new major version of the extension. | |
| 35 | - | </description> | |
| 36 | - | ||
| 37 | - | <interface name="ext_image_copy_capture_manager_v1" version="1"> | |
| 38 | - | <description summary="manager to inform clients and begin capturing"> | |
| 39 | - | This object is a manager which offers requests to start capturing from a | |
| 40 | - | source. | |
| 41 | - | </description> | |
| 42 | - | ||
| 43 | - | <enum name="error"> | |
| 44 | - | <entry name="invalid_option" value="1" summary="invalid option flag"/> | |
| 45 | - | </enum> | |
| 46 | - | ||
| 47 | - | <enum name="options" bitfield="true"> | |
| 48 | - | <entry name="paint_cursors" value="1" summary="paint cursors onto captured frames"/> | |
| 49 | - | </enum> | |
| 50 | - | ||
| 51 | - | <request name="create_session"> | |
| 52 | - | <description summary="capture an image capture source"> | |
| 53 | - | Create a capturing session for an image capture source. | |
| 54 | - | ||
| 55 | - | If the paint_cursors option is set, cursors shall be composited onto | |
| 56 | - | the captured frame. The cursor must not be composited onto the frame | |
| 57 | - | if this flag is not set. | |
| 58 | - | ||
| 59 | - | If the options bitfield is invalid, the invalid_option protocol error | |
| 60 | - | is sent. | |
| 61 | - | </description> | |
| 62 | - | <arg name="session" type="new_id" interface="ext_image_copy_capture_session_v1"/> | |
| 63 | - | <arg name="source" type="object" interface="ext_image_capture_source_v1"/> | |
| 64 | - | <arg name="options" type="uint" enum="options"/> | |
| 65 | - | </request> | |
| 66 | - | ||
| 67 | - | <request name="create_pointer_cursor_session"> | |
| 68 | - | <description summary="capture the pointer cursor of an image capture source"> | |
| 69 | - | Create a cursor capturing session for the pointer of an image capture | |
| 70 | - | source. | |
| 71 | - | </description> | |
| 72 | - | <arg name="session" type="new_id" interface="ext_image_copy_capture_cursor_session_v1"/> | |
| 73 | - | <arg name="source" type="object" interface="ext_image_capture_source_v1"/> | |
| 74 | - | <arg name="pointer" type="object" interface="wl_pointer"/> | |
| 75 | - | </request> | |
| 76 | - | ||
| 77 | - | <request name="destroy" type="destructor"> | |
| 78 | - | <description summary="destroy the manager"> | |
| 79 | - | Destroy the manager object. | |
| 80 | - | ||
| 81 | - | Other objects created via this interface are unaffected. | |
| 82 | - | </description> | |
| 83 | - | </request> | |
| 84 | - | </interface> | |
| 85 | - | ||
| 86 | - | <interface name="ext_image_copy_capture_session_v1" version="1"> | |
| 87 | - | <description summary="image copy capture session"> | |
| 88 | - | This object represents an active image copy capture session. | |
| 89 | - | ||
| 90 | - | After a capture session is created, buffer constraint events will be | |
| 91 | - | emitted from the compositor to tell the client which buffer types and | |
| 92 | - | formats are supported for reading from the session. The compositor may | |
| 93 | - | re-send buffer constraint events whenever they change. | |
| 94 | - | ||
| 95 | - | To advertise buffer constraints, the compositor must send in no | |
| 96 | - | particular order: zero or more shm_format and dmabuf_format events, zero | |
| 97 | - | or one dmabuf_device event, and exactly one buffer_size event. Then the | |
| 98 | - | compositor must send a done event. | |
| 99 | - | ||
| 100 | - | When the client has received all the buffer constraints, it can create a | |
| 101 | - | buffer accordingly, attach it to the capture session using the | |
| 102 | - | attach_buffer request, set the buffer damage using the damage_buffer | |
| 103 | - | request and then send the capture request. | |
| 104 | - | </description> | |
| 105 | - | ||
| 106 | - | <enum name="error"> | |
| 107 | - | <entry name="duplicate_frame" value="1" | |
| 108 | - | summary="create_frame sent before destroying previous frame"/> | |
| 109 | - | </enum> | |
| 110 | - | ||
| 111 | - | <event name="buffer_size"> | |
| 112 | - | <description summary="image capture source dimensions"> | |
| 113 | - | Provides the dimensions of the source image in buffer pixel coordinates. | |
| 114 | - | ||
| 115 | - | The client must attach buffers that match this size. | |
| 116 | - | </description> | |
| 117 | - | <arg name="width" type="uint" summary="buffer width"/> | |
| 118 | - | <arg name="height" type="uint" summary="buffer height"/> | |
| 119 | - | </event> | |
| 120 | - | ||
| 121 | - | <event name="shm_format"> | |
| 122 | - | <description summary="shm buffer format"> | |
| 123 | - | Provides the format that must be used for shared-memory buffers. | |
| 124 | - | ||
| 125 | - | This event may be emitted multiple times, in which case the client may | |
| 126 | - | choose any given format. | |
| 127 | - | </description> | |
| 128 | - | <arg name="format" type="uint" enum="wl_shm.format" summary="shm format"/> | |
| 129 | - | </event> | |
| 130 | - | ||
| 131 | - | <event name="dmabuf_device"> | |
| 132 | - | <description summary="dma-buf device"> | |
| 133 | - | This event advertises the device buffers must be allocated on for | |
| 134 | - | dma-buf buffers. | |
| 135 | - | ||
| 136 | - | In general the device is a DRM node. The DRM node type (primary vs. | |
| 137 | - | render) is unspecified. Clients must not rely on the compositor sending | |
| 138 | - | a particular node type. Clients cannot check two devices for equality | |
| 139 | - | by comparing the dev_t value. | |
| 140 | - | </description> | |
| 141 | - | <arg name="device" type="array" summary="device dev_t value"/> | |
| 142 | - | </event> | |
| 143 | - | ||
| 144 | - | <event name="dmabuf_format"> | |
| 145 | - | <description summary="dma-buf format"> | |
| 146 | - | Provides the format that must be used for dma-buf buffers. | |
| 147 | - | ||
| 148 | - | The client may choose any of the modifiers advertised in the array of | |
| 149 | - | 64-bit unsigned integers. | |
| 150 | - | ||
| 151 | - | This event may be emitted multiple times, in which case the client may | |
| 152 | - | choose any given format. | |
| 153 | - | </description> | |
| 154 | - | <arg name="format" type="uint" summary="drm format code"/> | |
| 155 | - | <arg name="modifiers" type="array" summary="drm format modifiers"/> | |
| 156 | - | </event> | |
| 157 | - | ||
| 158 | - | <event name="done"> | |
| 159 | - | <description summary="all constraints have been sent"> | |
| 160 | - | This event is sent once when all buffer constraint events have been | |
| 161 | - | sent. | |
| 162 | - | ||
| 163 | - | The compositor must always end a batch of buffer constraint events with | |
| 164 | - | this event, regardless of whether it sends the initial constraints or | |
| 165 | - | an update. | |
| 166 | - | </description> | |
| 167 | - | </event> | |
| 168 | - | ||
| 169 | - | <event name="stopped"> | |
| 170 | - | <description summary="session is no longer available"> | |
| 171 | - | This event indicates that the capture session has stopped and is no | |
| 172 | - | longer available. This can happen in a number of cases, e.g. when the | |
| 173 | - | underlying source is destroyed, if the user decides to end the image | |
| 174 | - | capture, or if an unrecoverable runtime error has occurred. | |
| 175 | - | ||
| 176 | - | The client should destroy the session after receiving this event. | |
| 177 | - | </description> | |
| 178 | - | </event> | |
| 179 | - | ||
| 180 | - | <request name="create_frame"> | |
| 181 | - | <description summary="create a frame"> | |
| 182 | - | Create a capture frame for this session. | |
| 183 | - | ||
| 184 | - | At most one frame object can exist for a given session at any time. If | |
| 185 | - | a client sends a create_frame request before a previous frame object | |
| 186 | - | has been destroyed, the duplicate_frame protocol error is raised. | |
| 187 | - | </description> | |
| 188 | - | <arg name="frame" type="new_id" interface="ext_image_copy_capture_frame_v1"/> | |
| 189 | - | </request> | |
| 190 | - | ||
| 191 | - | <request name="destroy" type="destructor"> | |
| 192 | - | <description summary="delete this object"> | |
| 193 | - | Destroys the session. This request can be sent at any time by the | |
| 194 | - | client. | |
| 195 | - | ||
| 196 | - | This request doesn't affect ext_image_copy_capture_frame_v1 objects created by | |
| 197 | - | this object. | |
| 198 | - | </description> | |
| 199 | - | </request> | |
| 200 | - | </interface> | |
| 201 | - | ||
| 202 | - | <interface name="ext_image_copy_capture_frame_v1" version="1"> | |
| 203 | - | <description summary="image capture frame"> | |
| 204 | - | This object represents an image capture frame. | |
| 205 | - | ||
| 206 | - | The client should attach a buffer, damage the buffer, and then send a | |
| 207 | - | capture request. | |
| 208 | - | ||
| 209 | - | If the capture is successful, the compositor must send the frame metadata | |
| 210 | - | (transform, damage, presentation_time in any order) followed by the ready | |
| 211 | - | event. | |
| 212 | - | ||
| 213 | - | If the capture fails, the compositor must send the failed event. | |
| 214 | - | </description> | |
| 215 | - | ||
| 216 | - | <enum name="error"> | |
| 217 | - | <entry name="no_buffer" value="1" summary="capture sent without attach_buffer"/> | |
| 218 | - | <entry name="invalid_buffer_damage" value="2" summary="invalid buffer damage"/> | |
| 219 | - | <entry name="already_captured" value="3" summary="capture request has been sent"/> | |
| 220 | - | </enum> | |
| 221 | - | ||
| 222 | - | <request name="destroy" type="destructor"> | |
| 223 | - | <description summary="destroy this object"> | |
| 224 | - | Destroys the frame. This request can be sent at any time by the | |
| 225 | - | client. | |
| 226 | - | </description> | |
| 227 | - | </request> | |
| 228 | - | ||
| 229 | - | <request name="attach_buffer"> | |
| 230 | - | <description summary="attach buffer to session"> | |
| 231 | - | Attach a buffer to the session. | |
| 232 | - | ||
| 233 | - | The wl_buffer.release request is unused. | |
| 234 | - | ||
| 235 | - | The new buffer replaces any previously attached buffer. | |
| 236 | - | ||
| 237 | - | This request must not be sent after capture, or else the | |
| 238 | - | already_captured protocol error is raised. | |
| 239 | - | </description> | |
| 240 | - | <arg name="buffer" type="object" interface="wl_buffer"/> | |
| 241 | - | </request> | |
| 242 | - | ||
| 243 | - | <request name="damage_buffer"> | |
| 244 | - | <description summary="damage buffer"> | |
| 245 | - | Apply damage to the buffer which is to be captured next. This request | |
| 246 | - | may be sent multiple times to describe a region. | |
| 247 | - | ||
| 248 | - | The client indicates the accumulated damage since this wl_buffer was | |
| 249 | - | last captured. During capture, the compositor will update the buffer | |
| 250 | - | with at least the union of the region passed by the client and the | |
| 251 | - | region advertised by ext_image_copy_capture_frame_v1.damage. | |
| 252 | - | ||
| 253 | - | When a wl_buffer is captured for the first time, or when the client | |
| 254 | - | doesn't track damage, the client must damage the whole buffer. | |
| 255 | - | ||
| 256 | - | This is for optimisation purposes. The compositor may use this | |
| 257 | - | information to reduce copying. | |
| 258 | - | ||
| 259 | - | These coordinates originate from the upper left corner of the buffer. | |
| 260 | - | ||
| 261 | - | If x or y are strictly negative, or if width or height are negative or | |
| 262 | - | zero, the invalid_buffer_damage protocol error is raised. | |
| 263 | - | ||
| 264 | - | This request must not be sent after capture, or else the | |
| 265 | - | already_captured protocol error is raised. | |
| 266 | - | </description> | |
| 267 | - | <arg name="x" type="int" summary="region x coordinate"/> | |
| 268 | - | <arg name="y" type="int" summary="region y coordinate"/> | |
| 269 | - | <arg name="width" type="int" summary="region width"/> | |
| 270 | - | <arg name="height" type="int" summary="region height"/> | |
| 271 | - | </request> | |
| 272 | - | ||
| 273 | - | <request name="capture"> | |
| 274 | - | <description summary="capture a frame"> | |
| 275 | - | Capture a frame. | |
| 276 | - | ||
| 277 | - | Unless this is the first successful captured frame performed in this | |
| 278 | - | session, the compositor may wait an indefinite amount of time for the | |
| 279 | - | source content to change before performing the copy. | |
| 280 | - | ||
| 281 | - | This request may only be sent once, or else the already_captured | |
| 282 | - | protocol error is raised. A buffer must be attached before this request | |
| 283 | - | is sent, or else the no_buffer protocol error is raised. | |
| 284 | - | </description> | |
| 285 | - | </request> | |
| 286 | - | ||
| 287 | - | <event name="transform"> | |
| 288 | - | <description summary="buffer transform"> | |
| 289 | - | This event is sent before the ready event and holds the transform that | |
| 290 | - | the compositor has applied to the buffer contents. | |
| 291 | - | </description> | |
| 292 | - | <arg name="transform" type="uint" enum="wl_output.transform"/> | |
| 293 | - | </event> | |
| 294 | - | ||
| 295 | - | <event name="damage"> | |
| 296 | - | <description summary="buffer damaged region"> | |
| 297 | - | This event is sent before the ready event. It may be generated multiple | |
| 298 | - | times to describe a region. | |
| 299 | - | ||
| 300 | - | The first captured frame in a session will always carry full damage. | |
| 301 | - | Subsequent frames' damaged regions describe which parts of the buffer | |
| 302 | - | have changed since the last ready event. | |
| 303 | - | ||
| 304 | - | These coordinates originate in the upper left corner of the buffer. | |
| 305 | - | </description> | |
| 306 | - | <arg name="x" type="int" summary="damage x coordinate"/> | |
| 307 | - | <arg name="y" type="int" summary="damage y coordinate"/> | |
| 308 | - | <arg name="width" type="int" summary="damage width"/> | |
| 309 | - | <arg name="height" type="int" summary="damage height"/> | |
| 310 | - | </event> | |
| 311 | - | ||
| 312 | - | <event name="presentation_time"> | |
| 313 | - | <description summary="presentation time of the frame"> | |
| 314 | - | This event indicates the time at which the frame is presented to the | |
| 315 | - | output in system monotonic time. This event is sent before the ready | |
| 316 | - | event. | |
| 317 | - | ||
| 318 | - | The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples, | |
| 319 | - | each component being an unsigned 32-bit value. Whole seconds are in | |
| 320 | - | tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo, | |
| 321 | - | and the additional fractional part in tv_nsec as nanoseconds. Hence, | |
| 322 | - | for valid timestamps tv_nsec must be in [0, 999999999]. | |
| 323 | - | </description> | |
| 324 | - | <arg name="tv_sec_hi" type="uint" | |
| 325 | - | summary="high 32 bits of the seconds part of the timestamp"/> | |
| 326 | - | <arg name="tv_sec_lo" type="uint" | |
| 327 | - | summary="low 32 bits of the seconds part of the timestamp"/> | |
| 328 | - | <arg name="tv_nsec" type="uint" | |
| 329 | - | summary="nanoseconds part of the timestamp"/> | |
| 330 | - | </event> | |
| 331 | - | ||
| 332 | - | <event name="ready"> | |
| 333 | - | <description summary="frame is available for reading"> | |
| 334 | - | Called as soon as the frame is copied, indicating it is available | |
| 335 | - | for reading. | |
| 336 | - | ||
| 337 | - | The buffer may be re-used by the client after this event. | |
| 338 | - | ||
| 339 | - | After receiving this event, the client must destroy the object. | |
| 340 | - | </description> | |
| 341 | - | </event> | |
| 342 | - | ||
| 343 | - | <enum name="failure_reason"> | |
| 344 | - | <entry name="unknown" value="0"> | |
| 345 | - | <description summary="unknown runtime error"> | |
| 346 | - | An unspecified runtime error has occurred. The client may retry. | |
| 347 | - | </description> | |
| 348 | - | </entry> | |
| 349 | - | <entry name="buffer_constraints" value="1"> | |
| 350 | - | <description summary="buffer constraints mismatch"> | |
| 351 | - | The buffer submitted by the client doesn't match the latest session | |
| 352 | - | constraints. The client should re-allocate its buffers and retry. | |
| 353 | - | </description> | |
| 354 | - | </entry> | |
| 355 | - | <entry name="stopped" value="2"> | |
| 356 | - | <description summary="session is no longer available"> | |
| 357 | - | The session has stopped. See ext_image_copy_capture_session_v1.stopped. | |
| 358 | - | </description> | |
| 359 | - | </entry> | |
| 360 | - | </enum> | |
| 361 | - | ||
| 362 | - | <event name="failed"> | |
| 363 | - | <description summary="capture failed"> | |
| 364 | - | This event indicates that the attempted frame copy has failed. | |
| 365 | - | ||
| 366 | - | After receiving this event, the client must destroy the object. | |
| 367 | - | </description> | |
| 368 | - | <arg name="reason" type="uint" enum="failure_reason"/> | |
| 369 | - | </event> | |
| 370 | - | </interface> | |
| 371 | - | ||
| 372 | - | <interface name="ext_image_copy_capture_cursor_session_v1" version="1"> | |
| 373 | - | <description summary="cursor capture session"> | |
| 374 | - | This object represents a cursor capture session. It extends the base | |
| 375 | - | capture session with cursor-specific metadata. | |
| 376 | - | </description> | |
| 377 | - | ||
| 378 | - | <enum name="error"> | |
| 379 | - | <entry name="duplicate_session" value="1" summary="get_capture_session sent twice"/> | |
| 380 | - | </enum> | |
| 381 | - | ||
| 382 | - | <request name="destroy" type="destructor"> | |
| 383 | - | <description summary="delete this object"> | |
| 384 | - | Destroys the session. This request can be sent at any time by the | |
| 385 | - | client. | |
| 386 | - | ||
| 387 | - | This request doesn't affect ext_image_copy_capture_frame_v1 objects created by | |
| 388 | - | this object. | |
| 389 | - | </description> | |
| 390 | - | </request> | |
| 391 | - | ||
| 392 | - | <request name="get_capture_session"> | |
| 393 | - | <description summary="get image copy capturer session"> | |
| 394 | - | Gets the image copy capture session for this cursor session. | |
| 395 | - | ||
| 396 | - | The session will produce frames of the cursor image. The compositor may | |
| 397 | - | pause the session when the cursor leaves the captured area. | |
| 398 | - | ||
| 399 | - | This request must not be sent more than once, or else the | |
| 400 | - | duplicate_session protocol error is raised. | |
| 401 | - | </description> | |
| 402 | - | <arg name="session" type="new_id" interface="ext_image_copy_capture_session_v1"/> | |
| 403 | - | </request> | |
| 404 | - | ||
| 405 | - | <event name="enter"> | |
| 406 | - | <description summary="cursor entered captured area"> | |
| 407 | - | Sent when a cursor enters the captured area. It shall be generated | |
| 408 | - | before the "position" and "hotspot" events when and only when a cursor | |
| 409 | - | enters the area. | |
| 410 | - | ||
| 411 | - | The cursor enters the captured area when the cursor image intersects | |
| 412 | - | with the captured area. Note, this is different from e.g. | |
| 413 | - | wl_pointer.enter. | |
| 414 | - | </description> | |
| 415 | - | </event> | |
| 416 | - | ||
| 417 | - | <event name="leave"> | |
| 418 | - | <description summary="cursor left captured area"> | |
| 419 | - | Sent when a cursor leaves the captured area. No "position" or "hotspot" | |
| 420 | - | event is generated for the cursor until the cursor enters the captured | |
| 421 | - | area again. | |
| 422 | - | </description> | |
| 423 | - | </event> | |
| 424 | - | ||
| 425 | - | <event name="position"> | |
| 426 | - | <description summary="position changed"> | |
| 427 | - | Cursors outside the image capture source do not get captured and no | |
| 428 | - | event will be generated for them. | |
| 429 | - | ||
| 430 | - | The given position is the position of the cursor's hotspot and it is | |
| 431 | - | relative to the main buffer's top left corner in transformed buffer | |
| 432 | - | pixel coordinates. The coordinates may be negative or greater than the | |
| 433 | - | main buffer size. | |
| 434 | - | </description> | |
| 435 | - | <arg name="x" type="int" summary="position x coordinates"/> | |
| 436 | - | <arg name="y" type="int" summary="position y coordinates"/> | |
| 437 | - | </event> | |
| 438 | - | ||
| 439 | - | <event name="hotspot"> | |
| 440 | - | <description summary="hotspot changed"> | |
| 441 | - | The hotspot describes the offset between the cursor image and the | |
| 442 | - | position of the input device. | |
| 443 | - | ||
| 444 | - | The given coordinates are the hotspot's offset from the origin in | |
| 445 | - | buffer coordinates. | |
| 446 | - | ||
| 447 | - | Clients should not apply the hotspot immediately: the hotspot becomes | |
| 448 | - | effective when the next ext_image_copy_capture_frame_v1.ready event is received. | |
| 449 | - | ||
| 450 | - | Compositors may delay this event until the client captures a new frame. | |
| 451 | - | </description> | |
| 452 | - | <arg name="x" type="int" summary="hotspot x coordinates"/> | |
| 453 | - | <arg name="y" type="int" summary="hotspot y coordinates"/> | |
| 454 | - | </event> | |
| 455 | - | </interface> | |
| 456 | - | </protocol> | |
D protocol/imagecopycapture/ext-image-copy-capture-v1_generated.go +0 -796
| @@ -1,796 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: ext_image_copy_capture_v1 | |
| 3 | - | // Source: ext-image-copy-capture-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2021-2023 Andri Yngvason | |
| 7 | - | // Copyright © 2024 Simon Ser | |
| 8 | - | // | |
| 9 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 | - | // copy of this software and associated documentation files (the "Software"), | |
| 11 | - | // to deal in the Software without restriction, including without limitation | |
| 12 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 14 | - | // Software is furnished to do so, subject to the following conditions: | |
| 15 | - | // | |
| 16 | - | // The above copyright notice and this permission notice (including the next | |
| 17 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 18 | - | // Software. | |
| 19 | - | // | |
| 20 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 23 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 25 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 26 | - | // DEALINGS IN THE SOFTWARE. | |
| 27 | - | ||
| 28 | - | package imagecopycapture | |
| 29 | - | ||
| 30 | - | import ( | |
| 31 | - | "sync" | |
| 32 | - | ||
| 33 | - | cross_wl_buffer "github.com/bnema/wlturbo/protocol/core" | |
| 34 | - | cross_wl_pointer "github.com/bnema/wlturbo/protocol/core" | |
| 35 | - | cross_ext_image_capture_source_v1 "github.com/bnema/wlturbo/protocol/imagecapturesource" | |
| 36 | - | "github.com/bnema/wlturbo/wl" | |
| 37 | - | ) | |
| 38 | - | ||
| 39 | - | // ERROR_INVALID_OPTION is the error invalid_option value. | |
| 40 | - | const ERROR_INVALID_OPTION = 1 | |
| 41 | - | ||
| 42 | - | // OPTIONS_PAINT_CURSORS is the options paint_cursors value. | |
| 43 | - | const OPTIONS_PAINT_CURSORS = 1 | |
| 44 | - | ||
| 45 | - | // ERROR_DUPLICATE_FRAME is the error duplicate_frame value. | |
| 46 | - | const ERROR_DUPLICATE_FRAME = 1 | |
| 47 | - | ||
| 48 | - | // ERROR_NO_BUFFER is the error no_buffer value. | |
| 49 | - | const ERROR_NO_BUFFER = 1 | |
| 50 | - | ||
| 51 | - | // ERROR_INVALID_BUFFER_DAMAGE is the error invalid_buffer_damage value. | |
| 52 | - | const ERROR_INVALID_BUFFER_DAMAGE = 2 | |
| 53 | - | ||
| 54 | - | // ERROR_ALREADY_CAPTURED is the error already_captured value. | |
| 55 | - | const ERROR_ALREADY_CAPTURED = 3 | |
| 56 | - | ||
| 57 | - | // FAILURE_REASON_UNKNOWN is the failure_reason unknown value. | |
| 58 | - | const FAILURE_REASON_UNKNOWN = 0 | |
| 59 | - | ||
| 60 | - | // FAILURE_REASON_BUFFER_CONSTRAINTS is the failure_reason buffer_constraints value. | |
| 61 | - | const FAILURE_REASON_BUFFER_CONSTRAINTS = 1 | |
| 62 | - | ||
| 63 | - | // FAILURE_REASON_STOPPED is the failure_reason stopped value. | |
| 64 | - | const FAILURE_REASON_STOPPED = 2 | |
| 65 | - | ||
| 66 | - | // ERROR_DUPLICATE_SESSION is the error duplicate_session value. | |
| 67 | - | const ERROR_DUPLICATE_SESSION = 1 | |
| 68 | - | ||
| 69 | - | // ExtImageCopyCaptureManagerInterface is the protocol interface name. | |
| 70 | - | const ExtImageCopyCaptureManagerInterface = "ext_image_copy_capture_manager_v1" | |
| 71 | - | ||
| 72 | - | // ExtImageCopyCaptureManager is the generated binding for ext_image_copy_capture_manager_v1 version 1. | |
| 73 | - | type ExtImageCopyCaptureManager struct { | |
| 74 | - | wl.BaseProxy | |
| 75 | - | } | |
| 76 | - | ||
| 77 | - | // NewExtImageCopyCaptureManager returns an unbound ExtImageCopyCaptureManager. | |
| 78 | - | func NewExtImageCopyCaptureManager(ctx *wl.Context) *ExtImageCopyCaptureManager { | |
| 79 | - | obj := &ExtImageCopyCaptureManager{} | |
| 80 | - | obj.SetContext(ctx) | |
| 81 | - | ctx.Register(obj) | |
| 82 | - | return obj | |
| 83 | - | } | |
| 84 | - | ||
| 85 | - | // Create a capturing session for an image capture source. If the paint_cursors option is set, cursors shall be composited onto the captured frame. The cursor must not be composited onto the frame if this flag is not set. If the options bitfield is invalid, the invalid_option protocol error is sent. | |
| 86 | - | func (o *ExtImageCopyCaptureManager) CreateSession(source *cross_ext_image_capture_source_v1.ExtImageCaptureSource, options uint32) (*ExtImageCopyCaptureSession, error) { | |
| 87 | - | var arg1 wl.Object | |
| 88 | - | if source != nil { | |
| 89 | - | arg1 = source | |
| 90 | - | } | |
| 91 | - | child := &ExtImageCopyCaptureSession{} | |
| 92 | - | child.SetContext(o.Context()) | |
| 93 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_image_copy_capture_manager_v1.create_session", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1), wl.ArgUint(options)); err != nil { | |
| 94 | - | return nil, err | |
| 95 | - | } | |
| 96 | - | return child, nil | |
| 97 | - | } | |
| 98 | - | ||
| 99 | - | // Create a cursor capturing session for the pointer of an image capture source. | |
| 100 | - | func (o *ExtImageCopyCaptureManager) CreatePointerCursorSession(source *cross_ext_image_capture_source_v1.ExtImageCaptureSource, pointer *cross_wl_pointer.Pointer) (*ExtImageCopyCaptureCursorSession, error) { | |
| 101 | - | var arg1 wl.Object | |
| 102 | - | if source != nil { | |
| 103 | - | arg1 = source | |
| 104 | - | } | |
| 105 | - | var arg2 wl.Object | |
| 106 | - | if pointer != nil { | |
| 107 | - | arg2 = pointer | |
| 108 | - | } | |
| 109 | - | child := &ExtImageCopyCaptureCursorSession{} | |
| 110 | - | child.SetContext(o.Context()) | |
| 111 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_image_copy_capture_manager_v1.create_pointer_cursor_session", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1), wl.ArgObject(arg2)); err != nil { | |
| 112 | - | return nil, err | |
| 113 | - | } | |
| 114 | - | return child, nil | |
| 115 | - | } | |
| 116 | - | ||
| 117 | - | // Destroy the manager object. Other objects created via this interface are unaffected. | |
| 118 | - | func (o *ExtImageCopyCaptureManager) Destroy() error { | |
| 119 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "ext_image_copy_capture_manager_v1.destroy", Destructor: true}); err != nil { | |
| 120 | - | return err | |
| 121 | - | } | |
| 122 | - | return nil | |
| 123 | - | } | |
| 124 | - | ||
| 125 | - | // EventSignature returns the declared event argument types in wire order. | |
| 126 | - | func (o *ExtImageCopyCaptureManager) EventSignature(opcode uint16) (string, bool) { | |
| 127 | - | switch opcode { | |
| 128 | - | default: | |
| 129 | - | return "", false | |
| 130 | - | } | |
| 131 | - | } | |
| 132 | - | ||
| 133 | - | // Dispatch decodes one event on ext_image_copy_capture_manager_v1 and calls the registered handlers. | |
| 134 | - | func (o *ExtImageCopyCaptureManager) Dispatch(event *wl.Event) { | |
| 135 | - | switch event.Opcode { | |
| 136 | - | default: | |
| 137 | - | } | |
| 138 | - | } | |
| 139 | - | ||
| 140 | - | // ExtImageCopyCaptureSessionInterface is the protocol interface name. | |
| 141 | - | const ExtImageCopyCaptureSessionInterface = "ext_image_copy_capture_session_v1" | |
| 142 | - | ||
| 143 | - | // ExtImageCopyCaptureSession is the generated binding for ext_image_copy_capture_session_v1 version 1. | |
| 144 | - | type ExtImageCopyCaptureSession struct { | |
| 145 | - | wl.BaseProxy | |
| 146 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 147 | - | // handlers while another goroutine dispatches events. | |
| 148 | - | handlersMu sync.Mutex | |
| 149 | - | onBufferSize []func(width uint32, height uint32) | |
| 150 | - | onShmFormat []func(format uint32) | |
| 151 | - | onDmabufDevice []func(device []byte) | |
| 152 | - | onDmabufFormat []func(format uint32, modifiers []byte) | |
| 153 | - | onDone []func() | |
| 154 | - | onStopped []func() | |
| 155 | - | } | |
| 156 | - | ||
| 157 | - | // NewExtImageCopyCaptureSession returns an unbound ExtImageCopyCaptureSession. | |
| 158 | - | func NewExtImageCopyCaptureSession(ctx *wl.Context) *ExtImageCopyCaptureSession { | |
| 159 | - | obj := &ExtImageCopyCaptureSession{} | |
| 160 | - | obj.SetContext(ctx) | |
| 161 | - | ctx.Register(obj) | |
| 162 | - | return obj | |
| 163 | - | } | |
| 164 | - | ||
| 165 | - | // Create a capture frame for this session. At most one frame object can exist for a given session at any time. If a client sends a create_frame request before a previous frame object has been destroyed, the duplicate_frame protocol error is raised. | |
| 166 | - | func (o *ExtImageCopyCaptureSession) CreateFrame() (*ExtImageCopyCaptureFrame, error) { | |
| 167 | - | child := &ExtImageCopyCaptureFrame{} | |
| 168 | - | child.SetContext(o.Context()) | |
| 169 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_image_copy_capture_session_v1.create_frame", Child: child}, wl.ArgObject(child)); err != nil { | |
| 170 | - | return nil, err | |
| 171 | - | } | |
| 172 | - | return child, nil | |
| 173 | - | } | |
| 174 | - | ||
| 175 | - | // Destroys the session. This request can be sent at any time by the client. This request doesn't affect ext_image_copy_capture_frame_v1 objects created by this object. | |
| 176 | - | func (o *ExtImageCopyCaptureSession) Destroy() error { | |
| 177 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_image_copy_capture_session_v1.destroy", Destructor: true}); err != nil { | |
| 178 | - | return err | |
| 179 | - | } | |
| 180 | - | return nil | |
| 181 | - | } | |
| 182 | - | ||
| 183 | - | // OnBufferSize registers a handler for the buffer_size event. | |
| 184 | - | // | |
| 185 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 186 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 187 | - | func (o *ExtImageCopyCaptureSession) OnBufferSize(handler func(width uint32, height uint32)) { | |
| 188 | - | if handler == nil { | |
| 189 | - | return | |
| 190 | - | } | |
| 191 | - | o.handlersMu.Lock() | |
| 192 | - | defer o.handlersMu.Unlock() | |
| 193 | - | o.onBufferSize = append(o.onBufferSize, handler) | |
| 194 | - | } | |
| 195 | - | ||
| 196 | - | // handlersForBufferSize returns the handlers registered for buffer_size, taken | |
| 197 | - | // under the lock so a handler may register another handler while events are | |
| 198 | - | // being dispatched. | |
| 199 | - | func (o *ExtImageCopyCaptureSession) handlersForBufferSize() []func(width uint32, height uint32) { | |
| 200 | - | o.handlersMu.Lock() | |
| 201 | - | defer o.handlersMu.Unlock() | |
| 202 | - | return o.onBufferSize | |
| 203 | - | } | |
| 204 | - | ||
| 205 | - | // OnShmFormat registers a handler for the shm_format event. | |
| 206 | - | // | |
| 207 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 208 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 209 | - | func (o *ExtImageCopyCaptureSession) OnShmFormat(handler func(format uint32)) { | |
| 210 | - | if handler == nil { | |
| 211 | - | return | |
| 212 | - | } | |
| 213 | - | o.handlersMu.Lock() | |
| 214 | - | defer o.handlersMu.Unlock() | |
| 215 | - | o.onShmFormat = append(o.onShmFormat, handler) | |
| 216 | - | } | |
| 217 | - | ||
| 218 | - | // handlersForShmFormat returns the handlers registered for shm_format, taken | |
| 219 | - | // under the lock so a handler may register another handler while events are | |
| 220 | - | // being dispatched. | |
| 221 | - | func (o *ExtImageCopyCaptureSession) handlersForShmFormat() []func(format uint32) { | |
| 222 | - | o.handlersMu.Lock() | |
| 223 | - | defer o.handlersMu.Unlock() | |
| 224 | - | return o.onShmFormat | |
| 225 | - | } | |
| 226 | - | ||
| 227 | - | // OnDmabufDevice registers a handler for the dmabuf_device event. | |
| 228 | - | // | |
| 229 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 230 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 231 | - | func (o *ExtImageCopyCaptureSession) OnDmabufDevice(handler func(device []byte)) { | |
| 232 | - | if handler == nil { | |
| 233 | - | return | |
| 234 | - | } | |
| 235 | - | o.handlersMu.Lock() | |
| 236 | - | defer o.handlersMu.Unlock() | |
| 237 | - | o.onDmabufDevice = append(o.onDmabufDevice, handler) | |
| 238 | - | } | |
| 239 | - | ||
| 240 | - | // handlersForDmabufDevice returns the handlers registered for dmabuf_device, taken | |
| 241 | - | // under the lock so a handler may register another handler while events are | |
| 242 | - | // being dispatched. | |
| 243 | - | func (o *ExtImageCopyCaptureSession) handlersForDmabufDevice() []func(device []byte) { | |
| 244 | - | o.handlersMu.Lock() | |
| 245 | - | defer o.handlersMu.Unlock() | |
| 246 | - | return o.onDmabufDevice | |
| 247 | - | } | |
| 248 | - | ||
| 249 | - | // OnDmabufFormat registers a handler for the dmabuf_format event. | |
| 250 | - | // | |
| 251 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 252 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 253 | - | func (o *ExtImageCopyCaptureSession) OnDmabufFormat(handler func(format uint32, modifiers []byte)) { | |
| 254 | - | if handler == nil { | |
| 255 | - | return | |
| 256 | - | } | |
| 257 | - | o.handlersMu.Lock() | |
| 258 | - | defer o.handlersMu.Unlock() | |
| 259 | - | o.onDmabufFormat = append(o.onDmabufFormat, handler) | |
| 260 | - | } | |
| 261 | - | ||
| 262 | - | // handlersForDmabufFormat returns the handlers registered for dmabuf_format, taken | |
| 263 | - | // under the lock so a handler may register another handler while events are | |
| 264 | - | // being dispatched. | |
| 265 | - | func (o *ExtImageCopyCaptureSession) handlersForDmabufFormat() []func(format uint32, modifiers []byte) { | |
| 266 | - | o.handlersMu.Lock() | |
| 267 | - | defer o.handlersMu.Unlock() | |
| 268 | - | return o.onDmabufFormat | |
| 269 | - | } | |
| 270 | - | ||
| 271 | - | // OnDone registers a handler for the done event. | |
| 272 | - | // | |
| 273 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 274 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 275 | - | func (o *ExtImageCopyCaptureSession) OnDone(handler func()) { | |
| 276 | - | if handler == nil { | |
| 277 | - | return | |
| 278 | - | } | |
| 279 | - | o.handlersMu.Lock() | |
| 280 | - | defer o.handlersMu.Unlock() | |
| 281 | - | o.onDone = append(o.onDone, handler) | |
| 282 | - | } | |
| 283 | - | ||
| 284 | - | // handlersForDone returns the handlers registered for done, taken | |
| 285 | - | // under the lock so a handler may register another handler while events are | |
| 286 | - | // being dispatched. | |
| 287 | - | func (o *ExtImageCopyCaptureSession) handlersForDone() []func() { | |
| 288 | - | o.handlersMu.Lock() | |
| 289 | - | defer o.handlersMu.Unlock() | |
| 290 | - | return o.onDone | |
| 291 | - | } | |
| 292 | - | ||
| 293 | - | // OnStopped registers a handler for the stopped event. | |
| 294 | - | // | |
| 295 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 296 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 297 | - | func (o *ExtImageCopyCaptureSession) OnStopped(handler func()) { | |
| 298 | - | if handler == nil { | |
| 299 | - | return | |
| 300 | - | } | |
| 301 | - | o.handlersMu.Lock() | |
| 302 | - | defer o.handlersMu.Unlock() | |
| 303 | - | o.onStopped = append(o.onStopped, handler) | |
| 304 | - | } | |
| 305 | - | ||
| 306 | - | // handlersForStopped returns the handlers registered for stopped, taken | |
| 307 | - | // under the lock so a handler may register another handler while events are | |
| 308 | - | // being dispatched. | |
| 309 | - | func (o *ExtImageCopyCaptureSession) handlersForStopped() []func() { | |
| 310 | - | o.handlersMu.Lock() | |
| 311 | - | defer o.handlersMu.Unlock() | |
| 312 | - | return o.onStopped | |
| 313 | - | } | |
| 314 | - | ||
| 315 | - | // EventSignature returns the declared event argument types in wire order. | |
| 316 | - | func (o *ExtImageCopyCaptureSession) EventSignature(opcode uint16) (string, bool) { | |
| 317 | - | switch opcode { | |
| 318 | - | case 0: | |
| 319 | - | return "uint,uint,", true | |
| 320 | - | case 1: | |
| 321 | - | return "uint,", true | |
| 322 | - | case 2: | |
| 323 | - | return "array,", true | |
| 324 | - | case 3: | |
| 325 | - | return "uint,array,", true | |
| 326 | - | case 4: | |
| 327 | - | return "", true | |
| 328 | - | case 5: | |
| 329 | - | return "", true | |
| 330 | - | default: | |
| 331 | - | return "", false | |
| 332 | - | } | |
| 333 | - | } | |
| 334 | - | ||
| 335 | - | // Dispatch decodes one event on ext_image_copy_capture_session_v1 and calls the registered handlers. | |
| 336 | - | func (o *ExtImageCopyCaptureSession) Dispatch(event *wl.Event) { | |
| 337 | - | switch event.Opcode { | |
| 338 | - | case 0: // buffer_size | |
| 339 | - | width := event.Uint32() | |
| 340 | - | height := event.Uint32() | |
| 341 | - | ||
| 342 | - | for i, handler := range o.handlersForBufferSize() { | |
| 343 | - | _ = i | |
| 344 | - | handler(width, height) | |
| 345 | - | } | |
| 346 | - | case 1: // shm_format | |
| 347 | - | format := event.Uint32() | |
| 348 | - | ||
| 349 | - | for i, handler := range o.handlersForShmFormat() { | |
| 350 | - | _ = i | |
| 351 | - | handler(format) | |
| 352 | - | } | |
| 353 | - | case 2: // dmabuf_device | |
| 354 | - | device := event.Array() | |
| 355 | - | ||
| 356 | - | for i, handler := range o.handlersForDmabufDevice() { | |
| 357 | - | _ = i | |
| 358 | - | handler(device) | |
| 359 | - | } | |
| 360 | - | case 3: // dmabuf_format | |
| 361 | - | format := event.Uint32() | |
| 362 | - | modifiers := event.Array() | |
| 363 | - | ||
| 364 | - | for i, handler := range o.handlersForDmabufFormat() { | |
| 365 | - | _ = i | |
| 366 | - | handler(format, modifiers) | |
| 367 | - | } | |
| 368 | - | case 4: // done | |
| 369 | - | ||
| 370 | - | for i, handler := range o.handlersForDone() { | |
| 371 | - | _ = i | |
| 372 | - | handler() | |
| 373 | - | } | |
| 374 | - | case 5: // stopped | |
| 375 | - | ||
| 376 | - | for i, handler := range o.handlersForStopped() { | |
| 377 | - | _ = i | |
| 378 | - | handler() | |
| 379 | - | } | |
| 380 | - | default: | |
| 381 | - | } | |
| 382 | - | } | |
| 383 | - | ||
| 384 | - | // ExtImageCopyCaptureFrameInterface is the protocol interface name. | |
| 385 | - | const ExtImageCopyCaptureFrameInterface = "ext_image_copy_capture_frame_v1" | |
| 386 | - | ||
| 387 | - | // ExtImageCopyCaptureFrame is the generated binding for ext_image_copy_capture_frame_v1 version 1. | |
| 388 | - | type ExtImageCopyCaptureFrame struct { | |
| 389 | - | wl.BaseProxy | |
| 390 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 391 | - | // handlers while another goroutine dispatches events. | |
| 392 | - | handlersMu sync.Mutex | |
| 393 | - | onTransform []func(transform uint32) | |
| 394 | - | onDamage []func(x int32, y int32, width int32, height int32) | |
| 395 | - | onPresentationTime []func(tvSecHi uint32, tvSecLo uint32, tvNsec uint32) | |
| 396 | - | onReady []func() | |
| 397 | - | onFailed []func(reason uint32) | |
| 398 | - | } | |
| 399 | - | ||
| 400 | - | // NewExtImageCopyCaptureFrame returns an unbound ExtImageCopyCaptureFrame. | |
| 401 | - | func NewExtImageCopyCaptureFrame(ctx *wl.Context) *ExtImageCopyCaptureFrame { | |
| 402 | - | obj := &ExtImageCopyCaptureFrame{} | |
| 403 | - | obj.SetContext(ctx) | |
| 404 | - | ctx.Register(obj) | |
| 405 | - | return obj | |
| 406 | - | } | |
| 407 | - | ||
| 408 | - | // Destroys the frame. This request can be sent at any time by the client. | |
| 409 | - | func (o *ExtImageCopyCaptureFrame) Destroy() error { | |
| 410 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_image_copy_capture_frame_v1.destroy", Destructor: true}); err != nil { | |
| 411 | - | return err | |
| 412 | - | } | |
| 413 | - | return nil | |
| 414 | - | } | |
| 415 | - | ||
| 416 | - | // Attach a buffer to the session. The wl_buffer.release request is unused. The new buffer replaces any previously attached buffer. This request must not be sent after capture, or else the already_captured protocol error is raised. | |
| 417 | - | func (o *ExtImageCopyCaptureFrame) AttachBuffer(buffer *cross_wl_buffer.Buffer) error { | |
| 418 | - | var arg0 wl.Object | |
| 419 | - | if buffer != nil { | |
| 420 | - | arg0 = buffer | |
| 421 | - | } | |
| 422 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_image_copy_capture_frame_v1.attach_buffer"}, wl.ArgObject(arg0)); err != nil { | |
| 423 | - | return err | |
| 424 | - | } | |
| 425 | - | return nil | |
| 426 | - | } | |
| 427 | - | ||
| 428 | - | // Apply damage to the buffer which is to be captured next. This request may be sent multiple times to describe a region. The client indicates the accumulated damage since this wl_buffer was last captured. During capture, the compositor will update the buffer with at least the union of the region passed by the client and the region advertised by ext_image_copy_capture_frame_v1.damage. When a wl_buffer is captured for the first time, or when the client doesn't track damage, the client must damage the whole buffer. This is for optimisation purposes. The compositor may use this information to reduce copying. These coordinates originate from the upper left corner of the buffer. If x or y are strictly negative, or if width or height are negative or zero, the invalid_buffer_damage protocol error is raised. This request must not be sent after capture, or else the already_captured protocol error is raised. | |
| 429 | - | func (o *ExtImageCopyCaptureFrame) DamageBuffer(x int32, y int32, width int32, height int32) error { | |
| 430 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "ext_image_copy_capture_frame_v1.damage_buffer"}, wl.ArgInt(x), wl.ArgInt(y), wl.ArgInt(width), wl.ArgInt(height)); err != nil { | |
| 431 | - | return err | |
| 432 | - | } | |
| 433 | - | return nil | |
| 434 | - | } | |
| 435 | - | ||
| 436 | - | // Capture a frame. Unless this is the first successful captured frame performed in this session, the compositor may wait an indefinite amount of time for the source content to change before performing the copy. This request may only be sent once, or else the already_captured protocol error is raised. A buffer must be attached before this request is sent, or else the no_buffer protocol error is raised. | |
| 437 | - | func (o *ExtImageCopyCaptureFrame) Capture() error { | |
| 438 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 3, Name: "ext_image_copy_capture_frame_v1.capture"}); err != nil { | |
| 439 | - | return err | |
| 440 | - | } | |
| 441 | - | return nil | |
| 442 | - | } | |
| 443 | - | ||
| 444 | - | // OnTransform registers a handler for the transform event. | |
| 445 | - | // | |
| 446 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 447 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 448 | - | func (o *ExtImageCopyCaptureFrame) OnTransform(handler func(transform uint32)) { | |
| 449 | - | if handler == nil { | |
| 450 | - | return | |
| 451 | - | } | |
| 452 | - | o.handlersMu.Lock() | |
| 453 | - | defer o.handlersMu.Unlock() | |
| 454 | - | o.onTransform = append(o.onTransform, handler) | |
| 455 | - | } | |
| 456 | - | ||
| 457 | - | // handlersForTransform returns the handlers registered for transform, taken | |
| 458 | - | // under the lock so a handler may register another handler while events are | |
| 459 | - | // being dispatched. | |
| 460 | - | func (o *ExtImageCopyCaptureFrame) handlersForTransform() []func(transform uint32) { | |
| 461 | - | o.handlersMu.Lock() | |
| 462 | - | defer o.handlersMu.Unlock() | |
| 463 | - | return o.onTransform | |
| 464 | - | } | |
| 465 | - | ||
| 466 | - | // OnDamage registers a handler for the damage event. | |
| 467 | - | // | |
| 468 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 469 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 470 | - | func (o *ExtImageCopyCaptureFrame) OnDamage(handler func(x int32, y int32, width int32, height int32)) { | |
| 471 | - | if handler == nil { | |
| 472 | - | return | |
| 473 | - | } | |
| 474 | - | o.handlersMu.Lock() | |
| 475 | - | defer o.handlersMu.Unlock() | |
| 476 | - | o.onDamage = append(o.onDamage, handler) | |
| 477 | - | } | |
| 478 | - | ||
| 479 | - | // handlersForDamage returns the handlers registered for damage, taken | |
| 480 | - | // under the lock so a handler may register another handler while events are | |
| 481 | - | // being dispatched. | |
| 482 | - | func (o *ExtImageCopyCaptureFrame) handlersForDamage() []func(x int32, y int32, width int32, height int32) { | |
| 483 | - | o.handlersMu.Lock() | |
| 484 | - | defer o.handlersMu.Unlock() | |
| 485 | - | return o.onDamage | |
| 486 | - | } | |
| 487 | - | ||
| 488 | - | // OnPresentationTime registers a handler for the presentation_time event. | |
| 489 | - | // | |
| 490 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 491 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 492 | - | func (o *ExtImageCopyCaptureFrame) OnPresentationTime(handler func(tvSecHi uint32, tvSecLo uint32, tvNsec uint32)) { | |
| 493 | - | if handler == nil { | |
| 494 | - | return | |
| 495 | - | } | |
| 496 | - | o.handlersMu.Lock() | |
| 497 | - | defer o.handlersMu.Unlock() | |
| 498 | - | o.onPresentationTime = append(o.onPresentationTime, handler) | |
| 499 | - | } | |
| 500 | - | ||
| 501 | - | // handlersForPresentationTime returns the handlers registered for presentation_time, taken | |
| 502 | - | // under the lock so a handler may register another handler while events are | |
| 503 | - | // being dispatched. | |
| 504 | - | func (o *ExtImageCopyCaptureFrame) handlersForPresentationTime() []func(tvSecHi uint32, tvSecLo uint32, tvNsec uint32) { | |
| 505 | - | o.handlersMu.Lock() | |
| 506 | - | defer o.handlersMu.Unlock() | |
| 507 | - | return o.onPresentationTime | |
| 508 | - | } | |
| 509 | - | ||
| 510 | - | // OnReady registers a handler for the ready event. | |
| 511 | - | // | |
| 512 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 513 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 514 | - | func (o *ExtImageCopyCaptureFrame) OnReady(handler func()) { | |
| 515 | - | if handler == nil { | |
| 516 | - | return | |
| 517 | - | } | |
| 518 | - | o.handlersMu.Lock() | |
| 519 | - | defer o.handlersMu.Unlock() | |
| 520 | - | o.onReady = append(o.onReady, handler) | |
| 521 | - | } | |
| 522 | - | ||
| 523 | - | // handlersForReady returns the handlers registered for ready, taken | |
| 524 | - | // under the lock so a handler may register another handler while events are | |
| 525 | - | // being dispatched. | |
| 526 | - | func (o *ExtImageCopyCaptureFrame) handlersForReady() []func() { | |
| 527 | - | o.handlersMu.Lock() | |
| 528 | - | defer o.handlersMu.Unlock() | |
| 529 | - | return o.onReady | |
| 530 | - | } | |
| 531 | - | ||
| 532 | - | // OnFailed registers a handler for the failed event. | |
| 533 | - | // | |
| 534 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 535 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 536 | - | func (o *ExtImageCopyCaptureFrame) OnFailed(handler func(reason uint32)) { | |
| 537 | - | if handler == nil { | |
| 538 | - | return | |
| 539 | - | } | |
| 540 | - | o.handlersMu.Lock() | |
| 541 | - | defer o.handlersMu.Unlock() | |
| 542 | - | o.onFailed = append(o.onFailed, handler) | |
| 543 | - | } | |
| 544 | - | ||
| 545 | - | // handlersForFailed returns the handlers registered for failed, taken | |
| 546 | - | // under the lock so a handler may register another handler while events are | |
| 547 | - | // being dispatched. | |
| 548 | - | func (o *ExtImageCopyCaptureFrame) handlersForFailed() []func(reason uint32) { | |
| 549 | - | o.handlersMu.Lock() | |
| 550 | - | defer o.handlersMu.Unlock() | |
| 551 | - | return o.onFailed | |
| 552 | - | } | |
| 553 | - | ||
| 554 | - | // EventSignature returns the declared event argument types in wire order. | |
| 555 | - | func (o *ExtImageCopyCaptureFrame) EventSignature(opcode uint16) (string, bool) { | |
| 556 | - | switch opcode { | |
| 557 | - | case 0: | |
| 558 | - | return "uint,", true | |
| 559 | - | case 1: | |
| 560 | - | return "int,int,int,int,", true | |
| 561 | - | case 2: | |
| 562 | - | return "uint,uint,uint,", true | |
| 563 | - | case 3: | |
| 564 | - | return "", true | |
| 565 | - | case 4: | |
| 566 | - | return "uint,", true | |
| 567 | - | default: | |
| 568 | - | return "", false | |
| 569 | - | } | |
| 570 | - | } | |
| 571 | - | ||
| 572 | - | // Dispatch decodes one event on ext_image_copy_capture_frame_v1 and calls the registered handlers. | |
| 573 | - | func (o *ExtImageCopyCaptureFrame) Dispatch(event *wl.Event) { | |
| 574 | - | switch event.Opcode { | |
| 575 | - | case 0: // transform | |
| 576 | - | transform := event.Uint32() | |
| 577 | - | ||
| 578 | - | for i, handler := range o.handlersForTransform() { | |
| 579 | - | _ = i | |
| 580 | - | handler(transform) | |
| 581 | - | } | |
| 582 | - | case 1: // damage | |
| 583 | - | x := event.Int32() | |
| 584 | - | y := event.Int32() | |
| 585 | - | width := event.Int32() | |
| 586 | - | height := event.Int32() | |
| 587 | - | ||
| 588 | - | for i, handler := range o.handlersForDamage() { | |
| 589 | - | _ = i | |
| 590 | - | handler(x, y, width, height) | |
| 591 | - | } | |
| 592 | - | case 2: // presentation_time | |
| 593 | - | tvSecHi := event.Uint32() | |
| 594 | - | tvSecLo := event.Uint32() | |
| 595 | - | tvNsec := event.Uint32() | |
| 596 | - | ||
| 597 | - | for i, handler := range o.handlersForPresentationTime() { | |
| 598 | - | _ = i | |
| 599 | - | handler(tvSecHi, tvSecLo, tvNsec) | |
| 600 | - | } | |
| 601 | - | case 3: // ready | |
| 602 | - | ||
| 603 | - | for i, handler := range o.handlersForReady() { | |
| 604 | - | _ = i | |
| 605 | - | handler() | |
| 606 | - | } | |
| 607 | - | case 4: // failed | |
| 608 | - | reason := event.Uint32() | |
| 609 | - | ||
| 610 | - | for i, handler := range o.handlersForFailed() { | |
| 611 | - | _ = i | |
| 612 | - | handler(reason) | |
| 613 | - | } | |
| 614 | - | default: | |
| 615 | - | } | |
| 616 | - | } | |
| 617 | - | ||
| 618 | - | // ExtImageCopyCaptureCursorSessionInterface is the protocol interface name. | |
| 619 | - | const ExtImageCopyCaptureCursorSessionInterface = "ext_image_copy_capture_cursor_session_v1" | |
| 620 | - | ||
| 621 | - | // ExtImageCopyCaptureCursorSession is the generated binding for ext_image_copy_capture_cursor_session_v1 version 1. | |
| 622 | - | type ExtImageCopyCaptureCursorSession struct { | |
| 623 | - | wl.BaseProxy | |
| 624 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 625 | - | // handlers while another goroutine dispatches events. | |
| 626 | - | handlersMu sync.Mutex | |
| 627 | - | onEnter []func() | |
| 628 | - | onLeave []func() | |
| 629 | - | onPosition []func(x int32, y int32) | |
| 630 | - | onHotspot []func(x int32, y int32) | |
| 631 | - | } | |
| 632 | - | ||
| 633 | - | // NewExtImageCopyCaptureCursorSession returns an unbound ExtImageCopyCaptureCursorSession. | |
| 634 | - | func NewExtImageCopyCaptureCursorSession(ctx *wl.Context) *ExtImageCopyCaptureCursorSession { | |
| 635 | - | obj := &ExtImageCopyCaptureCursorSession{} | |
| 636 | - | obj.SetContext(ctx) | |
| 637 | - | ctx.Register(obj) | |
| 638 | - | return obj | |
| 639 | - | } | |
| 640 | - | ||
| 641 | - | // Destroys the session. This request can be sent at any time by the client. This request doesn't affect ext_image_copy_capture_frame_v1 objects created by this object. | |
| 642 | - | func (o *ExtImageCopyCaptureCursorSession) Destroy() error { | |
| 643 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "ext_image_copy_capture_cursor_session_v1.destroy", Destructor: true}); err != nil { | |
| 644 | - | return err | |
| 645 | - | } | |
| 646 | - | return nil | |
| 647 | - | } | |
| 648 | - | ||
| 649 | - | // Gets the image copy capture session for this cursor session. The session will produce frames of the cursor image. The compositor may pause the session when the cursor leaves the captured area. This request must not be sent more than once, or else the duplicate_session protocol error is raised. | |
| 650 | - | func (o *ExtImageCopyCaptureCursorSession) GetCaptureSession() (*ExtImageCopyCaptureSession, error) { | |
| 651 | - | child := &ExtImageCopyCaptureSession{} | |
| 652 | - | child.SetContext(o.Context()) | |
| 653 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "ext_image_copy_capture_cursor_session_v1.get_capture_session", Child: child}, wl.ArgObject(child)); err != nil { | |
| 654 | - | return nil, err | |
| 655 | - | } | |
| 656 | - | return child, nil | |
| 657 | - | } | |
| 658 | - | ||
| 659 | - | // OnEnter registers a handler for the enter event. | |
| 660 | - | // | |
| 661 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 662 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 663 | - | func (o *ExtImageCopyCaptureCursorSession) OnEnter(handler func()) { | |
| 664 | - | if handler == nil { | |
| 665 | - | return | |
| 666 | - | } | |
| 667 | - | o.handlersMu.Lock() | |
| 668 | - | defer o.handlersMu.Unlock() | |
| 669 | - | o.onEnter = append(o.onEnter, handler) | |
| 670 | - | } | |
| 671 | - | ||
| 672 | - | // handlersForEnter returns the handlers registered for enter, taken | |
| 673 | - | // under the lock so a handler may register another handler while events are | |
| 674 | - | // being dispatched. | |
| 675 | - | func (o *ExtImageCopyCaptureCursorSession) handlersForEnter() []func() { | |
| 676 | - | o.handlersMu.Lock() | |
| 677 | - | defer o.handlersMu.Unlock() | |
| 678 | - | return o.onEnter | |
| 679 | - | } | |
| 680 | - | ||
| 681 | - | // OnLeave registers a handler for the leave event. | |
| 682 | - | // | |
| 683 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 684 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 685 | - | func (o *ExtImageCopyCaptureCursorSession) OnLeave(handler func()) { | |
| 686 | - | if handler == nil { | |
| 687 | - | return | |
| 688 | - | } | |
| 689 | - | o.handlersMu.Lock() | |
| 690 | - | defer o.handlersMu.Unlock() | |
| 691 | - | o.onLeave = append(o.onLeave, handler) | |
| 692 | - | } | |
| 693 | - | ||
| 694 | - | // handlersForLeave returns the handlers registered for leave, taken | |
| 695 | - | // under the lock so a handler may register another handler while events are | |
| 696 | - | // being dispatched. | |
| 697 | - | func (o *ExtImageCopyCaptureCursorSession) handlersForLeave() []func() { | |
| 698 | - | o.handlersMu.Lock() | |
| 699 | - | defer o.handlersMu.Unlock() | |
| 700 | - | return o.onLeave | |
| 701 | - | } | |
| 702 | - | ||
| 703 | - | // OnPosition registers a handler for the position event. | |
| 704 | - | // | |
| 705 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 706 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 707 | - | func (o *ExtImageCopyCaptureCursorSession) OnPosition(handler func(x int32, y int32)) { | |
| 708 | - | if handler == nil { | |
| 709 | - | return | |
| 710 | - | } | |
| 711 | - | o.handlersMu.Lock() | |
| 712 | - | defer o.handlersMu.Unlock() | |
| 713 | - | o.onPosition = append(o.onPosition, handler) | |
| 714 | - | } | |
| 715 | - | ||
| 716 | - | // handlersForPosition returns the handlers registered for position, taken | |
| 717 | - | // under the lock so a handler may register another handler while events are | |
| 718 | - | // being dispatched. | |
| 719 | - | func (o *ExtImageCopyCaptureCursorSession) handlersForPosition() []func(x int32, y int32) { | |
| 720 | - | o.handlersMu.Lock() | |
| 721 | - | defer o.handlersMu.Unlock() | |
| 722 | - | return o.onPosition | |
| 723 | - | } | |
| 724 | - | ||
| 725 | - | // OnHotspot registers a handler for the hotspot event. | |
| 726 | - | // | |
| 727 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 728 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 729 | - | func (o *ExtImageCopyCaptureCursorSession) OnHotspot(handler func(x int32, y int32)) { | |
| 730 | - | if handler == nil { | |
| 731 | - | return | |
| 732 | - | } | |
| 733 | - | o.handlersMu.Lock() | |
| 734 | - | defer o.handlersMu.Unlock() | |
| 735 | - | o.onHotspot = append(o.onHotspot, handler) | |
| 736 | - | } | |
| 737 | - | ||
| 738 | - | // handlersForHotspot returns the handlers registered for hotspot, taken | |
| 739 | - | // under the lock so a handler may register another handler while events are | |
| 740 | - | // being dispatched. | |
| 741 | - | func (o *ExtImageCopyCaptureCursorSession) handlersForHotspot() []func(x int32, y int32) { | |
| 742 | - | o.handlersMu.Lock() | |
| 743 | - | defer o.handlersMu.Unlock() | |
| 744 | - | return o.onHotspot | |
| 745 | - | } | |
| 746 | - | ||
| 747 | - | // EventSignature returns the declared event argument types in wire order. | |
| 748 | - | func (o *ExtImageCopyCaptureCursorSession) EventSignature(opcode uint16) (string, bool) { | |
| 749 | - | switch opcode { | |
| 750 | - | case 0: | |
| 751 | - | return "", true | |
| 752 | - | case 1: | |
| 753 | - | return "", true | |
| 754 | - | case 2: | |
| 755 | - | return "int,int,", true | |
| 756 | - | case 3: | |
| 757 | - | return "int,int,", true | |
| 758 | - | default: | |
| 759 | - | return "", false | |
| 760 | - | } | |
| 761 | - | } | |
| 762 | - | ||
| 763 | - | // Dispatch decodes one event on ext_image_copy_capture_cursor_session_v1 and calls the registered handlers. | |
| 764 | - | func (o *ExtImageCopyCaptureCursorSession) Dispatch(event *wl.Event) { | |
| 765 | - | switch event.Opcode { | |
| 766 | - | case 0: // enter | |
| 767 | - | ||
| 768 | - | for i, handler := range o.handlersForEnter() { | |
| 769 | - | _ = i | |
| 770 | - | handler() | |
| 771 | - | } | |
| 772 | - | case 1: // leave | |
| 773 | - | ||
| 774 | - | for i, handler := range o.handlersForLeave() { | |
| 775 | - | _ = i | |
| 776 | - | handler() | |
| 777 | - | } | |
| 778 | - | case 2: // position | |
| 779 | - | x := event.Int32() | |
| 780 | - | y := event.Int32() | |
| 781 | - | ||
| 782 | - | for i, handler := range o.handlersForPosition() { | |
| 783 | - | _ = i | |
| 784 | - | handler(x, y) | |
| 785 | - | } | |
| 786 | - | case 3: // hotspot | |
| 787 | - | x := event.Int32() | |
| 788 | - | y := event.Int32() | |
| 789 | - | ||
| 790 | - | for i, handler := range o.handlersForHotspot() { | |
| 791 | - | _ = i | |
| 792 | - | handler(x, y) | |
| 793 | - | } | |
| 794 | - | default: | |
| 795 | - | } | |
| 796 | - | } | |
D protocol/imagecopycapture/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package imagecopycapture | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p imagecopycapture -o ext-image-copy-capture-v1_generated.go -import ext_image_capture_source_v1=github.com/bnema/wlturbo/protocol/imagecapturesource -import wl_buffer=github.com/bnema/wlturbo/protocol/core -import wl_pointer=github.com/bnema/wlturbo/protocol/core ext-image-copy-capture-v1.xml | |
D protocol/input_desktop_extensions_test.go +0 -726
| @@ -1,726 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package protocol_test | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "encoding/binary" | |
| 7 | - | "errors" | |
| 8 | - | "os" | |
| 9 | - | "reflect" | |
| 10 | - | "testing" | |
| 11 | - | "time" | |
| 12 | - | ||
| 13 | - | "github.com/bnema/wlturbo" | |
| 14 | - | "github.com/bnema/wlturbo/protocol/datacontrol" | |
| 15 | - | "github.com/bnema/wlturbo/protocol/extforeigntoplevel" | |
| 16 | - | "github.com/bnema/wlturbo/protocol/idleinhibit" | |
| 17 | - | "github.com/bnema/wlturbo/protocol/idlenotify" | |
| 18 | - | "github.com/bnema/wlturbo/protocol/imagecapturesource" | |
| 19 | - | "github.com/bnema/wlturbo/protocol/imagecopycapture" | |
| 20 | - | "github.com/bnema/wlturbo/protocol/pointerconstraints" | |
| 21 | - | "github.com/bnema/wlturbo/protocol/primaryselection" | |
| 22 | - | "github.com/bnema/wlturbo/protocol/relativepointer" | |
| 23 | - | "github.com/bnema/wlturbo/protocol/shortcutsinhibit" | |
| 24 | - | "github.com/bnema/wlturbo/protocol/workspace" | |
| 25 | - | "github.com/bnema/wlturbo/protocol/xdgdecoration" | |
| 26 | - | "github.com/bnema/wlturbo/protocol/xdgoutput" | |
| 27 | - | "github.com/bnema/wlturbo/protocol/xdgshell" | |
| 28 | - | "golang.org/x/sys/unix" | |
| 29 | - | ) | |
| 30 | - | ||
| 31 | - | func TestRelativePointerMotionDecode(t *testing.T) { | |
| 32 | - | s := newWireEnv(t) | |
| 33 | - | ptr := s.pointer() | |
| 34 | - | mgr := relativepointer.NewRelativePointerManager(s.d.Context()) | |
| 35 | - | s.bind(1, relativepointer.RelativePointerManagerInterface, 1, 1, mgr) | |
| 36 | - | rp, e := mgr.GetRelativePointer(ptr) | |
| 37 | - | noerr(t, e) | |
| 38 | - | wantWords(t, "get_relative_pointer", s.req(mgr.ID(), 1), rp.ID(), ptr.ID()) | |
| 39 | - | ||
| 40 | - | type motion struct { | |
| 41 | - | hi, lo uint32 | |
| 42 | - | dx, dy, ux, uy wlturbo.Fixed | |
| 43 | - | } | |
| 44 | - | var got []motion | |
| 45 | - | rp.OnRelativeMotion(func(hi, lo uint32, dx, dy, ux, uy wlturbo.Fixed) { | |
| 46 | - | got = append(got, motion{hi, lo, dx, dy, ux, uy}) | |
| 47 | - | }) | |
| 48 | - | // 64-bit microsecond timestamp split in two words; negative deltas must | |
| 49 | - | // keep their sign through the 24.8 fixed-point decode. | |
| 50 | - | want := motion{1, 0x89abcdef, wlturbo.NewFixed(-1.5), wlturbo.NewFixed(2.25), wlturbo.NewFixed(-3), wlturbo.NewFixed(0.5)} | |
| 51 | - | s.event(rp.ID(), 0, wordBytes(want.hi, want.lo, uint32(want.dx), uint32(want.dy), uint32(want.ux), uint32(want.uy))...) | |
| 52 | - | if len(got) != 1 || got[0] != want { | |
| 53 | - | t.Fatalf("motion %+v, want %+v", got, want) | |
| 54 | - | } | |
| 55 | - | if got[0].dx.Float64() != -1.5 || got[0].dy.Float64() != 2.25 { | |
| 56 | - | t.Fatalf("fixed decode %v %v", got[0].dx.Float64(), got[0].dy.Float64()) | |
| 57 | - | } | |
| 58 | - | // Two handlers are both called, in registration order. | |
| 59 | - | var order []int | |
| 60 | - | rp.OnRelativeMotion(func(_, _ uint32, _, _, _, _ wlturbo.Fixed) { order = append(order, 1) }) | |
| 61 | - | rp.OnRelativeMotion(func(_, _ uint32, _, _, _, _ wlturbo.Fixed) { order = append(order, 2) }) | |
| 62 | - | s.event(rp.ID(), 0, wordBytes(0, 1, 0, 0, 0, 0)...) | |
| 63 | - | if !reflect.DeepEqual(order, []int{1, 2}) || len(got) != 2 { | |
| 64 | - | t.Fatalf("handlers order=%v motions=%d", order, len(got)) | |
| 65 | - | } | |
| 66 | - | noerr(t, rp.Destroy()) | |
| 67 | - | s.req(rp.ID(), 0) | |
| 68 | - | noerr(t, mgr.Destroy()) | |
| 69 | - | s.req(mgr.ID(), 0) | |
| 70 | - | } | |
| 71 | - | ||
| 72 | - | func TestPointerConstraintsNullableRegion(t *testing.T) { | |
| 73 | - | s := newWireEnv(t) | |
| 74 | - | surf, ptr := s.surface(), s.pointer() | |
| 75 | - | pc := pointerconstraints.NewPointerConstraints(s.d.Context()) | |
| 76 | - | s.bind(1, pointerconstraints.PointerConstraintsInterface, 1, 1, pc) | |
| 77 | - | ||
| 78 | - | // A null region means "use the surface input region" and is wire id 0. | |
| 79 | - | lock, e := pc.LockPointer(surf, ptr, nil, pointerconstraints.LIFETIME_PERSISTENT) | |
| 80 | - | noerr(t, e) | |
| 81 | - | wantWords(t, "lock_pointer(nil)", s.req(pc.ID(), 1), lock.ID(), surf.ID(), ptr.ID(), 0, pointerconstraints.LIFETIME_PERSISTENT) | |
| 82 | - | ||
| 83 | - | reg := s.region() | |
| 84 | - | conf, e := pc.ConfinePointer(surf, ptr, reg, pointerconstraints.LIFETIME_ONESHOT) | |
| 85 | - | noerr(t, e) | |
| 86 | - | wantWords(t, "confine_pointer(region)", s.req(pc.ID(), 2), conf.ID(), surf.ID(), ptr.ID(), reg.ID(), pointerconstraints.LIFETIME_ONESHOT) | |
| 87 | - | ||
| 88 | - | noerr(t, lock.SetCursorPositionHint(wlturbo.NewFixed(10.5), wlturbo.NewFixed(-2))) | |
| 89 | - | wantWords(t, "set_cursor_position_hint", s.req(lock.ID(), 1), uint32(wlturbo.NewFixed(10.5)), uint32(wlturbo.NewFixed(-2))) | |
| 90 | - | noerr(t, lock.SetRegion(nil)) | |
| 91 | - | wantWords(t, "locked.set_region(nil)", s.req(lock.ID(), 2), 0) | |
| 92 | - | noerr(t, lock.SetRegion(reg)) | |
| 93 | - | wantWords(t, "locked.set_region", s.req(lock.ID(), 2), reg.ID()) | |
| 94 | - | noerr(t, conf.SetRegion(nil)) | |
| 95 | - | wantWords(t, "confined.set_region(nil)", s.req(conf.ID(), 1), 0) | |
| 96 | - | ||
| 97 | - | var seq []string | |
| 98 | - | lock.OnLocked(func() { seq = append(seq, "locked") }) | |
| 99 | - | lock.OnUnlocked(func() { seq = append(seq, "unlocked") }) | |
| 100 | - | conf.OnConfined(func() { seq = append(seq, "confined") }) | |
| 101 | - | conf.OnUnconfined(func() { seq = append(seq, "unconfined") }) | |
| 102 | - | s.event(lock.ID(), 0) | |
| 103 | - | s.event(lock.ID(), 1) | |
| 104 | - | s.event(conf.ID(), 0) | |
| 105 | - | s.event(conf.ID(), 1) | |
| 106 | - | if !reflect.DeepEqual(seq, []string{"locked", "unlocked", "confined", "unconfined"}) { | |
| 107 | - | t.Fatal(seq) | |
| 108 | - | } | |
| 109 | - | noerr(t, lock.Destroy()) | |
| 110 | - | s.req(lock.ID(), 0) | |
| 111 | - | noerr(t, conf.Destroy()) | |
| 112 | - | s.req(conf.ID(), 0) | |
| 113 | - | noerr(t, pc.Destroy()) | |
| 114 | - | s.req(pc.ID(), 0) | |
| 115 | - | } | |
| 116 | - | ||
| 117 | - | // rawPipe returns a pipe as plain descriptors. An *os.File would close a reused | |
| 118 | - | // descriptor number on Close after the binding already closed the original. | |
| 119 | - | func rawPipe(t *testing.T) (*os.File, int) { | |
| 120 | - | t.Helper() | |
| 121 | - | var fds [2]int | |
| 122 | - | noerr(t, unix.Pipe2(fds[:], unix.O_CLOEXEC)) | |
| 123 | - | r := os.NewFile(uintptr(fds[0]), "pipe-r") | |
| 124 | - | t.Cleanup(func() { r.Close() }) | |
| 125 | - | return r, fds[1] | |
| 126 | - | } | |
| 127 | - | ||
| 128 | - | func TestPrimarySelectionNewIDAndFDOwnership(t *testing.T) { | |
| 129 | - | s := newWireEnv(t) | |
| 130 | - | seat := s.seat() | |
| 131 | - | mgr := primaryselection.NewPrimarySelectionDeviceManager(s.d.Context()) | |
| 132 | - | s.bind(1, primaryselection.PrimarySelectionDeviceManagerInterface, 1, 1, mgr) | |
| 133 | - | dev, e := mgr.GetDevice(seat) | |
| 134 | - | noerr(t, e) | |
| 135 | - | wantWords(t, "get_device", s.req(mgr.ID(), 1), dev.ID(), seat.ID()) | |
| 136 | - | src, e := mgr.CreateSource() | |
| 137 | - | noerr(t, e) | |
| 138 | - | wantWords(t, "create_source", s.req(mgr.ID(), 0), src.ID()) | |
| 139 | - | noerr(t, src.Offer("text/plain")) | |
| 140 | - | s.req(src.ID(), 0) | |
| 141 | - | noerr(t, dev.SetSelection(src, 77)) | |
| 142 | - | wantWords(t, "set_selection", s.req(dev.ID(), 0), src.ID(), 77) | |
| 143 | - | noerr(t, dev.SetSelection(nil, 78)) | |
| 144 | - | wantWords(t, "set_selection(nil)", s.req(dev.ID(), 0), 0, 78) | |
| 145 | - | ||
| 146 | - | // data_offer carries a server-allocated new_id which must come back as a | |
| 147 | - | // typed, registered child inheriting the device version. | |
| 148 | - | var offer *primaryselection.PrimarySelectionOffer | |
| 149 | - | var mimes []string | |
| 150 | - | dev.OnDataOffer(func(o *primaryselection.PrimarySelectionOffer) { | |
| 151 | - | offer = o | |
| 152 | - | o.OnOffer(func(m string) { mimes = append(mimes, m) }) | |
| 153 | - | }) | |
| 154 | - | var selected []uint32 | |
| 155 | - | dev.OnSelection(func(id uint32) { selected = append(selected, id) }) | |
| 156 | - | s.event(dev.ID(), 0, wordBytes(serverID+1)...) | |
| 157 | - | if offer == nil || offer.ID() != serverID+1 || offer.Version() != dev.Version() { | |
| 158 | - | t.Fatalf("offer %+v", offer) | |
| 159 | - | } | |
| 160 | - | s.event(offer.ID(), 0, str("text/plain")...) | |
| 161 | - | s.event(dev.ID(), 1, wordBytes(offer.ID())...) | |
| 162 | - | s.event(dev.ID(), 1, wordBytes(0)...) // null selection | |
| 163 | - | if !reflect.DeepEqual(mimes, []string{"text/plain"}) || !reflect.DeepEqual(selected, []uint32{offer.ID(), 0}) { | |
| 164 | - | t.Fatalf("mimes=%v selected=%v", mimes, selected) | |
| 165 | - | } | |
| 166 | - | ||
| 167 | - | // Client -> compositor: the sent descriptor is duplicated by the kernel and | |
| 168 | - | // the client's copy is closed by the binding. | |
| 169 | - | r, w := rawPipe(t) | |
| 170 | - | noerr(t, offer.Receive("text/plain", w)) | |
| 171 | - | // Check before reading the request: the received duplicate may reuse the | |
| 172 | - | // number of the descriptor the client just closed. | |
| 173 | - | requireFDClosed(t, w) | |
| 174 | - | body, fd := s.reqFD(offer.ID(), 0) | |
| 175 | - | // Closed explicitly below; the guard covers early t.Fatal paths only. | |
| 176 | - | defer func() { | |
| 177 | - | if fd >= 0 { | |
| 178 | - | unix.Close(fd) | |
| 179 | - | } | |
| 180 | - | }() | |
| 181 | - | if len(body) < 4 { | |
| 182 | - | t.Fatalf("receive body %x", body) | |
| 183 | - | } | |
| 184 | - | _, e = unix.Write(fd, []byte("payload")) | |
| 185 | - | noerr(t, e) | |
| 186 | - | noerr(t, unix.Close(fd)) | |
| 187 | - | fd = -1 | |
| 188 | - | buf := make([]byte, 16) | |
| 189 | - | n, e := r.Read(buf) | |
| 190 | - | noerr(t, e) | |
| 191 | - | if string(buf[:n]) != "payload" { | |
| 192 | - | t.Fatalf("payload %q", buf[:n]) | |
| 193 | - | } | |
| 194 | - | ||
| 195 | - | // Compositor -> client: source.send hands over an owned descriptor. | |
| 196 | - | var taken, ignored *wlturbo.OwnedFD | |
| 197 | - | var sendMimes []string | |
| 198 | - | src.OnSend(func(m string, f *wlturbo.OwnedFD) { | |
| 199 | - | sendMimes = append(sendMimes, m) | |
| 200 | - | if taken == nil { | |
| 201 | - | taken = f | |
| 202 | - | n, e := f.Take() | |
| 203 | - | noerr(t, e) | |
| 204 | - | _, e = unix.Write(n, []byte("from-client")) | |
| 205 | - | noerr(t, e) | |
| 206 | - | unix.Close(n) | |
| 207 | - | return | |
| 208 | - | } | |
| 209 | - | ignored = f // deliberately neither taken nor closed | |
| 210 | - | }) | |
| 211 | - | sr, sw, e := os.Pipe() | |
| 212 | - | noerr(t, e) | |
| 213 | - | send(t, s.p, payload(src.ID(), 0, str("text/plain")...), int(sw.Fd())) | |
| 214 | - | s.dispatch() | |
| 215 | - | sw.Close() | |
| 216 | - | n, e = sr.Read(buf) | |
| 217 | - | noerr(t, e) | |
| 218 | - | if string(buf[:n]) != "from-client" { | |
| 219 | - | t.Fatalf("source payload %q", buf[:n]) | |
| 220 | - | } | |
| 221 | - | if _, e := taken.Take(); e == nil { | |
| 222 | - | t.Fatal("second Take on a taken descriptor must fail") | |
| 223 | - | } | |
| 224 | - | sr.Close() | |
| 225 | - | // An unclaimed descriptor is closed by the transport when dispatch ends, | |
| 226 | - | // so the pipe reader sees EOF although the handler never closed it. | |
| 227 | - | pr, pw, e := os.Pipe() | |
| 228 | - | noerr(t, e) | |
| 229 | - | defer pr.Close() | |
| 230 | - | send(t, s.p, payload(src.ID(), 0, str("text/html")...), int(pw.Fd())) | |
| 231 | - | pw.Close() // only the in-flight duplicate keeps the write end alive | |
| 232 | - | s.dispatch() | |
| 233 | - | if ignored == nil || len(sendMimes) != 2 { | |
| 234 | - | t.Fatalf("send events %v", sendMimes) | |
| 235 | - | } | |
| 236 | - | if _, e := ignored.Take(); e == nil { | |
| 237 | - | t.Fatal("unclaimed descriptor must be closed after dispatch, but Take succeeded") | |
| 238 | - | } | |
| 239 | - | pr.SetReadDeadline(time.Now().Add(2 * time.Second)) | |
| 240 | - | if n, e := pr.Read(buf); n != 0 || e == nil { | |
| 241 | - | t.Fatalf("unclaimed descriptor still open: n=%d err=%v", n, e) | |
| 242 | - | } | |
| 243 | - | var cancelled bool | |
| 244 | - | src.OnCancelled(func() { cancelled = true }) | |
| 245 | - | s.event(src.ID(), 1) | |
| 246 | - | if !cancelled { | |
| 247 | - | t.Fatal("cancelled not delivered") | |
| 248 | - | } | |
| 249 | - | noerr(t, offer.Destroy()) | |
| 250 | - | s.req(offer.ID(), 1) | |
| 251 | - | noerr(t, src.Destroy()) | |
| 252 | - | s.req(src.ID(), 1) | |
| 253 | - | noerr(t, dev.Destroy()) | |
| 254 | - | s.req(dev.ID(), 1) | |
| 255 | - | noerr(t, mgr.Destroy()) | |
| 256 | - | s.req(mgr.ID(), 2) | |
| 257 | - | } | |
| 258 | - | ||
| 259 | - | func TestDataControlNewIDAndFDOwnership(t *testing.T) { | |
| 260 | - | s := newWireEnv(t) | |
| 261 | - | seat := s.seat() | |
| 262 | - | mgr := datacontrol.NewExtDataControlManager(s.d.Context()) | |
| 263 | - | s.bind(1, datacontrol.ExtDataControlManagerInterface, 1, 1, mgr) | |
| 264 | - | dev, e := mgr.GetDataDevice(seat) | |
| 265 | - | noerr(t, e) | |
| 266 | - | wantWords(t, "get_data_device", s.req(mgr.ID(), 1), dev.ID(), seat.ID()) | |
| 267 | - | src, e := mgr.CreateDataSource() | |
| 268 | - | noerr(t, e) | |
| 269 | - | wantWords(t, "create_data_source", s.req(mgr.ID(), 0), src.ID()) | |
| 270 | - | noerr(t, dev.SetSelection(src)) | |
| 271 | - | wantWords(t, "set_selection", s.req(dev.ID(), 0), src.ID()) | |
| 272 | - | noerr(t, dev.SetPrimarySelection(nil)) | |
| 273 | - | wantWords(t, "set_primary_selection(nil)", s.req(dev.ID(), 2), 0) | |
| 274 | - | ||
| 275 | - | var offers []*datacontrol.ExtDataControlOffer | |
| 276 | - | dev.OnDataOffer(func(o *datacontrol.ExtDataControlOffer) { offers = append(offers, o) }) | |
| 277 | - | var sel, primary []uint32 | |
| 278 | - | dev.OnSelection(func(id uint32) { sel = append(sel, id) }) | |
| 279 | - | dev.OnPrimarySelection(func(id uint32) { primary = append(primary, id) }) | |
| 280 | - | var finished bool | |
| 281 | - | dev.OnFinished(func() { finished = true }) | |
| 282 | - | s.event(dev.ID(), 0, wordBytes(serverID+1)...) | |
| 283 | - | s.event(dev.ID(), 0, wordBytes(serverID+2)...) | |
| 284 | - | if len(offers) != 2 || offers[0].ID() != serverID+1 || offers[1].ID() != serverID+2 { | |
| 285 | - | t.Fatalf("offers %+v", offers) | |
| 286 | - | } | |
| 287 | - | s.event(dev.ID(), 1, wordBytes(serverID+1)...) | |
| 288 | - | s.event(dev.ID(), 3, wordBytes(serverID+2)...) | |
| 289 | - | s.event(dev.ID(), 3, wordBytes(0)...) | |
| 290 | - | if !reflect.DeepEqual(sel, []uint32{serverID + 1}) || !reflect.DeepEqual(primary, []uint32{serverID + 2, 0}) { | |
| 291 | - | t.Fatalf("sel=%v primary=%v", sel, primary) | |
| 292 | - | } | |
| 293 | - | var mime string | |
| 294 | - | offers[0].OnOffer(func(m string) { mime = m }) | |
| 295 | - | s.event(offers[0].ID(), 0, str("text/uri-list")...) | |
| 296 | - | if mime != "text/uri-list" { | |
| 297 | - | t.Fatal(mime) | |
| 298 | - | } | |
| 299 | - | ||
| 300 | - | r, w := rawPipe(t) | |
| 301 | - | noerr(t, offers[0].Receive("text/uri-list", w)) | |
| 302 | - | requireFDClosed(t, w) | |
| 303 | - | _, fd := s.reqFD(offers[0].ID(), 0) | |
| 304 | - | unix.Close(fd) | |
| 305 | - | buf := make([]byte, 8) | |
| 306 | - | if n, e := r.Read(buf); n != 0 || e == nil { | |
| 307 | - | t.Fatalf("expected EOF once both write ends closed, n=%d err=%v", n, e) | |
| 308 | - | } | |
| 309 | - | ||
| 310 | - | // source.send: the handler owns the descriptor and can Close it early. | |
| 311 | - | var closedByHandler bool | |
| 312 | - | src.OnSend(func(m string, f *wlturbo.OwnedFD) { | |
| 313 | - | noerr(t, f.Close()) | |
| 314 | - | noerr(t, f.Close()) // idempotent | |
| 315 | - | if _, e := f.Take(); e == nil { | |
| 316 | - | t.Error("Take after Close must fail") | |
| 317 | - | } | |
| 318 | - | closedByHandler = true | |
| 319 | - | }) | |
| 320 | - | pr, pw, e := os.Pipe() | |
| 321 | - | noerr(t, e) | |
| 322 | - | defer pr.Close() | |
| 323 | - | send(t, s.p, payload(src.ID(), 0, str("text/plain")...), int(pw.Fd())) | |
| 324 | - | pw.Close() | |
| 325 | - | s.dispatch() | |
| 326 | - | pr.SetReadDeadline(time.Now().Add(2 * time.Second)) | |
| 327 | - | if n, e := pr.Read(buf); !closedByHandler || n != 0 || e == nil { | |
| 328 | - | t.Fatalf("closed=%v n=%d err=%v", closedByHandler, n, e) | |
| 329 | - | } | |
| 330 | - | s.event(dev.ID(), 2) | |
| 331 | - | if !finished { | |
| 332 | - | t.Fatal("finished not delivered") | |
| 333 | - | } | |
| 334 | - | noerr(t, src.Offer("text/plain")) | |
| 335 | - | s.req(src.ID(), 0) | |
| 336 | - | noerr(t, offers[0].Destroy()) | |
| 337 | - | s.req(offers[0].ID(), 1) | |
| 338 | - | noerr(t, src.Destroy()) | |
| 339 | - | s.req(src.ID(), 1) | |
| 340 | - | noerr(t, dev.Destroy()) | |
| 341 | - | s.req(dev.ID(), 1) | |
| 342 | - | noerr(t, mgr.Destroy()) | |
| 343 | - | s.req(mgr.ID(), 2) | |
| 344 | - | } | |
| 345 | - | ||
| 346 | - | func TestWorkspaceLifecycle(t *testing.T) { | |
| 347 | - | s := newWireEnv(t) | |
| 348 | - | out := s.output() | |
| 349 | - | mgr := workspace.NewExtWorkspaceManager(s.d.Context()) | |
| 350 | - | s.bind(1, workspace.ExtWorkspaceManagerInterface, 1, 1, mgr) | |
| 351 | - | ||
| 352 | - | var groups []*workspace.ExtWorkspaceGroupHandle | |
| 353 | - | var spaces []*workspace.ExtWorkspaceHandle | |
| 354 | - | var log []string | |
| 355 | - | mgr.OnWorkspaceGroup(func(g *workspace.ExtWorkspaceGroupHandle) { groups = append(groups, g) }) | |
| 356 | - | mgr.OnWorkspace(func(w *workspace.ExtWorkspaceHandle) { spaces = append(spaces, w) }) | |
| 357 | - | mgr.OnDone(func() { log = append(log, "done") }) | |
| 358 | - | mgr.OnFinished(func() { log = append(log, "finished") }) | |
| 359 | - | ||
| 360 | - | s.event(mgr.ID(), 0, wordBytes(serverID+1)...) | |
| 361 | - | s.event(mgr.ID(), 1, wordBytes(serverID+2)...) | |
| 362 | - | if len(groups) != 1 || len(spaces) != 1 || groups[0].ID() != serverID+1 || spaces[0].ID() != serverID+2 { | |
| 363 | - | t.Fatal("typed children missing") | |
| 364 | - | } | |
| 365 | - | g, w := groups[0], spaces[0] | |
| 366 | - | var gcaps, wcaps, state uint32 | |
| 367 | - | var outs, entered []uint32 | |
| 368 | - | var id, name string | |
| 369 | - | var coords []byte | |
| 370 | - | g.OnCapabilities(func(c uint32) { gcaps = c }) | |
| 371 | - | g.OnOutputEnter(func(o uint32) { outs = append(outs, o) }) | |
| 372 | - | g.OnWorkspaceEnter(func(x uint32) { entered = append(entered, x) }) | |
| 373 | - | g.OnRemoved(func() { log = append(log, "group-removed") }) | |
| 374 | - | w.OnId(func(v string) { id = v }) | |
| 375 | - | w.OnName(func(v string) { name = v }) | |
| 376 | - | w.OnCoordinates(func(c []byte) { coords = c }) | |
| 377 | - | w.OnState(func(v uint32) { state = v }) | |
| 378 | - | w.OnCapabilities(func(v uint32) { wcaps = v }) | |
| 379 | - | w.OnRemoved(func() { log = append(log, "workspace-removed") }) | |
| 380 | - | ||
| 381 | - | s.event(g.ID(), 0, wordBytes(workspace.GROUP_CAPABILITIES_CREATE_WORKSPACE)...) | |
| 382 | - | s.event(g.ID(), 1, wordBytes(out.ID())...) | |
| 383 | - | s.event(g.ID(), 3, wordBytes(w.ID())...) | |
| 384 | - | s.event(w.ID(), 0, str("ws-1")...) | |
| 385 | - | s.event(w.ID(), 1, str("Workspace é")...) | |
| 386 | - | s.event(w.ID(), 2, arr(wordBytes(1, 2))...) | |
| 387 | - | s.event(w.ID(), 3, wordBytes(workspace.STATE_ACTIVE|workspace.STATE_URGENT)...) | |
| 388 | - | s.event(w.ID(), 4, wordBytes(workspace.WORKSPACE_CAPABILITIES_ACTIVATE|workspace.WORKSPACE_CAPABILITIES_ASSIGN)...) | |
| 389 | - | s.event(mgr.ID(), 2) | |
| 390 | - | if gcaps != workspace.GROUP_CAPABILITIES_CREATE_WORKSPACE || !reflect.DeepEqual(outs, []uint32{out.ID()}) || !reflect.DeepEqual(entered, []uint32{w.ID()}) || | |
| 391 | - | id != "ws-1" || name != "Workspace é" || !reflect.DeepEqual(decodeWords(coords), []uint32{1, 2}) || | |
| 392 | - | state != 3 || wcaps != 9 || !reflect.DeepEqual(log, []string{"done"}) { | |
| 393 | - | t.Fatalf("state gcaps=%d outs=%v entered=%v id=%q name=%q coords=%v state=%d wcaps=%d log=%v", gcaps, outs, entered, id, name, coords, state, wcaps, log) | |
| 394 | - | } | |
| 395 | - | ||
| 396 | - | // Requests are only transactional after commit, so the wire order is | |
| 397 | - | // request, request, commit. | |
| 398 | - | noerr(t, w.Activate()) | |
| 399 | - | s.req(w.ID(), 1) | |
| 400 | - | noerr(t, w.Assign(g)) | |
| 401 | - | wantWords(t, "assign", s.req(w.ID(), 3), g.ID()) | |
| 402 | - | noerr(t, g.CreateWorkspace("new")) | |
| 403 | - | if b := s.req(g.ID(), 0); binary.NativeEndian.Uint32(b) != 4 || string(b[4:7]) != "new" { | |
| 404 | - | t.Fatalf("create_workspace %x", b) | |
| 405 | - | } | |
| 406 | - | noerr(t, w.Deactivate()) | |
| 407 | - | s.req(w.ID(), 2) | |
| 408 | - | noerr(t, w.Remove()) | |
| 409 | - | s.req(w.ID(), 4) | |
| 410 | - | noerr(t, mgr.Commit()) | |
| 411 | - | s.req(mgr.ID(), 0) | |
| 412 | - | ||
| 413 | - | // Removal: the compositor sends removed, the client answers with destroy. | |
| 414 | - | s.event(w.ID(), 5) | |
| 415 | - | s.event(g.ID(), 5) | |
| 416 | - | noerr(t, w.Destroy()) | |
| 417 | - | s.req(w.ID(), 0) | |
| 418 | - | noerr(t, g.Destroy()) | |
| 419 | - | s.req(g.ID(), 1) | |
| 420 | - | // stop is answered by finished, which is the final event. | |
| 421 | - | noerr(t, mgr.Stop()) | |
| 422 | - | s.req(mgr.ID(), 1) | |
| 423 | - | s.event(mgr.ID(), 3) | |
| 424 | - | if !reflect.DeepEqual(log, []string{"done", "workspace-removed", "group-removed", "finished"}) { | |
| 425 | - | t.Fatal(log) | |
| 426 | - | } | |
| 427 | - | // finished is a destructor event: the manager is dead and must not | |
| 428 | - | // reach the compositor any more. | |
| 429 | - | if e := mgr.Commit(); e == nil { | |
| 430 | - | t.Fatal("Commit after finished must fail") | |
| 431 | - | } | |
| 432 | - | s.noRequest() | |
| 433 | - | } | |
| 434 | - | ||
| 435 | - | func TestIdleNotifyVersionGate(t *testing.T) { | |
| 436 | - | s := newWireEnv(t) | |
| 437 | - | seat := s.seat() | |
| 438 | - | old := idlenotify.NewExtIdleNotifier(s.d.Context()) | |
| 439 | - | s.bind(1, idlenotify.ExtIdleNotifierInterface, 2, 1, old) // negotiated v1 | |
| 440 | - | if _, e := old.GetInputIdleNotification(1000, seat); !errors.Is(e, wlturbo.ErrVersionTooLow) { | |
| 441 | - | t.Fatalf("v1 get_input_idle_notification = %v, want ErrVersionTooLow", e) | |
| 442 | - | } | |
| 443 | - | s.noRequest() // refused locally, nothing reaches the compositor | |
| 444 | - | n, e := old.GetIdleNotification(1000, seat) | |
| 445 | - | noerr(t, e) | |
| 446 | - | wantWords(t, "get_idle_notification", s.req(old.ID(), 1), n.ID(), 1000, seat.ID()) | |
| 447 | - | ||
| 448 | - | send(t, s.p, msg(s.d.Registry().ID(), 1, 1)) // global_remove for the v1 bind | |
| 449 | - | s.dispatch() | |
| 450 | - | cur := idlenotify.NewExtIdleNotifier(s.d.Context()) | |
| 451 | - | s.bind(2, idlenotify.ExtIdleNotifierInterface, 2, 2, cur) | |
| 452 | - | in, e := cur.GetInputIdleNotification(0, seat) // zero timeout is valid | |
| 453 | - | noerr(t, e) | |
| 454 | - | wantWords(t, "get_input_idle_notification", s.req(cur.ID(), 2), in.ID(), 0, seat.ID()) | |
| 455 | - | var seq []string | |
| 456 | - | in.OnIdled(func() { seq = append(seq, "idled") }) | |
| 457 | - | in.OnResumed(func() { seq = append(seq, "resumed") }) | |
| 458 | - | s.event(in.ID(), 0) | |
| 459 | - | s.event(in.ID(), 1) | |
| 460 | - | if !reflect.DeepEqual(seq, []string{"idled", "resumed"}) { | |
| 461 | - | t.Fatal(seq) | |
| 462 | - | } | |
| 463 | - | noerr(t, in.Destroy()) | |
| 464 | - | s.req(in.ID(), 0) | |
| 465 | - | noerr(t, n.Destroy()) | |
| 466 | - | s.req(n.ID(), 0) | |
| 467 | - | } | |
| 468 | - | ||
| 469 | - | func TestInhibitAndDesktopHintsWire(t *testing.T) { | |
| 470 | - | s := newWireEnv(t) | |
| 471 | - | surf, seat, out := s.surface(), s.seat(), s.output() | |
| 472 | - | ||
| 473 | - | ii := idleinhibit.NewIdleInhibitManager(s.d.Context()) | |
| 474 | - | s.bind(1, idleinhibit.IdleInhibitManagerInterface, 1, 1, ii) | |
| 475 | - | inh, e := ii.CreateInhibitor(surf) | |
| 476 | - | noerr(t, e) | |
| 477 | - | wantWords(t, "create_inhibitor", s.req(ii.ID(), 1), inh.ID(), surf.ID()) | |
| 478 | - | noerr(t, inh.Destroy()) | |
| 479 | - | s.req(inh.ID(), 0) | |
| 480 | - | noerr(t, ii.Destroy()) | |
| 481 | - | s.req(ii.ID(), 0) | |
| 482 | - | ||
| 483 | - | ks := shortcutsinhibit.NewKeyboardShortcutsInhibitManager(s.d.Context()) | |
| 484 | - | s.bind(2, shortcutsinhibit.KeyboardShortcutsInhibitManagerInterface, 1, 1, ks) | |
| 485 | - | k, e := ks.InhibitShortcuts(surf, seat) | |
| 486 | - | noerr(t, e) | |
| 487 | - | wantWords(t, "inhibit_shortcuts", s.req(ks.ID(), 1), k.ID(), surf.ID(), seat.ID()) | |
| 488 | - | var seq []string | |
| 489 | - | k.OnActive(func() { seq = append(seq, "active") }) | |
| 490 | - | k.OnInactive(func() { seq = append(seq, "inactive") }) | |
| 491 | - | s.event(k.ID(), 0) | |
| 492 | - | s.event(k.ID(), 1) | |
| 493 | - | if !reflect.DeepEqual(seq, []string{"active", "inactive"}) { | |
| 494 | - | t.Fatal(seq) | |
| 495 | - | } | |
| 496 | - | noerr(t, k.Destroy()) | |
| 497 | - | s.req(k.ID(), 0) | |
| 498 | - | noerr(t, ks.Destroy()) | |
| 499 | - | s.req(ks.ID(), 0) | |
| 500 | - | ||
| 501 | - | xo := xdgoutput.NewZxdgOutputManager(s.d.Context()) | |
| 502 | - | s.bind(3, xdgoutput.ZxdgOutputManagerInterface, 3, 3, xo) | |
| 503 | - | o, e := xo.GetXdgOutput(out) | |
| 504 | - | noerr(t, e) | |
| 505 | - | wantWords(t, "get_xdg_output", s.req(xo.ID(), 1), o.ID(), out.ID()) | |
| 506 | - | var pos, size [2]int32 | |
| 507 | - | var name string | |
| 508 | - | o.OnLogicalPosition(func(x, y int32) { pos = [2]int32{x, y} }) | |
| 509 | - | o.OnLogicalSize(func(w, h int32) { size = [2]int32{w, h} }) | |
| 510 | - | o.OnName(func(n string) { name = n }) | |
| 511 | - | s.event(o.ID(), 0, wordBytes(uint32(0xfffffff6), 20)...) // -10, 20 | |
| 512 | - | s.event(o.ID(), 1, wordBytes(1920, 1080)...) | |
| 513 | - | s.event(o.ID(), 3, str("DP-1")...) | |
| 514 | - | if pos != [2]int32{-10, 20} || size != [2]int32{1920, 1080} || name != "DP-1" { | |
| 515 | - | t.Fatal(pos, size, name) | |
| 516 | - | } | |
| 517 | - | noerr(t, o.Destroy()) | |
| 518 | - | s.req(o.ID(), 0) | |
| 519 | - | noerr(t, xo.Destroy()) | |
| 520 | - | s.req(xo.ID(), 0) | |
| 521 | - | } | |
| 522 | - | ||
| 523 | - | func TestXdgDecorationCrossPackageToplevel(t *testing.T) { | |
| 524 | - | s := newWireEnv(t) | |
| 525 | - | surf := s.surface() | |
| 526 | - | wm := xdgshell.NewXdgWmBase(s.d.Context()) | |
| 527 | - | s.bind(1, xdgshell.XdgWmBaseInterface, 6, 6, wm) | |
| 528 | - | xs, e := wm.GetXdgSurface(surf) | |
| 529 | - | noerr(t, e) | |
| 530 | - | s.req(wm.ID(), 2) | |
| 531 | - | top, e := xs.GetToplevel() | |
| 532 | - | noerr(t, e) | |
| 533 | - | s.req(xs.ID(), 1) | |
| 534 | - | ||
| 535 | - | dm := xdgdecoration.NewZxdgDecorationManager(s.d.Context()) | |
| 536 | - | s.bind(2, xdgdecoration.ZxdgDecorationManagerInterface, 2, 2, dm) | |
| 537 | - | dec, e := dm.GetToplevelDecoration(top) | |
| 538 | - | noerr(t, e) | |
| 539 | - | wantWords(t, "get_toplevel_decoration", s.req(dm.ID(), 1), dec.ID(), top.ID()) | |
| 540 | - | noerr(t, dec.SetMode(xdgdecoration.MODE_SERVER_SIDE)) | |
| 541 | - | wantWords(t, "set_mode", s.req(dec.ID(), 1), xdgdecoration.MODE_SERVER_SIDE) | |
| 542 | - | var modes []uint32 | |
| 543 | - | dec.OnConfigure(func(m uint32) { modes = append(modes, m) }) | |
| 544 | - | s.event(dec.ID(), 0, wordBytes(xdgdecoration.MODE_CLIENT_SIDE)...) | |
| 545 | - | if !reflect.DeepEqual(modes, []uint32{xdgdecoration.MODE_CLIENT_SIDE}) { | |
| 546 | - | t.Fatal(modes) | |
| 547 | - | } | |
| 548 | - | noerr(t, dec.UnsetMode()) | |
| 549 | - | s.req(dec.ID(), 2) | |
| 550 | - | noerr(t, dec.Destroy()) | |
| 551 | - | s.req(dec.ID(), 0) | |
| 552 | - | noerr(t, dm.Destroy()) | |
| 553 | - | s.req(dm.ID(), 0) | |
| 554 | - | } | |
| 555 | - | ||
| 556 | - | func TestImageCaptureCrossPackageChildren(t *testing.T) { | |
| 557 | - | s := newWireEnv(t) | |
| 558 | - | out, ptr := s.output(), s.pointer() | |
| 559 | - | ||
| 560 | - | // Foreign toplevel handles come from ext-foreign-toplevel-list and are | |
| 561 | - | // consumed by a different package (imagecapturesource). | |
| 562 | - | list := extforeigntoplevel.NewExtForeignToplevelList(s.d.Context()) | |
| 563 | - | s.bind(1, extforeigntoplevel.ExtForeignToplevelListInterface, 1, 1, list) | |
| 564 | - | var handle *extforeigntoplevel.ExtForeignToplevelHandle | |
| 565 | - | list.OnToplevel(func(h *extforeigntoplevel.ExtForeignToplevelHandle) { handle = h }) | |
| 566 | - | s.event(list.ID(), 0, wordBytes(serverID+1)...) | |
| 567 | - | if handle == nil || handle.ID() != serverID+1 { | |
| 568 | - | t.Fatal("toplevel handle missing") | |
| 569 | - | } | |
| 570 | - | var title, appID, ident string | |
| 571 | - | handle.OnTitle(func(v string) { title = v }) | |
| 572 | - | handle.OnAppId(func(v string) { appID = v }) | |
| 573 | - | handle.OnIdentifier(func(v string) { ident = v }) | |
| 574 | - | s.event(handle.ID(), 2, str("term")...) | |
| 575 | - | s.event(handle.ID(), 3, str("org.example.term")...) | |
| 576 | - | s.event(handle.ID(), 4, str("id-1")...) | |
| 577 | - | if title != "term" || appID != "org.example.term" || ident != "id-1" { | |
| 578 | - | t.Fatal(title, appID, ident) | |
| 579 | - | } | |
| 580 | - | ||
| 581 | - | om := imagecapturesource.NewExtOutputImageCaptureSourceManager(s.d.Context()) | |
| 582 | - | s.bind(2, imagecapturesource.ExtOutputImageCaptureSourceManagerInterface, 1, 1, om) | |
| 583 | - | fm := imagecapturesource.NewExtForeignToplevelImageCaptureSourceManager(s.d.Context()) | |
| 584 | - | s.bind(3, imagecapturesource.ExtForeignToplevelImageCaptureSourceManagerInterface, 1, 1, fm) | |
| 585 | - | outSrc, e := om.CreateSource(out) | |
| 586 | - | noerr(t, e) | |
| 587 | - | wantWords(t, "output create_source", s.req(om.ID(), 0), outSrc.ID(), out.ID()) | |
| 588 | - | topSrc, e := fm.CreateSource(handle) | |
| 589 | - | noerr(t, e) | |
| 590 | - | wantWords(t, "toplevel create_source", s.req(fm.ID(), 0), topSrc.ID(), handle.ID()) | |
| 591 | - | ||
| 592 | - | cm := imagecopycapture.NewExtImageCopyCaptureManager(s.d.Context()) | |
| 593 | - | s.bind(4, imagecopycapture.ExtImageCopyCaptureManagerInterface, 1, 1, cm) | |
| 594 | - | sess, e := cm.CreateSession(topSrc, imagecopycapture.OPTIONS_PAINT_CURSORS) | |
| 595 | - | noerr(t, e) | |
| 596 | - | wantWords(t, "create_session", s.req(cm.ID(), 0), sess.ID(), topSrc.ID(), imagecopycapture.OPTIONS_PAINT_CURSORS) | |
| 597 | - | cur, e := cm.CreatePointerCursorSession(outSrc, ptr) | |
| 598 | - | noerr(t, e) | |
| 599 | - | wantWords(t, "create_pointer_cursor_session", s.req(cm.ID(), 1), cur.ID(), outSrc.ID(), ptr.ID()) | |
| 600 | - | ||
| 601 | - | // Session constraints: advertised before done, arrays decoded. | |
| 602 | - | var log []string | |
| 603 | - | var size [2]uint32 | |
| 604 | - | var dev []byte | |
| 605 | - | var dmaFormat uint32 | |
| 606 | - | var mods []byte | |
| 607 | - | sess.OnBufferSize(func(w, h uint32) { size = [2]uint32{w, h}; log = append(log, "size") }) | |
| 608 | - | var shm []uint32 | |
| 609 | - | sess.OnShmFormat(func(f uint32) { shm = append(shm, f); log = append(log, "shm") }) | |
| 610 | - | sess.OnDmabufDevice(func(d []byte) { dev = d; log = append(log, "dev") }) | |
| 611 | - | sess.OnDmabufFormat(func(f uint32, m []byte) { dmaFormat, mods = f, m; log = append(log, "dmabuf") }) | |
| 612 | - | sess.OnDone(func() { log = append(log, "done") }) | |
| 613 | - | sess.OnStopped(func() { log = append(log, "stopped") }) | |
| 614 | - | s.event(sess.ID(), 0, wordBytes(1280, 720)...) | |
| 615 | - | s.event(sess.ID(), 1, wordBytes(1)...) // wl_shm.format xrgb8888 | |
| 616 | - | s.event(sess.ID(), 2, arr(make([]byte, 8))...) | |
| 617 | - | s.event(sess.ID(), 3, cat(wordBytes(0x34325258), arr(wordBytes(0, 0, 1, 0)))...) | |
| 618 | - | s.event(sess.ID(), 4) | |
| 619 | - | if !reflect.DeepEqual(shm, []uint32{1}) { | |
| 620 | - | t.Fatalf("shm formats %v", shm) | |
| 621 | - | } | |
| 622 | - | if size != [2]uint32{1280, 720} || len(dev) != 8 || dmaFormat != 0x34325258 || len(mods) != 16 || | |
| 623 | - | !reflect.DeepEqual(log, []string{"size", "shm", "dev", "dmabuf", "done"}) { | |
| 624 | - | t.Fatal(size, dev, dmaFormat, mods, log) | |
| 625 | - | } | |
| 626 | - | ||
| 627 | - | frame, e := sess.CreateFrame() | |
| 628 | - | noerr(t, e) | |
| 629 | - | wantWords(t, "create_frame", s.req(sess.ID(), 0), frame.ID()) | |
| 630 | - | buf := s.buffer() | |
| 631 | - | noerr(t, frame.AttachBuffer(buf)) | |
| 632 | - | wantWords(t, "attach_buffer", s.req(frame.ID(), 1), buf.ID()) | |
| 633 | - | noerr(t, frame.DamageBuffer(0, 0, 1280, 720)) | |
| 634 | - | wantWords(t, "damage_buffer", s.req(frame.ID(), 2), 0, 0, 1280, 720) | |
| 635 | - | noerr(t, frame.Capture()) | |
| 636 | - | s.req(frame.ID(), 3) | |
| 637 | - | ||
| 638 | - | var fl []string | |
| 639 | - | var damage [4]int32 | |
| 640 | - | var tv [3]uint32 | |
| 641 | - | frame.OnTransform(func(v uint32) { fl = append(fl, "transform") }) | |
| 642 | - | frame.OnDamage(func(x, y, w, h int32) { damage = [4]int32{x, y, w, h}; fl = append(fl, "damage") }) | |
| 643 | - | frame.OnPresentationTime(func(hi, lo, ns uint32) { tv = [3]uint32{hi, lo, ns}; fl = append(fl, "time") }) | |
| 644 | - | frame.OnReady(func() { fl = append(fl, "ready") }) | |
| 645 | - | frame.OnFailed(func(uint32) { fl = append(fl, "failed") }) | |
| 646 | - | s.event(frame.ID(), 0, wordBytes(0)...) | |
| 647 | - | s.event(frame.ID(), 1, wordBytes(1, 2, 3, 4)...) | |
| 648 | - | s.event(frame.ID(), 2, wordBytes(0, 1700000000, 999)...) | |
| 649 | - | s.event(frame.ID(), 3) | |
| 650 | - | if damage != [4]int32{1, 2, 3, 4} || tv != [3]uint32{0, 1700000000, 999} || | |
| 651 | - | !reflect.DeepEqual(fl, []string{"transform", "damage", "time", "ready"}) { | |
| 652 | - | t.Fatal(damage, tv, fl) | |
| 653 | - | } | |
| 654 | - | // ready is terminal for a frame, and a session allows one frame at a time | |
| 655 | - | // even after ready, so destroy it before creating the frame that fails. | |
| 656 | - | noerr(t, frame.Destroy()) | |
| 657 | - | s.req(frame.ID(), 0) | |
| 658 | - | failing, e := sess.CreateFrame() | |
| 659 | - | noerr(t, e) | |
| 660 | - | wantWords(t, "create_frame(2)", s.req(sess.ID(), 0), failing.ID()) | |
| 661 | - | noerr(t, failing.AttachBuffer(buf)) | |
| 662 | - | s.req(failing.ID(), 1) | |
| 663 | - | noerr(t, failing.Capture()) | |
| 664 | - | s.req(failing.ID(), 3) | |
| 665 | - | var reasons []uint32 | |
| 666 | - | failing.OnReady(func() { t.Error("failed frame must not become ready") }) | |
| 667 | - | failing.OnFailed(func(r uint32) { reasons = append(reasons, r) }) | |
| 668 | - | s.event(failing.ID(), 4, wordBytes(imagecopycapture.FAILURE_REASON_BUFFER_CONSTRAINTS)...) | |
| 669 | - | if !reflect.DeepEqual(reasons, []uint32{imagecopycapture.FAILURE_REASON_BUFFER_CONSTRAINTS}) { | |
| 670 | - | t.Fatal(reasons) | |
| 671 | - | } | |
| 672 | - | ||
| 673 | - | // Cursor session: get_capture_session is a typed child too. | |
| 674 | - | var cl []string | |
| 675 | - | var pos, hot [2]int32 | |
| 676 | - | cur.OnEnter(func() { cl = append(cl, "enter") }) | |
| 677 | - | cur.OnLeave(func() { cl = append(cl, "leave") }) | |
| 678 | - | cur.OnPosition(func(x, y int32) { pos = [2]int32{x, y} }) | |
| 679 | - | cur.OnHotspot(func(x, y int32) { hot = [2]int32{x, y} }) | |
| 680 | - | s.event(cur.ID(), 0) | |
| 681 | - | s.event(cur.ID(), 2, wordBytes(uint32(0xfffffffb), 9)...) // -5, 9 | |
| 682 | - | s.event(cur.ID(), 3, wordBytes(4, 6)...) | |
| 683 | - | s.event(cur.ID(), 1) | |
| 684 | - | if pos != [2]int32{-5, 9} || hot != [2]int32{4, 6} || !reflect.DeepEqual(cl, []string{"enter", "leave"}) { | |
| 685 | - | t.Fatal(pos, hot, cl) | |
| 686 | - | } | |
| 687 | - | csess, e := cur.GetCaptureSession() | |
| 688 | - | noerr(t, e) | |
| 689 | - | wantWords(t, "get_capture_session", s.req(cur.ID(), 1), csess.ID()) | |
| 690 | - | if csess.Version() != cur.Version() { | |
| 691 | - | t.Fatalf("child version %d, parent %d", csess.Version(), cur.Version()) | |
| 692 | - | } | |
| 693 | - | ||
| 694 | - | // destroy order: children, sources, managers, toplevel handle. | |
| 695 | - | for _, c := range []struct { | |
| 696 | - | name string | |
| 697 | - | id uint32 | |
| 698 | - | op uint16 | |
| 699 | - | fn func() error | |
| 700 | - | }{ | |
| 701 | - | {"failed frame", failing.ID(), 0, failing.Destroy}, | |
| 702 | - | {"capture session", csess.ID(), 1, csess.Destroy}, | |
| 703 | - | {"session", sess.ID(), 1, sess.Destroy}, | |
| 704 | - | {"cursor", cur.ID(), 0, cur.Destroy}, | |
| 705 | - | {"output source", outSrc.ID(), 0, outSrc.Destroy}, | |
| 706 | - | {"toplevel source", topSrc.ID(), 0, topSrc.Destroy}, | |
| 707 | - | {"copy manager", cm.ID(), 2, cm.Destroy}, | |
| 708 | - | {"output manager", om.ID(), 1, om.Destroy}, | |
| 709 | - | {"toplevel manager", fm.ID(), 1, fm.Destroy}, | |
| 710 | - | {"handle", handle.ID(), 0, handle.Destroy}, | |
| 711 | - | } { | |
| 712 | - | // Subtests run serially (no t.Parallel): the wire order of destroy | |
| 713 | - | // requests on the shared socketpair is part of what is asserted. | |
| 714 | - | ok := t.Run(c.name, func(t *testing.T) { | |
| 715 | - | ss := *s | |
| 716 | - | ss.t = t | |
| 717 | - | noerr(t, c.fn()) | |
| 718 | - | ss.req(c.id, c.op) | |
| 719 | - | }) | |
| 720 | - | if !ok { | |
| 721 | - | // A failed step leaves unread bytes on the socket; carrying on | |
| 722 | - | // would misattribute them to later destroys. | |
| 723 | - | t.FailNow() | |
| 724 | - | } | |
| 725 | - | } | |
| 726 | - | } | |
D protocol/inputmethod/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package inputmethod | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p inputmethod -o input-method-unstable-v2_generated.go -import wl_seat=github.com/bnema/wlturbo/protocol/core -import wl_surface=github.com/bnema/wlturbo/protocol/core input-method-unstable-v2.xml | |
D protocol/inputmethod/input-method-unstable-v2.xml +0 -494
| @@ -1,494 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="input_method_unstable_v2"> | |
| 3 | - | ||
| 4 | - | <copyright> | |
| 5 | - | Copyright © 2008-2011 Kristian Høgsberg | |
| 6 | - | Copyright © 2010-2011 Intel Corporation | |
| 7 | - | Copyright © 2012-2013 Collabora, Ltd. | |
| 8 | - | Copyright © 2012, 2013 Intel Corporation | |
| 9 | - | Copyright © 2015, 2016 Jan Arne Petersen | |
| 10 | - | Copyright © 2017, 2018 Red Hat, Inc. | |
| 11 | - | Copyright © 2018 Purism SPC | |
| 12 | - | ||
| 13 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 14 | - | copy of this software and associated documentation files (the "Software"), | |
| 15 | - | to deal in the Software without restriction, including without limitation | |
| 16 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 17 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 18 | - | Software is furnished to do so, subject to the following conditions: | |
| 19 | - | ||
| 20 | - | The above copyright notice and this permission notice (including the next | |
| 21 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 22 | - | Software. | |
| 23 | - | ||
| 24 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 25 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 26 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 27 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 28 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 29 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 30 | - | DEALINGS IN THE SOFTWARE. | |
| 31 | - | </copyright> | |
| 32 | - | ||
| 33 | - | <description summary="Protocol for creating input methods"> | |
| 34 | - | This protocol allows applications to act as input methods for compositors. | |
| 35 | - | ||
| 36 | - | An input method context is used to manage the state of the input method. | |
| 37 | - | ||
| 38 | - | Text strings are UTF-8 encoded, their indices and lengths are in bytes. | |
| 39 | - | ||
| 40 | - | This document adheres to the RFC 2119 when using words like "must", | |
| 41 | - | "should", "may", etc. | |
| 42 | - | ||
| 43 | - | Warning! The protocol described in this file is experimental and | |
| 44 | - | backward incompatible changes may be made. Backward compatible changes | |
| 45 | - | may be added together with the corresponding interface version bump. | |
| 46 | - | Backward incompatible changes are done by bumping the version number in | |
| 47 | - | the protocol and interface names and resetting the interface version. | |
| 48 | - | Once the protocol is to be declared stable, the 'z' prefix and the | |
| 49 | - | version number in the protocol and interface names are removed and the | |
| 50 | - | interface version number is reset. | |
| 51 | - | </description> | |
| 52 | - | ||
| 53 | - | <interface name="zwp_input_method_v2" version="1"> | |
| 54 | - | <description summary="input method"> | |
| 55 | - | An input method object allows for clients to compose text. | |
| 56 | - | ||
| 57 | - | The objects connects the client to a text input in an application, and | |
| 58 | - | lets the client to serve as an input method for a seat. | |
| 59 | - | ||
| 60 | - | The zwp_input_method_v2 object can occupy two distinct states: active and | |
| 61 | - | inactive. In the active state, the object is associated to and | |
| 62 | - | communicates with a text input. In the inactive state, there is no | |
| 63 | - | associated text input, and the only communication is with the compositor. | |
| 64 | - | Initially, the input method is in the inactive state. | |
| 65 | - | ||
| 66 | - | Requests issued in the inactive state must be accepted by the compositor. | |
| 67 | - | Because of the serial mechanism, and the state reset on activate event, | |
| 68 | - | they will not have any effect on the state of the next text input. | |
| 69 | - | ||
| 70 | - | There must be no more than one input method object per seat. | |
| 71 | - | </description> | |
| 72 | - | ||
| 73 | - | <enum name="error"> | |
| 74 | - | <entry name="role" value="0" summary="wl_surface has another role"/> | |
| 75 | - | </enum> | |
| 76 | - | ||
| 77 | - | <event name="activate"> | |
| 78 | - | <description summary="input method has been requested"> | |
| 79 | - | Notification that a text input focused on this seat requested the input | |
| 80 | - | method to be activated. | |
| 81 | - | ||
| 82 | - | This event serves the purpose of providing the compositor with an | |
| 83 | - | active input method. | |
| 84 | - | ||
| 85 | - | This event resets all state associated with previous enable, disable, | |
| 86 | - | surrounding_text, text_change_cause, and content_type events, as well | |
| 87 | - | as the state associated with set_preedit_string, commit_string, and | |
| 88 | - | delete_surrounding_text requests. In addition, it marks the | |
| 89 | - | zwp_input_method_v2 object as active, and makes any existing | |
| 90 | - | zwp_input_popup_surface_v2 objects visible. | |
| 91 | - | ||
| 92 | - | The surrounding_text, and content_type events must follow before the | |
| 93 | - | next done event if the text input supports the respective | |
| 94 | - | functionality. | |
| 95 | - | ||
| 96 | - | State set with this event is double-buffered. It will get applied on | |
| 97 | - | the next zwp_input_method_v2.done event, and stay valid until changed. | |
| 98 | - | </description> | |
| 99 | - | </event> | |
| 100 | - | ||
| 101 | - | <event name="deactivate"> | |
| 102 | - | <description summary="deactivate event"> | |
| 103 | - | Notification that no focused text input currently needs an active | |
| 104 | - | input method on this seat. | |
| 105 | - | ||
| 106 | - | This event marks the zwp_input_method_v2 object as inactive. The | |
| 107 | - | compositor must make all existing zwp_input_popup_surface_v2 objects | |
| 108 | - | invisible until the next activate event. | |
| 109 | - | ||
| 110 | - | State set with this event is double-buffered. It will get applied on | |
| 111 | - | the next zwp_input_method_v2.done event, and stay valid until changed. | |
| 112 | - | </description> | |
| 113 | - | </event> | |
| 114 | - | ||
| 115 | - | <event name="surrounding_text"> | |
| 116 | - | <description summary="surrounding text event"> | |
| 117 | - | Updates the surrounding plain text around the cursor, excluding the | |
| 118 | - | preedit text. | |
| 119 | - | ||
| 120 | - | If any preedit text is present, it is replaced with the cursor for the | |
| 121 | - | purpose of this event. | |
| 122 | - | ||
| 123 | - | The argument text is a buffer containing the preedit string, and must | |
| 124 | - | include the cursor position, and the complete selection. It should | |
| 125 | - | contain additional characters before and after these. There is a | |
| 126 | - | maximum length of wayland messages, so text can not be longer than 4000 | |
| 127 | - | bytes. | |
| 128 | - | ||
| 129 | - | cursor is the byte offset of the cursor within the text buffer. | |
| 130 | - | ||
| 131 | - | anchor is the byte offset of the selection anchor within the text | |
| 132 | - | buffer. If there is no selected text, anchor must be the same as | |
| 133 | - | cursor. | |
| 134 | - | ||
| 135 | - | If this event does not arrive before the first done event, the input | |
| 136 | - | method may assume that the text input does not support this | |
| 137 | - | functionality and ignore following surrounding_text events. | |
| 138 | - | ||
| 139 | - | Values set with this event are double-buffered. They will get applied | |
| 140 | - | and set to initial values on the next zwp_input_method_v2.done | |
| 141 | - | event. | |
| 142 | - | ||
| 143 | - | The initial state for affected fields is empty, meaning that the text | |
| 144 | - | input does not support sending surrounding text. If the empty values | |
| 145 | - | get applied, subsequent attempts to change them may have no effect. | |
| 146 | - | </description> | |
| 147 | - | <arg name="text" type="string"/> | |
| 148 | - | <arg name="cursor" type="uint"/> | |
| 149 | - | <arg name="anchor" type="uint"/> | |
| 150 | - | </event> | |
| 151 | - | ||
| 152 | - | <event name="text_change_cause"> | |
| 153 | - | <description summary="indicates the cause of surrounding text change"> | |
| 154 | - | Tells the input method why the text surrounding the cursor changed. | |
| 155 | - | ||
| 156 | - | Whenever the client detects an external change in text, cursor, or | |
| 157 | - | anchor position, it must issue this request to the compositor. This | |
| 158 | - | request is intended to give the input method a chance to update the | |
| 159 | - | preedit text in an appropriate way, e.g. by removing it when the user | |
| 160 | - | starts typing with a keyboard. | |
| 161 | - | ||
| 162 | - | cause describes the source of the change. | |
| 163 | - | ||
| 164 | - | The value set with this event is double-buffered. It will get applied | |
| 165 | - | and set to its initial value on the next zwp_input_method_v2.done | |
| 166 | - | event. | |
| 167 | - | ||
| 168 | - | The initial value of cause is input_method. | |
| 169 | - | </description> | |
| 170 | - | <arg name="cause" type="uint" enum="zwp_text_input_v3.change_cause"/> | |
| 171 | - | </event> | |
| 172 | - | ||
| 173 | - | <event name="content_type"> | |
| 174 | - | <description summary="content purpose and hint"> | |
| 175 | - | Indicates the content type and hint for the current | |
| 176 | - | zwp_input_method_v2 instance. | |
| 177 | - | ||
| 178 | - | Values set with this event are double-buffered. They will get applied | |
| 179 | - | on the next zwp_input_method_v2.done event. | |
| 180 | - | ||
| 181 | - | The initial value for hint is none, and the initial value for purpose | |
| 182 | - | is normal. | |
| 183 | - | </description> | |
| 184 | - | <arg name="hint" type="uint" enum="zwp_text_input_v3.content_hint"/> | |
| 185 | - | <arg name="purpose" type="uint" enum="zwp_text_input_v3.content_purpose"/> | |
| 186 | - | </event> | |
| 187 | - | ||
| 188 | - | <event name="done"> | |
| 189 | - | <description summary="apply state"> | |
| 190 | - | Atomically applies state changes recently sent to the client. | |
| 191 | - | ||
| 192 | - | The done event establishes and updates the state of the client, and | |
| 193 | - | must be issued after any changes to apply them. | |
| 194 | - | ||
| 195 | - | Text input state (content purpose, content hint, surrounding text, and | |
| 196 | - | change cause) is conceptually double-buffered within an input method | |
| 197 | - | context. | |
| 198 | - | ||
| 199 | - | Events modify the pending state, as opposed to the current state in use | |
| 200 | - | by the input method. A done event atomically applies all pending state, | |
| 201 | - | replacing the current state. After done, the new pending state is as | |
| 202 | - | documented for each related request. | |
| 203 | - | ||
| 204 | - | Events must be applied in the order of arrival. | |
| 205 | - | ||
| 206 | - | Neither current nor pending state are modified unless noted otherwise. | |
| 207 | - | </description> | |
| 208 | - | </event> | |
| 209 | - | ||
| 210 | - | <request name="commit_string"> | |
| 211 | - | <description summary="commit string"> | |
| 212 | - | Send the commit string text for insertion to the application. | |
| 213 | - | ||
| 214 | - | Inserts a string at current cursor position (see commit event | |
| 215 | - | sequence). The string to commit could be either just a single character | |
| 216 | - | after a key press or the result of some composing. | |
| 217 | - | ||
| 218 | - | The argument text is a buffer containing the string to insert. There is | |
| 219 | - | a maximum length of wayland messages, so text can not be longer than | |
| 220 | - | 4000 bytes. | |
| 221 | - | ||
| 222 | - | Values set with this event are double-buffered. They must be applied | |
| 223 | - | and reset to initial on the next zwp_text_input_v3.commit request. | |
| 224 | - | ||
| 225 | - | The initial value of text is an empty string. | |
| 226 | - | </description> | |
| 227 | - | <arg name="text" type="string"/> | |
| 228 | - | </request> | |
| 229 | - | ||
| 230 | - | <request name="set_preedit_string"> | |
| 231 | - | <description summary="pre-edit string"> | |
| 232 | - | Send the pre-edit string text to the application text input. | |
| 233 | - | ||
| 234 | - | Place a new composing text (pre-edit) at the current cursor position. | |
| 235 | - | Any previously set composing text must be removed. Any previously | |
| 236 | - | existing selected text must be removed. The cursor is moved to a new | |
| 237 | - | position within the preedit string. | |
| 238 | - | ||
| 239 | - | The argument text is a buffer containing the preedit string. There is | |
| 240 | - | a maximum length of wayland messages, so text can not be longer than | |
| 241 | - | 4000 bytes. | |
| 242 | - | ||
| 243 | - | The arguments cursor_begin and cursor_end are counted in bytes relative | |
| 244 | - | to the beginning of the submitted string buffer. Cursor should be | |
| 245 | - | hidden by the text input when both are equal to -1. | |
| 246 | - | ||
| 247 | - | cursor_begin indicates the beginning of the cursor. cursor_end | |
| 248 | - | indicates the end of the cursor. It may be equal or different than | |
| 249 | - | cursor_begin. | |
| 250 | - | ||
| 251 | - | Values set with this event are double-buffered. They must be applied on | |
| 252 | - | the next zwp_input_method_v2.commit event. | |
| 253 | - | ||
| 254 | - | The initial value of text is an empty string. The initial value of | |
| 255 | - | cursor_begin, and cursor_end are both 0. | |
| 256 | - | </description> | |
| 257 | - | <arg name="text" type="string"/> | |
| 258 | - | <arg name="cursor_begin" type="int"/> | |
| 259 | - | <arg name="cursor_end" type="int"/> | |
| 260 | - | </request> | |
| 261 | - | ||
| 262 | - | <request name="delete_surrounding_text"> | |
| 263 | - | <description summary="delete text"> | |
| 264 | - | Remove the surrounding text. | |
| 265 | - | ||
| 266 | - | before_length and after_length are the number of bytes before and after | |
| 267 | - | the current cursor index (excluding the preedit text) to delete. | |
| 268 | - | ||
| 269 | - | If any preedit text is present, it is replaced with the cursor for the | |
| 270 | - | purpose of this event. In effect before_length is counted from the | |
| 271 | - | beginning of preedit text, and after_length from its end (see commit | |
| 272 | - | event sequence). | |
| 273 | - | ||
| 274 | - | Values set with this event are double-buffered. They must be applied | |
| 275 | - | and reset to initial on the next zwp_input_method_v2.commit request. | |
| 276 | - | ||
| 277 | - | The initial values of both before_length and after_length are 0. | |
| 278 | - | </description> | |
| 279 | - | <arg name="before_length" type="uint"/> | |
| 280 | - | <arg name="after_length" type="uint"/> | |
| 281 | - | </request> | |
| 282 | - | ||
| 283 | - | <request name="commit"> | |
| 284 | - | <description summary="apply state"> | |
| 285 | - | Apply state changes from commit_string, set_preedit_string and | |
| 286 | - | delete_surrounding_text requests. | |
| 287 | - | ||
| 288 | - | The state relating to these events is double-buffered, and each one | |
| 289 | - | modifies the pending state. This request replaces the current state | |
| 290 | - | with the pending state. | |
| 291 | - | ||
| 292 | - | The connected text input is expected to proceed by evaluating the | |
| 293 | - | changes in the following order: | |
| 294 | - | ||
| 295 | - | 1. Replace existing preedit string with the cursor. | |
| 296 | - | 2. Delete requested surrounding text. | |
| 297 | - | 3. Insert commit string with the cursor at its end. | |
| 298 | - | 4. Calculate surrounding text to send. | |
| 299 | - | 5. Insert new preedit text in cursor position. | |
| 300 | - | 6. Place cursor inside preedit text. | |
| 301 | - | ||
| 302 | - | The serial number reflects the last state of the zwp_input_method_v2 | |
| 303 | - | object known to the client. The value of the serial argument must be | |
| 304 | - | equal to the number of done events already issued by that object. When | |
| 305 | - | the compositor receives a commit request with a serial different than | |
| 306 | - | the number of past done events, it must proceed as normal, except it | |
| 307 | - | should not change the current state of the zwp_input_method_v2 object. | |
| 308 | - | </description> | |
| 309 | - | <arg name="serial" type="uint"/> | |
| 310 | - | </request> | |
| 311 | - | ||
| 312 | - | <request name="get_input_popup_surface"> | |
| 313 | - | <description summary="create popup surface"> | |
| 314 | - | Creates a new zwp_input_popup_surface_v2 object wrapping a given | |
| 315 | - | surface. | |
| 316 | - | ||
| 317 | - | The surface gets assigned the "input_popup" role. If the surface | |
| 318 | - | already has an assigned role, the compositor must issue a protocol | |
| 319 | - | error. | |
| 320 | - | </description> | |
| 321 | - | <arg name="id" type="new_id" interface="zwp_input_popup_surface_v2"/> | |
| 322 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 323 | - | </request> | |
| 324 | - | ||
| 325 | - | <request name="grab_keyboard"> | |
| 326 | - | <description summary="grab hardware keyboard"> | |
| 327 | - | Allow an input method to receive hardware keyboard input and process | |
| 328 | - | key events to generate text events (with pre-edit) over the wire. This | |
| 329 | - | allows input methods which compose multiple key events for inputting | |
| 330 | - | text like it is done for CJK languages. | |
| 331 | - | ||
| 332 | - | The compositor should send all keyboard events on the seat to the grab | |
| 333 | - | holder via the returned wl_keyboard object. Nevertheless, the | |
| 334 | - | compositor may decide not to forward any particular event. The | |
| 335 | - | compositor must not further process any event after it has been | |
| 336 | - | forwarded to the grab holder. | |
| 337 | - | ||
| 338 | - | Releasing the resulting wl_keyboard object releases the grab. | |
| 339 | - | </description> | |
| 340 | - | <arg name="keyboard" type="new_id" | |
| 341 | - | interface="zwp_input_method_keyboard_grab_v2"/> | |
| 342 | - | </request> | |
| 343 | - | ||
| 344 | - | <event name="unavailable"> | |
| 345 | - | <description summary="input method unavailable"> | |
| 346 | - | The input method ceased to be available. | |
| 347 | - | ||
| 348 | - | The compositor must issue this event as the only event on the object if | |
| 349 | - | there was another input_method object associated with the same seat at | |
| 350 | - | the time of its creation. | |
| 351 | - | ||
| 352 | - | The compositor must issue this request when the object is no longer | |
| 353 | - | usable, e.g. due to seat removal. | |
| 354 | - | ||
| 355 | - | The input method context becomes inert and should be destroyed after | |
| 356 | - | deactivation is handled. Any further requests and events except for the | |
| 357 | - | destroy request must be ignored. | |
| 358 | - | </description> | |
| 359 | - | </event> | |
| 360 | - | ||
| 361 | - | <request name="destroy" type="destructor"> | |
| 362 | - | <description summary="destroy the text input"> | |
| 363 | - | Destroys the zwp_text_input_v2 object and any associated child | |
| 364 | - | objects, i.e. zwp_input_popup_surface_v2 and | |
| 365 | - | zwp_input_method_keyboard_grab_v2. | |
| 366 | - | </description> | |
| 367 | - | </request> | |
| 368 | - | </interface> | |
| 369 | - | ||
| 370 | - | <interface name="zwp_input_popup_surface_v2" version="1"> | |
| 371 | - | <description summary="popup surface"> | |
| 372 | - | This interface marks a surface as a popup for interacting with an input | |
| 373 | - | method. | |
| 374 | - | ||
| 375 | - | The compositor should place it near the active text input area. It must | |
| 376 | - | be visible if and only if the input method is in the active state. | |
| 377 | - | ||
| 378 | - | The client must not destroy the underlying wl_surface while the | |
| 379 | - | zwp_input_popup_surface_v2 object exists. | |
| 380 | - | </description> | |
| 381 | - | ||
| 382 | - | <event name="text_input_rectangle"> | |
| 383 | - | <description summary="set text input area position"> | |
| 384 | - | Notify about the position of the area of the text input expressed as a | |
| 385 | - | rectangle in surface local coordinates. | |
| 386 | - | ||
| 387 | - | This is a hint to the input method telling it the relative position of | |
| 388 | - | the text being entered. | |
| 389 | - | </description> | |
| 390 | - | <arg name="x" type="int"/> | |
| 391 | - | <arg name="y" type="int"/> | |
| 392 | - | <arg name="width" type="int"/> | |
| 393 | - | <arg name="height" type="int"/> | |
| 394 | - | </event> | |
| 395 | - | ||
| 396 | - | <request name="destroy" type="destructor"/> | |
| 397 | - | </interface> | |
| 398 | - | ||
| 399 | - | <interface name="zwp_input_method_keyboard_grab_v2" version="1"> | |
| 400 | - | <!-- Closely follows wl_keyboard version 6 --> | |
| 401 | - | <description summary="keyboard grab"> | |
| 402 | - | The zwp_input_method_keyboard_grab_v2 interface represents an exclusive | |
| 403 | - | grab of the wl_keyboard interface associated with the seat. | |
| 404 | - | </description> | |
| 405 | - | ||
| 406 | - | <event name="keymap"> | |
| 407 | - | <description summary="keyboard mapping"> | |
| 408 | - | This event provides a file descriptor to the client which can be | |
| 409 | - | memory-mapped to provide a keyboard mapping description. | |
| 410 | - | </description> | |
| 411 | - | <arg name="format" type="uint" enum="wl_keyboard.keymap_format" | |
| 412 | - | summary="keymap format"/> | |
| 413 | - | <arg name="fd" type="fd" summary="keymap file descriptor"/> | |
| 414 | - | <arg name="size" type="uint" summary="keymap size, in bytes"/> | |
| 415 | - | </event> | |
| 416 | - | ||
| 417 | - | <event name="key"> | |
| 418 | - | <description summary="key event"> | |
| 419 | - | A key was pressed or released. | |
| 420 | - | The time argument is a timestamp with millisecond granularity, with an | |
| 421 | - | undefined base. | |
| 422 | - | </description> | |
| 423 | - | <arg name="serial" type="uint" summary="serial number of the key event"/> | |
| 424 | - | <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> | |
| 425 | - | <arg name="key" type="uint" summary="key that produced the event"/> | |
| 426 | - | <arg name="state" type="uint" enum="wl_keyboard.key_state" | |
| 427 | - | summary="physical state of the key"/> | |
| 428 | - | </event> | |
| 429 | - | ||
| 430 | - | <event name="modifiers"> | |
| 431 | - | <description summary="modifier and group state"> | |
| 432 | - | Notifies clients that the modifier and/or group state has changed, and | |
| 433 | - | it should update its local state. | |
| 434 | - | </description> | |
| 435 | - | <arg name="serial" type="uint" summary="serial number of the modifiers event"/> | |
| 436 | - | <arg name="mods_depressed" type="uint" summary="depressed modifiers"/> | |
| 437 | - | <arg name="mods_latched" type="uint" summary="latched modifiers"/> | |
| 438 | - | <arg name="mods_locked" type="uint" summary="locked modifiers"/> | |
| 439 | - | <arg name="group" type="uint" summary="keyboard layout"/> | |
| 440 | - | </event> | |
| 441 | - | ||
| 442 | - | <request name="release" type="destructor"> | |
| 443 | - | <description summary="release the grab object"/> | |
| 444 | - | </request> | |
| 445 | - | ||
| 446 | - | <event name="repeat_info"> | |
| 447 | - | <description summary="repeat rate and delay"> | |
| 448 | - | Informs the client about the keyboard's repeat rate and delay. | |
| 449 | - | ||
| 450 | - | This event is sent as soon as the zwp_input_method_keyboard_grab_v2 | |
| 451 | - | object has been created, and is guaranteed to be received by the | |
| 452 | - | client before any key press event. | |
| 453 | - | ||
| 454 | - | Negative values for either rate or delay are illegal. A rate of zero | |
| 455 | - | will disable any repeating (regardless of the value of delay). | |
| 456 | - | ||
| 457 | - | This event can be sent later on as well with a new value if necessary, | |
| 458 | - | so clients should continue listening for the event past the creation | |
| 459 | - | of zwp_input_method_keyboard_grab_v2. | |
| 460 | - | </description> | |
| 461 | - | <arg name="rate" type="int" | |
| 462 | - | summary="the rate of repeating keys in characters per second"/> | |
| 463 | - | <arg name="delay" type="int" | |
| 464 | - | summary="delay in milliseconds since key down until repeating starts"/> | |
| 465 | - | </event> | |
| 466 | - | </interface> | |
| 467 | - | ||
| 468 | - | <interface name="zwp_input_method_manager_v2" version="1"> | |
| 469 | - | <description summary="input method manager"> | |
| 470 | - | The input method manager allows the client to become the input method on | |
| 471 | - | a chosen seat. | |
| 472 | - | ||
| 473 | - | No more than one input method must be associated with any seat at any | |
| 474 | - | given time. | |
| 475 | - | </description> | |
| 476 | - | ||
| 477 | - | <request name="get_input_method"> | |
| 478 | - | <description summary="request an input method object"> | |
| 479 | - | Request a new input zwp_input_method_v2 object associated with a given | |
| 480 | - | seat. | |
| 481 | - | </description> | |
| 482 | - | <arg name="seat" type="object" interface="wl_seat"/> | |
| 483 | - | <arg name="input_method" type="new_id" interface="zwp_input_method_v2"/> | |
| 484 | - | </request> | |
| 485 | - | ||
| 486 | - | <request name="destroy" type="destructor"> | |
| 487 | - | <description summary="destroy the input method manager"> | |
| 488 | - | Destroys the zwp_input_method_manager_v2 object. | |
| 489 | - | ||
| 490 | - | The zwp_input_method_v2 objects originating from it remain valid. | |
| 491 | - | </description> | |
| 492 | - | </request> | |
| 493 | - | </interface> | |
| 494 | - | </protocol> | |
D protocol/inputmethod/input-method-unstable-v2_generated.go +0 -677
| @@ -1,677 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: input_method_unstable_v2 | |
| 3 | - | // Source: input-method-unstable-v2.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2008-2011 Kristian Høgsberg | |
| 7 | - | // Copyright © 2010-2011 Intel Corporation | |
| 8 | - | // Copyright © 2012-2013 Collabora, Ltd. | |
| 9 | - | // Copyright © 2012, 2013 Intel Corporation | |
| 10 | - | // Copyright © 2015, 2016 Jan Arne Petersen | |
| 11 | - | // Copyright © 2017, 2018 Red Hat, Inc. | |
| 12 | - | // Copyright © 2018 Purism SPC | |
| 13 | - | // | |
| 14 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 15 | - | // copy of this software and associated documentation files (the "Software"), | |
| 16 | - | // to deal in the Software without restriction, including without limitation | |
| 17 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 18 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 19 | - | // Software is furnished to do so, subject to the following conditions: | |
| 20 | - | // | |
| 21 | - | // The above copyright notice and this permission notice (including the next | |
| 22 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 23 | - | // Software. | |
| 24 | - | // | |
| 25 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 26 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 27 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 28 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 29 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 30 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 31 | - | // DEALINGS IN THE SOFTWARE. | |
| 32 | - | ||
| 33 | - | package inputmethod | |
| 34 | - | ||
| 35 | - | import ( | |
| 36 | - | "sync" | |
| 37 | - | ||
| 38 | - | cross_wl_seat "github.com/bnema/wlturbo/protocol/core" | |
| 39 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 40 | - | "github.com/bnema/wlturbo/wl" | |
| 41 | - | ) | |
| 42 | - | ||
| 43 | - | // ERROR_ROLE is the error role value. | |
| 44 | - | const ERROR_ROLE = 0 | |
| 45 | - | ||
| 46 | - | // InputMethodInterface is the protocol interface name. | |
| 47 | - | const InputMethodInterface = "zwp_input_method_v2" | |
| 48 | - | ||
| 49 | - | // InputMethod is the generated binding for zwp_input_method_v2 version 1. | |
| 50 | - | type InputMethod struct { | |
| 51 | - | wl.BaseProxy | |
| 52 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 53 | - | // handlers while another goroutine dispatches events. | |
| 54 | - | handlersMu sync.Mutex | |
| 55 | - | onActivate []func() | |
| 56 | - | onDeactivate []func() | |
| 57 | - | onSurroundingText []func(text string, cursor uint32, anchor uint32) | |
| 58 | - | onTextChangeCause []func(cause uint32) | |
| 59 | - | onContentType []func(hint uint32, purpose uint32) | |
| 60 | - | onDone []func() | |
| 61 | - | onUnavailable []func() | |
| 62 | - | } | |
| 63 | - | ||
| 64 | - | // NewInputMethod returns an unbound InputMethod. | |
| 65 | - | func NewInputMethod(ctx *wl.Context) *InputMethod { | |
| 66 | - | obj := &InputMethod{} | |
| 67 | - | obj.SetContext(ctx) | |
| 68 | - | ctx.Register(obj) | |
| 69 | - | return obj | |
| 70 | - | } | |
| 71 | - | ||
| 72 | - | // Send the commit string text for insertion to the application. Inserts a string at current cursor position (see commit event sequence). The string to commit could be either just a single character after a key press or the result of some composing. The argument text is a buffer containing the string to insert. There is a maximum length of wayland messages, so text can not be longer than 4000 bytes. Values set with this event are double-buffered. They must be applied and reset to initial on the next zwp_text_input_v3.commit request. The initial value of text is an empty string. | |
| 73 | - | func (o *InputMethod) CommitString(text string) error { | |
| 74 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwp_input_method_v2.commit_string"}, wl.ArgString(text)); err != nil { | |
| 75 | - | return err | |
| 76 | - | } | |
| 77 | - | return nil | |
| 78 | - | } | |
| 79 | - | ||
| 80 | - | // Send the pre-edit string text to the application text input. Place a new composing text (pre-edit) at the current cursor position. Any previously set composing text must be removed. Any previously existing selected text must be removed. The cursor is moved to a new position within the preedit string. The argument text is a buffer containing the preedit string. There is a maximum length of wayland messages, so text can not be longer than 4000 bytes. The arguments cursor_begin and cursor_end are counted in bytes relative to the beginning of the submitted string buffer. Cursor should be hidden by the text input when both are equal to -1. cursor_begin indicates the beginning of the cursor. cursor_end indicates the end of the cursor. It may be equal or different than cursor_begin. Values set with this event are double-buffered. They must be applied on the next zwp_input_method_v2.commit event. The initial value of text is an empty string. The initial value of cursor_begin, and cursor_end are both 0. | |
| 81 | - | func (o *InputMethod) SetPreeditString(text string, cursorBegin int32, cursorEnd int32) error { | |
| 82 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "zwp_input_method_v2.set_preedit_string"}, wl.ArgString(text), wl.ArgInt(cursorBegin), wl.ArgInt(cursorEnd)); err != nil { | |
| 83 | - | return err | |
| 84 | - | } | |
| 85 | - | return nil | |
| 86 | - | } | |
| 87 | - | ||
| 88 | - | // Remove the surrounding text. before_length and after_length are the number of bytes before and after the current cursor index (excluding the preedit text) to delete. If any preedit text is present, it is replaced with the cursor for the purpose of this event. In effect before_length is counted from the beginning of preedit text, and after_length from its end (see commit event sequence). Values set with this event are double-buffered. They must be applied and reset to initial on the next zwp_input_method_v2.commit request. The initial values of both before_length and after_length are 0. | |
| 89 | - | func (o *InputMethod) DeleteSurroundingText(beforeLength uint32, afterLength uint32) error { | |
| 90 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "zwp_input_method_v2.delete_surrounding_text"}, wl.ArgUint(beforeLength), wl.ArgUint(afterLength)); err != nil { | |
| 91 | - | return err | |
| 92 | - | } | |
| 93 | - | return nil | |
| 94 | - | } | |
| 95 | - | ||
| 96 | - | // Apply state changes from commit_string, set_preedit_string and delete_surrounding_text requests. The state relating to these events is double-buffered, and each one modifies the pending state. This request replaces the current state with the pending state. The connected text input is expected to proceed by evaluating the changes in the following order: 1. Replace existing preedit string with the cursor. 2. Delete requested surrounding text. 3. Insert commit string with the cursor at its end. 4. Calculate surrounding text to send. 5. Insert new preedit text in cursor position. 6. Place cursor inside preedit text. The serial number reflects the last state of the zwp_input_method_v2 object known to the client. The value of the serial argument must be equal to the number of done events already issued by that object. When the compositor receives a commit request with a serial different than the number of past done events, it must proceed as normal, except it should not change the current state of the zwp_input_method_v2 object. | |
| 97 | - | func (o *InputMethod) Commit(serial uint32) error { | |
| 98 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 3, Name: "zwp_input_method_v2.commit"}, wl.ArgUint(serial)); err != nil { | |
| 99 | - | return err | |
| 100 | - | } | |
| 101 | - | return nil | |
| 102 | - | } | |
| 103 | - | ||
| 104 | - | // Creates a new zwp_input_popup_surface_v2 object wrapping a given surface. The surface gets assigned the "input_popup" role. If the surface already has an assigned role, the compositor must issue a protocol error. | |
| 105 | - | func (o *InputMethod) GetInputPopupSurface(surface *cross_wl_surface.Surface) (*InputPopupSurface, error) { | |
| 106 | - | var arg1 wl.Object | |
| 107 | - | if surface != nil { | |
| 108 | - | arg1 = surface | |
| 109 | - | } | |
| 110 | - | child := &InputPopupSurface{} | |
| 111 | - | child.SetContext(o.Context()) | |
| 112 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 4, Name: "zwp_input_method_v2.get_input_popup_surface", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 113 | - | return nil, err | |
| 114 | - | } | |
| 115 | - | return child, nil | |
| 116 | - | } | |
| 117 | - | ||
| 118 | - | // Allow an input method to receive hardware keyboard input and process key events to generate text events (with pre-edit) over the wire. This allows input methods which compose multiple key events for inputting text like it is done for CJK languages. The compositor should send all keyboard events on the seat to the grab holder via the returned wl_keyboard object. Nevertheless, the compositor may decide not to forward any particular event. The compositor must not further process any event after it has been forwarded to the grab holder. Releasing the resulting wl_keyboard object releases the grab. | |
| 119 | - | func (o *InputMethod) GrabKeyboard() (*InputMethodKeyboardGrab, error) { | |
| 120 | - | child := &InputMethodKeyboardGrab{} | |
| 121 | - | child.SetContext(o.Context()) | |
| 122 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 5, Name: "zwp_input_method_v2.grab_keyboard", Child: child}, wl.ArgObject(child)); err != nil { | |
| 123 | - | return nil, err | |
| 124 | - | } | |
| 125 | - | return child, nil | |
| 126 | - | } | |
| 127 | - | ||
| 128 | - | // Destroys the zwp_text_input_v2 object and any associated child objects, i.e. zwp_input_popup_surface_v2 and zwp_input_method_keyboard_grab_v2. | |
| 129 | - | func (o *InputMethod) Destroy() error { | |
| 130 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 6, Name: "zwp_input_method_v2.destroy", Destructor: true}); err != nil { | |
| 131 | - | return err | |
| 132 | - | } | |
| 133 | - | return nil | |
| 134 | - | } | |
| 135 | - | ||
| 136 | - | // OnActivate registers a handler for the activate event. | |
| 137 | - | // | |
| 138 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 139 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 140 | - | func (o *InputMethod) OnActivate(handler func()) { | |
| 141 | - | if handler == nil { | |
| 142 | - | return | |
| 143 | - | } | |
| 144 | - | o.handlersMu.Lock() | |
| 145 | - | defer o.handlersMu.Unlock() | |
| 146 | - | o.onActivate = append(o.onActivate, handler) | |
| 147 | - | } | |
| 148 | - | ||
| 149 | - | // handlersForActivate returns the handlers registered for activate, taken | |
| 150 | - | // under the lock so a handler may register another handler while events are | |
| 151 | - | // being dispatched. | |
| 152 | - | func (o *InputMethod) handlersForActivate() []func() { | |
| 153 | - | o.handlersMu.Lock() | |
| 154 | - | defer o.handlersMu.Unlock() | |
| 155 | - | return o.onActivate | |
| 156 | - | } | |
| 157 | - | ||
| 158 | - | // OnDeactivate registers a handler for the deactivate event. | |
| 159 | - | // | |
| 160 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 161 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 162 | - | func (o *InputMethod) OnDeactivate(handler func()) { | |
| 163 | - | if handler == nil { | |
| 164 | - | return | |
| 165 | - | } | |
| 166 | - | o.handlersMu.Lock() | |
| 167 | - | defer o.handlersMu.Unlock() | |
| 168 | - | o.onDeactivate = append(o.onDeactivate, handler) | |
| 169 | - | } | |
| 170 | - | ||
| 171 | - | // handlersForDeactivate returns the handlers registered for deactivate, taken | |
| 172 | - | // under the lock so a handler may register another handler while events are | |
| 173 | - | // being dispatched. | |
| 174 | - | func (o *InputMethod) handlersForDeactivate() []func() { | |
| 175 | - | o.handlersMu.Lock() | |
| 176 | - | defer o.handlersMu.Unlock() | |
| 177 | - | return o.onDeactivate | |
| 178 | - | } | |
| 179 | - | ||
| 180 | - | // OnSurroundingText registers a handler for the surrounding_text event. | |
| 181 | - | // | |
| 182 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 183 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 184 | - | func (o *InputMethod) OnSurroundingText(handler func(text string, cursor uint32, anchor uint32)) { | |
| 185 | - | if handler == nil { | |
| 186 | - | return | |
| 187 | - | } | |
| 188 | - | o.handlersMu.Lock() | |
| 189 | - | defer o.handlersMu.Unlock() | |
| 190 | - | o.onSurroundingText = append(o.onSurroundingText, handler) | |
| 191 | - | } | |
| 192 | - | ||
| 193 | - | // handlersForSurroundingText returns the handlers registered for surrounding_text, taken | |
| 194 | - | // under the lock so a handler may register another handler while events are | |
| 195 | - | // being dispatched. | |
| 196 | - | func (o *InputMethod) handlersForSurroundingText() []func(text string, cursor uint32, anchor uint32) { | |
| 197 | - | o.handlersMu.Lock() | |
| 198 | - | defer o.handlersMu.Unlock() | |
| 199 | - | return o.onSurroundingText | |
| 200 | - | } | |
| 201 | - | ||
| 202 | - | // OnTextChangeCause registers a handler for the text_change_cause event. | |
| 203 | - | // | |
| 204 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 205 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 206 | - | func (o *InputMethod) OnTextChangeCause(handler func(cause uint32)) { | |
| 207 | - | if handler == nil { | |
| 208 | - | return | |
| 209 | - | } | |
| 210 | - | o.handlersMu.Lock() | |
| 211 | - | defer o.handlersMu.Unlock() | |
| 212 | - | o.onTextChangeCause = append(o.onTextChangeCause, handler) | |
| 213 | - | } | |
| 214 | - | ||
| 215 | - | // handlersForTextChangeCause returns the handlers registered for text_change_cause, taken | |
| 216 | - | // under the lock so a handler may register another handler while events are | |
| 217 | - | // being dispatched. | |
| 218 | - | func (o *InputMethod) handlersForTextChangeCause() []func(cause uint32) { | |
| 219 | - | o.handlersMu.Lock() | |
| 220 | - | defer o.handlersMu.Unlock() | |
| 221 | - | return o.onTextChangeCause | |
| 222 | - | } | |
| 223 | - | ||
| 224 | - | // OnContentType registers a handler for the content_type event. | |
| 225 | - | // | |
| 226 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 227 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 228 | - | func (o *InputMethod) OnContentType(handler func(hint uint32, purpose uint32)) { | |
| 229 | - | if handler == nil { | |
| 230 | - | return | |
| 231 | - | } | |
| 232 | - | o.handlersMu.Lock() | |
| 233 | - | defer o.handlersMu.Unlock() | |
| 234 | - | o.onContentType = append(o.onContentType, handler) | |
| 235 | - | } | |
| 236 | - | ||
| 237 | - | // handlersForContentType returns the handlers registered for content_type, taken | |
| 238 | - | // under the lock so a handler may register another handler while events are | |
| 239 | - | // being dispatched. | |
| 240 | - | func (o *InputMethod) handlersForContentType() []func(hint uint32, purpose uint32) { | |
| 241 | - | o.handlersMu.Lock() | |
| 242 | - | defer o.handlersMu.Unlock() | |
| 243 | - | return o.onContentType | |
| 244 | - | } | |
| 245 | - | ||
| 246 | - | // OnDone registers a handler for the done event. | |
| 247 | - | // | |
| 248 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 249 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 250 | - | func (o *InputMethod) OnDone(handler func()) { | |
| 251 | - | if handler == nil { | |
| 252 | - | return | |
| 253 | - | } | |
| 254 | - | o.handlersMu.Lock() | |
| 255 | - | defer o.handlersMu.Unlock() | |
| 256 | - | o.onDone = append(o.onDone, handler) | |
| 257 | - | } | |
| 258 | - | ||
| 259 | - | // handlersForDone returns the handlers registered for done, taken | |
| 260 | - | // under the lock so a handler may register another handler while events are | |
| 261 | - | // being dispatched. | |
| 262 | - | func (o *InputMethod) handlersForDone() []func() { | |
| 263 | - | o.handlersMu.Lock() | |
| 264 | - | defer o.handlersMu.Unlock() | |
| 265 | - | return o.onDone | |
| 266 | - | } | |
| 267 | - | ||
| 268 | - | // OnUnavailable registers a handler for the unavailable event. | |
| 269 | - | // | |
| 270 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 271 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 272 | - | func (o *InputMethod) OnUnavailable(handler func()) { | |
| 273 | - | if handler == nil { | |
| 274 | - | return | |
| 275 | - | } | |
| 276 | - | o.handlersMu.Lock() | |
| 277 | - | defer o.handlersMu.Unlock() | |
| 278 | - | o.onUnavailable = append(o.onUnavailable, handler) | |
| 279 | - | } | |
| 280 | - | ||
| 281 | - | // handlersForUnavailable returns the handlers registered for unavailable, taken | |
| 282 | - | // under the lock so a handler may register another handler while events are | |
| 283 | - | // being dispatched. | |
| 284 | - | func (o *InputMethod) handlersForUnavailable() []func() { | |
| 285 | - | o.handlersMu.Lock() | |
| 286 | - | defer o.handlersMu.Unlock() | |
| 287 | - | return o.onUnavailable | |
| 288 | - | } | |
| 289 | - | ||
| 290 | - | // EventSignature returns the declared event argument types in wire order. | |
| 291 | - | func (o *InputMethod) EventSignature(opcode uint16) (string, bool) { | |
| 292 | - | switch opcode { | |
| 293 | - | case 0: | |
| 294 | - | return "", true | |
| 295 | - | case 1: | |
| 296 | - | return "", true | |
| 297 | - | case 2: | |
| 298 | - | return "string,uint,uint,", true | |
| 299 | - | case 3: | |
| 300 | - | return "uint,", true | |
| 301 | - | case 4: | |
| 302 | - | return "uint,uint,", true | |
| 303 | - | case 5: | |
| 304 | - | return "", true | |
| 305 | - | case 6: | |
| 306 | - | return "", true | |
| 307 | - | default: | |
| 308 | - | return "", false | |
| 309 | - | } | |
| 310 | - | } | |
| 311 | - | ||
| 312 | - | // Dispatch decodes one event on zwp_input_method_v2 and calls the registered handlers. | |
| 313 | - | func (o *InputMethod) Dispatch(event *wl.Event) { | |
| 314 | - | switch event.Opcode { | |
| 315 | - | case 0: // activate | |
| 316 | - | ||
| 317 | - | for i, handler := range o.handlersForActivate() { | |
| 318 | - | _ = i | |
| 319 | - | handler() | |
| 320 | - | } | |
| 321 | - | case 1: // deactivate | |
| 322 | - | ||
| 323 | - | for i, handler := range o.handlersForDeactivate() { | |
| 324 | - | _ = i | |
| 325 | - | handler() | |
| 326 | - | } | |
| 327 | - | case 2: // surrounding_text | |
| 328 | - | text := event.String() | |
| 329 | - | cursor := event.Uint32() | |
| 330 | - | anchor := event.Uint32() | |
| 331 | - | ||
| 332 | - | for i, handler := range o.handlersForSurroundingText() { | |
| 333 | - | _ = i | |
| 334 | - | handler(text, cursor, anchor) | |
| 335 | - | } | |
| 336 | - | case 3: // text_change_cause | |
| 337 | - | cause := event.Uint32() | |
| 338 | - | ||
| 339 | - | for i, handler := range o.handlersForTextChangeCause() { | |
| 340 | - | _ = i | |
| 341 | - | handler(cause) | |
| 342 | - | } | |
| 343 | - | case 4: // content_type | |
| 344 | - | hint := event.Uint32() | |
| 345 | - | purpose := event.Uint32() | |
| 346 | - | ||
| 347 | - | for i, handler := range o.handlersForContentType() { | |
| 348 | - | _ = i | |
| 349 | - | handler(hint, purpose) | |
| 350 | - | } | |
| 351 | - | case 5: // done | |
| 352 | - | ||
| 353 | - | for i, handler := range o.handlersForDone() { | |
| 354 | - | _ = i | |
| 355 | - | handler() | |
| 356 | - | } | |
| 357 | - | case 6: // unavailable | |
| 358 | - | ||
| 359 | - | for i, handler := range o.handlersForUnavailable() { | |
| 360 | - | _ = i | |
| 361 | - | handler() | |
| 362 | - | } | |
| 363 | - | default: | |
| 364 | - | } | |
| 365 | - | } | |
| 366 | - | ||
| 367 | - | // InputPopupSurfaceInterface is the protocol interface name. | |
| 368 | - | const InputPopupSurfaceInterface = "zwp_input_popup_surface_v2" | |
| 369 | - | ||
| 370 | - | // InputPopupSurface is the generated binding for zwp_input_popup_surface_v2 version 1. | |
| 371 | - | type InputPopupSurface struct { | |
| 372 | - | wl.BaseProxy | |
| 373 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 374 | - | // handlers while another goroutine dispatches events. | |
| 375 | - | handlersMu sync.Mutex | |
| 376 | - | onTextInputRectangle []func(x int32, y int32, width int32, height int32) | |
| 377 | - | } | |
| 378 | - | ||
| 379 | - | // NewInputPopupSurface returns an unbound InputPopupSurface. | |
| 380 | - | func NewInputPopupSurface(ctx *wl.Context) *InputPopupSurface { | |
| 381 | - | obj := &InputPopupSurface{} | |
| 382 | - | obj.SetContext(ctx) | |
| 383 | - | ctx.Register(obj) | |
| 384 | - | return obj | |
| 385 | - | } | |
| 386 | - | func (o *InputPopupSurface) Destroy() error { | |
| 387 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwp_input_popup_surface_v2.destroy", Destructor: true}); err != nil { | |
| 388 | - | return err | |
| 389 | - | } | |
| 390 | - | return nil | |
| 391 | - | } | |
| 392 | - | ||
| 393 | - | // OnTextInputRectangle registers a handler for the text_input_rectangle event. | |
| 394 | - | // | |
| 395 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 396 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 397 | - | func (o *InputPopupSurface) OnTextInputRectangle(handler func(x int32, y int32, width int32, height int32)) { | |
| 398 | - | if handler == nil { | |
| 399 | - | return | |
| 400 | - | } | |
| 401 | - | o.handlersMu.Lock() | |
| 402 | - | defer o.handlersMu.Unlock() | |
| 403 | - | o.onTextInputRectangle = append(o.onTextInputRectangle, handler) | |
| 404 | - | } | |
| 405 | - | ||
| 406 | - | // handlersForTextInputRectangle returns the handlers registered for text_input_rectangle, taken | |
| 407 | - | // under the lock so a handler may register another handler while events are | |
| 408 | - | // being dispatched. | |
| 409 | - | func (o *InputPopupSurface) handlersForTextInputRectangle() []func(x int32, y int32, width int32, height int32) { | |
| 410 | - | o.handlersMu.Lock() | |
| 411 | - | defer o.handlersMu.Unlock() | |
| 412 | - | return o.onTextInputRectangle | |
| 413 | - | } | |
| 414 | - | ||
| 415 | - | // EventSignature returns the declared event argument types in wire order. | |
| 416 | - | func (o *InputPopupSurface) EventSignature(opcode uint16) (string, bool) { | |
| 417 | - | switch opcode { | |
| 418 | - | case 0: | |
| 419 | - | return "int,int,int,int,", true | |
| 420 | - | default: | |
| 421 | - | return "", false | |
| 422 | - | } | |
| 423 | - | } | |
| 424 | - | ||
| 425 | - | // Dispatch decodes one event on zwp_input_popup_surface_v2 and calls the registered handlers. | |
| 426 | - | func (o *InputPopupSurface) Dispatch(event *wl.Event) { | |
| 427 | - | switch event.Opcode { | |
| 428 | - | case 0: // text_input_rectangle | |
| 429 | - | x := event.Int32() | |
| 430 | - | y := event.Int32() | |
| 431 | - | width := event.Int32() | |
| 432 | - | height := event.Int32() | |
| 433 | - | ||
| 434 | - | for i, handler := range o.handlersForTextInputRectangle() { | |
| 435 | - | _ = i | |
| 436 | - | handler(x, y, width, height) | |
| 437 | - | } | |
| 438 | - | default: | |
| 439 | - | } | |
| 440 | - | } | |
| 441 | - | ||
| 442 | - | // InputMethodKeyboardGrabInterface is the protocol interface name. | |
| 443 | - | const InputMethodKeyboardGrabInterface = "zwp_input_method_keyboard_grab_v2" | |
| 444 | - | ||
| 445 | - | // InputMethodKeyboardGrab is the generated binding for zwp_input_method_keyboard_grab_v2 version 1. | |
| 446 | - | type InputMethodKeyboardGrab struct { | |
| 447 | - | wl.BaseProxy | |
| 448 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 449 | - | // handlers while another goroutine dispatches events. | |
| 450 | - | handlersMu sync.Mutex | |
| 451 | - | onKeymap []func(format uint32, fd *wl.OwnedFD, size uint32) | |
| 452 | - | onKey []func(serial uint32, time uint32, key uint32, state uint32) | |
| 453 | - | onModifiers []func(serial uint32, modsDepressed uint32, modsLatched uint32, modsLocked uint32, group uint32) | |
| 454 | - | onRepeatInfo []func(rate int32, delay int32) | |
| 455 | - | } | |
| 456 | - | ||
| 457 | - | // NewInputMethodKeyboardGrab returns an unbound InputMethodKeyboardGrab. | |
| 458 | - | func NewInputMethodKeyboardGrab(ctx *wl.Context) *InputMethodKeyboardGrab { | |
| 459 | - | obj := &InputMethodKeyboardGrab{} | |
| 460 | - | obj.SetContext(ctx) | |
| 461 | - | ctx.Register(obj) | |
| 462 | - | return obj | |
| 463 | - | } | |
| 464 | - | ||
| 465 | - | // release the grab object | |
| 466 | - | func (o *InputMethodKeyboardGrab) Release() error { | |
| 467 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwp_input_method_keyboard_grab_v2.release", Destructor: true}); err != nil { | |
| 468 | - | return err | |
| 469 | - | } | |
| 470 | - | return nil | |
| 471 | - | } | |
| 472 | - | ||
| 473 | - | // OnKeymap registers a handler for the keymap event. | |
| 474 | - | // | |
| 475 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 476 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 477 | - | func (o *InputMethodKeyboardGrab) OnKeymap(handler func(format uint32, fd *wl.OwnedFD, size uint32)) { | |
| 478 | - | if handler == nil { | |
| 479 | - | return | |
| 480 | - | } | |
| 481 | - | o.handlersMu.Lock() | |
| 482 | - | defer o.handlersMu.Unlock() | |
| 483 | - | o.onKeymap = append(o.onKeymap, handler) | |
| 484 | - | } | |
| 485 | - | ||
| 486 | - | // handlersForKeymap returns the handlers registered for keymap, taken | |
| 487 | - | // under the lock so a handler may register another handler while events are | |
| 488 | - | // being dispatched. | |
| 489 | - | func (o *InputMethodKeyboardGrab) handlersForKeymap() []func(format uint32, fd *wl.OwnedFD, size uint32) { | |
| 490 | - | o.handlersMu.Lock() | |
| 491 | - | defer o.handlersMu.Unlock() | |
| 492 | - | return o.onKeymap | |
| 493 | - | } | |
| 494 | - | ||
| 495 | - | // OnKey registers a handler for the key event. | |
| 496 | - | // | |
| 497 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 498 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 499 | - | func (o *InputMethodKeyboardGrab) OnKey(handler func(serial uint32, time uint32, key uint32, state uint32)) { | |
| 500 | - | if handler == nil { | |
| 501 | - | return | |
| 502 | - | } | |
| 503 | - | o.handlersMu.Lock() | |
| 504 | - | defer o.handlersMu.Unlock() | |
| 505 | - | o.onKey = append(o.onKey, handler) | |
| 506 | - | } | |
| 507 | - | ||
| 508 | - | // handlersForKey returns the handlers registered for key, taken | |
| 509 | - | // under the lock so a handler may register another handler while events are | |
| 510 | - | // being dispatched. | |
| 511 | - | func (o *InputMethodKeyboardGrab) handlersForKey() []func(serial uint32, time uint32, key uint32, state uint32) { | |
| 512 | - | o.handlersMu.Lock() | |
| 513 | - | defer o.handlersMu.Unlock() | |
| 514 | - | return o.onKey | |
| 515 | - | } | |
| 516 | - | ||
| 517 | - | // OnModifiers registers a handler for the modifiers event. | |
| 518 | - | // | |
| 519 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 520 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 521 | - | func (o *InputMethodKeyboardGrab) OnModifiers(handler func(serial uint32, modsDepressed uint32, modsLatched uint32, modsLocked uint32, group uint32)) { | |
| 522 | - | if handler == nil { | |
| 523 | - | return | |
| 524 | - | } | |
| 525 | - | o.handlersMu.Lock() | |
| 526 | - | defer o.handlersMu.Unlock() | |
| 527 | - | o.onModifiers = append(o.onModifiers, handler) | |
| 528 | - | } | |
| 529 | - | ||
| 530 | - | // handlersForModifiers returns the handlers registered for modifiers, taken | |
| 531 | - | // under the lock so a handler may register another handler while events are | |
| 532 | - | // being dispatched. | |
| 533 | - | func (o *InputMethodKeyboardGrab) handlersForModifiers() []func(serial uint32, modsDepressed uint32, modsLatched uint32, modsLocked uint32, group uint32) { | |
| 534 | - | o.handlersMu.Lock() | |
| 535 | - | defer o.handlersMu.Unlock() | |
| 536 | - | return o.onModifiers | |
| 537 | - | } | |
| 538 | - | ||
| 539 | - | // OnRepeatInfo registers a handler for the repeat_info event. | |
| 540 | - | // | |
| 541 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 542 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 543 | - | func (o *InputMethodKeyboardGrab) OnRepeatInfo(handler func(rate int32, delay int32)) { | |
| 544 | - | if handler == nil { | |
| 545 | - | return | |
| 546 | - | } | |
| 547 | - | o.handlersMu.Lock() | |
| 548 | - | defer o.handlersMu.Unlock() | |
| 549 | - | o.onRepeatInfo = append(o.onRepeatInfo, handler) | |
| 550 | - | } | |
| 551 | - | ||
| 552 | - | // handlersForRepeatInfo returns the handlers registered for repeat_info, taken | |
| 553 | - | // under the lock so a handler may register another handler while events are | |
| 554 | - | // being dispatched. | |
| 555 | - | func (o *InputMethodKeyboardGrab) handlersForRepeatInfo() []func(rate int32, delay int32) { | |
| 556 | - | o.handlersMu.Lock() | |
| 557 | - | defer o.handlersMu.Unlock() | |
| 558 | - | return o.onRepeatInfo | |
| 559 | - | } | |
| 560 | - | ||
| 561 | - | // EventSignature returns the declared event argument types in wire order. | |
| 562 | - | func (o *InputMethodKeyboardGrab) EventSignature(opcode uint16) (string, bool) { | |
| 563 | - | switch opcode { | |
| 564 | - | case 0: | |
| 565 | - | return "uint,fd,uint,", true | |
| 566 | - | case 1: | |
| 567 | - | return "uint,uint,uint,uint,", true | |
| 568 | - | case 2: | |
| 569 | - | return "uint,uint,uint,uint,uint,", true | |
| 570 | - | case 3: | |
| 571 | - | return "int,int,", true | |
| 572 | - | default: | |
| 573 | - | return "", false | |
| 574 | - | } | |
| 575 | - | } | |
| 576 | - | ||
| 577 | - | // Dispatch decodes one event on zwp_input_method_keyboard_grab_v2 and calls the registered handlers. | |
| 578 | - | func (o *InputMethodKeyboardGrab) Dispatch(event *wl.Event) { | |
| 579 | - | switch event.Opcode { | |
| 580 | - | case 0: // keymap | |
| 581 | - | format := event.Uint32() | |
| 582 | - | fd := event.FD() | |
| 583 | - | size := event.Uint32() | |
| 584 | - | ownedfd := fd | |
| 585 | - | defer ownedfd.Close() | |
| 586 | - | ||
| 587 | - | for i, handler := range o.handlersForKeymap() { | |
| 588 | - | if i > 0 { | |
| 589 | - | fd = nil | |
| 590 | - | } | |
| 591 | - | handler(format, fd, size) | |
| 592 | - | } | |
| 593 | - | case 1: // key | |
| 594 | - | serial := event.Uint32() | |
| 595 | - | time := event.Uint32() | |
| 596 | - | key := event.Uint32() | |
| 597 | - | state := event.Uint32() | |
| 598 | - | ||
| 599 | - | for i, handler := range o.handlersForKey() { | |
| 600 | - | _ = i | |
| 601 | - | handler(serial, time, key, state) | |
| 602 | - | } | |
| 603 | - | case 2: // modifiers | |
| 604 | - | serial := event.Uint32() | |
| 605 | - | modsDepressed := event.Uint32() | |
| 606 | - | modsLatched := event.Uint32() | |
| 607 | - | modsLocked := event.Uint32() | |
| 608 | - | group := event.Uint32() | |
| 609 | - | ||
| 610 | - | for i, handler := range o.handlersForModifiers() { | |
| 611 | - | _ = i | |
| 612 | - | handler(serial, modsDepressed, modsLatched, modsLocked, group) | |
| 613 | - | } | |
| 614 | - | case 3: // repeat_info | |
| 615 | - | rate := event.Int32() | |
| 616 | - | delay := event.Int32() | |
| 617 | - | ||
| 618 | - | for i, handler := range o.handlersForRepeatInfo() { | |
| 619 | - | _ = i | |
| 620 | - | handler(rate, delay) | |
| 621 | - | } | |
| 622 | - | default: | |
| 623 | - | } | |
| 624 | - | } | |
| 625 | - | ||
| 626 | - | // InputMethodManagerInterface is the protocol interface name. | |
| 627 | - | const InputMethodManagerInterface = "zwp_input_method_manager_v2" | |
| 628 | - | ||
| 629 | - | // InputMethodManager is the generated binding for zwp_input_method_manager_v2 version 1. | |
| 630 | - | type InputMethodManager struct { | |
| 631 | - | wl.BaseProxy | |
| 632 | - | } | |
| 633 | - | ||
| 634 | - | // NewInputMethodManager returns an unbound InputMethodManager. | |
| 635 | - | func NewInputMethodManager(ctx *wl.Context) *InputMethodManager { | |
| 636 | - | obj := &InputMethodManager{} | |
| 637 | - | obj.SetContext(ctx) | |
| 638 | - | ctx.Register(obj) | |
| 639 | - | return obj | |
| 640 | - | } | |
| 641 | - | ||
| 642 | - | // Request a new input zwp_input_method_v2 object associated with a given seat. | |
| 643 | - | func (o *InputMethodManager) GetInputMethod(seat *cross_wl_seat.Seat) (*InputMethod, error) { | |
| 644 | - | var arg0 wl.Object | |
| 645 | - | if seat != nil { | |
| 646 | - | arg0 = seat | |
| 647 | - | } | |
| 648 | - | child := &InputMethod{} | |
| 649 | - | child.SetContext(o.Context()) | |
| 650 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwp_input_method_manager_v2.get_input_method", Child: child}, wl.ArgObject(arg0), wl.ArgObject(child)); err != nil { | |
| 651 | - | return nil, err | |
| 652 | - | } | |
| 653 | - | return child, nil | |
| 654 | - | } | |
| 655 | - | ||
| 656 | - | // Destroys the zwp_input_method_manager_v2 object. The zwp_input_method_v2 objects originating from it remain valid. | |
| 657 | - | func (o *InputMethodManager) Destroy() error { | |
| 658 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "zwp_input_method_manager_v2.destroy", Destructor: true}); err != nil { | |
| 659 | - | return err | |
| 660 | - | } | |
| 661 | - | return nil | |
| 662 | - | } | |
| 663 | - | ||
| 664 | - | // EventSignature returns the declared event argument types in wire order. | |
| 665 | - | func (o *InputMethodManager) EventSignature(opcode uint16) (string, bool) { | |
| 666 | - | switch opcode { | |
| 667 | - | default: | |
| 668 | - | return "", false | |
| 669 | - | } | |
| 670 | - | } | |
| 671 | - | ||
| 672 | - | // Dispatch decodes one event on zwp_input_method_manager_v2 and calls the registered handlers. | |
| 673 | - | func (o *InputMethodManager) Dispatch(event *wl.Event) { | |
| 674 | - | switch event.Opcode { | |
| 675 | - | default: | |
| 676 | - | } | |
| 677 | - | } | |
D protocol/kdeserverdecoration/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package kdeserverdecoration | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p kdeserverdecoration -o server-decoration_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core server-decoration.xml | |
D protocol/kdeserverdecoration/server-decoration.xml +0 -85
| @@ -1,85 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="server_decoration"> | |
| 3 | - | <copyright><![CDATA[ | |
| 4 | - | SPDX-FileCopyrightText: 2015 Martin Gräßlin | |
| 5 | - | ||
| 6 | - | SPDX-License-Identifier: LGPL-2.1-or-later | |
| 7 | - | ]]></copyright> | |
| 8 | - | <interface name="org_kde_kwin_server_decoration_manager" version="1"> | |
| 9 | - | <description summary="Server side window decoration manager"> | |
| 10 | - | This interface allows to coordinate whether the server should create | |
| 11 | - | a server-side window decoration around a wl_surface representing a | |
| 12 | - | shell surface (wl_shell_surface or similar). By announcing support | |
| 13 | - | for this interface the server indicates that it supports server | |
| 14 | - | side decorations. | |
| 15 | - | ||
| 16 | - | Use in conjunction with zxdg_decoration_manager_v1 is undefined. | |
| 17 | - | </description> | |
| 18 | - | <request name="create"> | |
| 19 | - | <description summary="Create a server-side decoration object for a given surface"> | |
| 20 | - | When a client creates a server-side decoration object it indicates | |
| 21 | - | that it supports the protocol. The client is supposed to tell the | |
| 22 | - | server whether it wants server-side decorations or will provide | |
| 23 | - | client-side decorations. | |
| 24 | - | ||
| 25 | - | If the client does not create a server-side decoration object for | |
| 26 | - | a surface the server interprets this as lack of support for this | |
| 27 | - | protocol and considers it as client-side decorated. Nevertheless a | |
| 28 | - | client-side decorated surface should use this protocol to indicate | |
| 29 | - | to the server that it does not want a server-side deco. | |
| 30 | - | </description> | |
| 31 | - | <arg name="id" type="new_id" interface="org_kde_kwin_server_decoration"/> | |
| 32 | - | <arg name="surface" type="object" interface="wl_surface"/> | |
| 33 | - | </request> | |
| 34 | - | <enum name="mode"> | |
| 35 | - | <description summary="Possible values to use in request_mode and the event mode."/> | |
| 36 | - | <entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/> | |
| 37 | - | <entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/> | |
| 38 | - | <entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/> | |
| 39 | - | </enum> | |
| 40 | - | <event name="default_mode"> | |
| 41 | - | <description summary="The default mode used on the server"> | |
| 42 | - | This event is emitted directly after binding the interface. It contains | |
| 43 | - | the default mode for the decoration. When a new server decoration object | |
| 44 | - | is created this new object will be in the default mode until the first | |
| 45 | - | request_mode is requested. | |
| 46 | - | ||
| 47 | - | The server may change the default mode at any time. | |
| 48 | - | </description> | |
| 49 | - | <arg name="mode" type="uint" summary="The default decoration mode applied to newly created server decorations."/> | |
| 50 | - | </event> | |
| 51 | - | </interface> | |
| 52 | - | <interface name="org_kde_kwin_server_decoration" version="1"> | |
| 53 | - | <request name="release" type="destructor"> | |
| 54 | - | <description summary="release the server decoration object"/> | |
| 55 | - | </request> | |
| 56 | - | <enum name="mode"> | |
| 57 | - | <description summary="Possible values to use in request_mode and the event mode."/> | |
| 58 | - | <entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/> | |
| 59 | - | <entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/> | |
| 60 | - | <entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/> | |
| 61 | - | </enum> | |
| 62 | - | <request name="request_mode"> | |
| 63 | - | <description summary="The decoration mode the surface wants to use."/> | |
| 64 | - | <arg name="mode" type="uint" summary="The mode this surface wants to use."/> | |
| 65 | - | </request> | |
| 66 | - | <event name="mode"> | |
| 67 | - | <description summary="The new decoration mode applied by the server"> | |
| 68 | - | This event is emitted directly after the decoration is created and | |
| 69 | - | represents the base decoration policy by the server. E.g. a server | |
| 70 | - | which wants all surfaces to be client-side decorated will send Client, | |
| 71 | - | a server which wants server-side decoration will send Server. | |
| 72 | - | ||
| 73 | - | The client can request a different mode through the decoration request. | |
| 74 | - | The server will acknowledge this by another event with the same mode. So | |
| 75 | - | even if a server prefers server-side decoration it's possible to force a | |
| 76 | - | client-side decoration. | |
| 77 | - | ||
| 78 | - | The server may emit this event at any time. In this case the client can | |
| 79 | - | again request a different mode. It's the responsibility of the server to | |
| 80 | - | prevent a feedback loop. | |
| 81 | - | </description> | |
| 82 | - | <arg name="mode" type="uint" summary="The decoration mode applied to the surface by the server."/> | |
| 83 | - | </event> | |
| 84 | - | </interface> | |
| 85 | - | </protocol> | |
D protocol/kdeserverdecoration/server-decoration_generated.go +0 -197
| @@ -1,197 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: server_decoration | |
| 3 | - | // Source: server-decoration.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // SPDX-FileCopyrightText: 2015 Martin Gräßlin | |
| 7 | - | // | |
| 8 | - | // SPDX-License-Identifier: LGPL-2.1-or-later | |
| 9 | - | ||
| 10 | - | package kdeserverdecoration | |
| 11 | - | ||
| 12 | - | import ( | |
| 13 | - | "sync" | |
| 14 | - | ||
| 15 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 16 | - | "github.com/bnema/wlturbo/wl" | |
| 17 | - | ) | |
| 18 | - | ||
| 19 | - | // ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE is the mode None value. | |
| 20 | - | const ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE = 0 | |
| 21 | - | ||
| 22 | - | // ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT is the mode Client value. | |
| 23 | - | const ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT = 1 | |
| 24 | - | ||
| 25 | - | // ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER is the mode Server value. | |
| 26 | - | const ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER = 2 | |
| 27 | - | ||
| 28 | - | // ORG_KDE_KWIN_SERVER_DECORATION_MODE_NONE is the mode None value. | |
| 29 | - | const ORG_KDE_KWIN_SERVER_DECORATION_MODE_NONE = 0 | |
| 30 | - | ||
| 31 | - | // ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT is the mode Client value. | |
| 32 | - | const ORG_KDE_KWIN_SERVER_DECORATION_MODE_CLIENT = 1 | |
| 33 | - | ||
| 34 | - | // ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER is the mode Server value. | |
| 35 | - | const ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER = 2 | |
| 36 | - | ||
| 37 | - | // OrgKdeKwinServerDecorationManagerInterface is the protocol interface name. | |
| 38 | - | const OrgKdeKwinServerDecorationManagerInterface = "org_kde_kwin_server_decoration_manager" | |
| 39 | - | ||
| 40 | - | // OrgKdeKwinServerDecorationManager is the generated binding for org_kde_kwin_server_decoration_manager version 1. | |
| 41 | - | type OrgKdeKwinServerDecorationManager struct { | |
| 42 | - | wl.BaseProxy | |
| 43 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 44 | - | // handlers while another goroutine dispatches events. | |
| 45 | - | handlersMu sync.Mutex | |
| 46 | - | onDefaultMode []func(mode uint32) | |
| 47 | - | } | |
| 48 | - | ||
| 49 | - | // NewOrgKdeKwinServerDecorationManager returns an unbound OrgKdeKwinServerDecorationManager. | |
| 50 | - | func NewOrgKdeKwinServerDecorationManager(ctx *wl.Context) *OrgKdeKwinServerDecorationManager { | |
| 51 | - | obj := &OrgKdeKwinServerDecorationManager{} | |
| 52 | - | obj.SetContext(ctx) | |
| 53 | - | ctx.Register(obj) | |
| 54 | - | return obj | |
| 55 | - | } | |
| 56 | - | ||
| 57 | - | // When a client creates a server-side decoration object it indicates that it supports the protocol. The client is supposed to tell the server whether it wants server-side decorations or will provide client-side decorations. If the client does not create a server-side decoration object for a surface the server interprets this as lack of support for this protocol and considers it as client-side decorated. Nevertheless a client-side decorated surface should use this protocol to indicate to the server that it does not want a server-side deco. | |
| 58 | - | func (o *OrgKdeKwinServerDecorationManager) Create(surface *cross_wl_surface.Surface) (*OrgKdeKwinServerDecoration, error) { | |
| 59 | - | var arg1 wl.Object | |
| 60 | - | if surface != nil { | |
| 61 | - | arg1 = surface | |
| 62 | - | } | |
| 63 | - | child := &OrgKdeKwinServerDecoration{} | |
| 64 | - | child.SetContext(o.Context()) | |
| 65 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "org_kde_kwin_server_decoration_manager.create", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 66 | - | return nil, err | |
| 67 | - | } | |
| 68 | - | return child, nil | |
| 69 | - | } | |
| 70 | - | ||
| 71 | - | // OnDefaultMode registers a handler for the default_mode event. | |
| 72 | - | // | |
| 73 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 74 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 75 | - | func (o *OrgKdeKwinServerDecorationManager) OnDefaultMode(handler func(mode uint32)) { | |
| 76 | - | if handler == nil { | |
| 77 | - | return | |
| 78 | - | } | |
| 79 | - | o.handlersMu.Lock() | |
| 80 | - | defer o.handlersMu.Unlock() | |
| 81 | - | o.onDefaultMode = append(o.onDefaultMode, handler) | |
| 82 | - | } | |
| 83 | - | ||
| 84 | - | // handlersForDefaultMode returns the handlers registered for default_mode, taken | |
| 85 | - | // under the lock so a handler may register another handler while events are | |
| 86 | - | // being dispatched. | |
| 87 | - | func (o *OrgKdeKwinServerDecorationManager) handlersForDefaultMode() []func(mode uint32) { | |
| 88 | - | o.handlersMu.Lock() | |
| 89 | - | defer o.handlersMu.Unlock() | |
| 90 | - | return o.onDefaultMode | |
| 91 | - | } | |
| 92 | - | ||
| 93 | - | // EventSignature returns the declared event argument types in wire order. | |
| 94 | - | func (o *OrgKdeKwinServerDecorationManager) EventSignature(opcode uint16) (string, bool) { | |
| 95 | - | switch opcode { | |
| 96 | - | case 0: | |
| 97 | - | return "uint,", true | |
| 98 | - | default: | |
| 99 | - | return "", false | |
| 100 | - | } | |
| 101 | - | } | |
| 102 | - | ||
| 103 | - | // Dispatch decodes one event on org_kde_kwin_server_decoration_manager and calls the registered handlers. | |
| 104 | - | func (o *OrgKdeKwinServerDecorationManager) Dispatch(event *wl.Event) { | |
| 105 | - | switch event.Opcode { | |
| 106 | - | case 0: // default_mode | |
| 107 | - | mode := event.Uint32() | |
| 108 | - | ||
| 109 | - | for i, handler := range o.handlersForDefaultMode() { | |
| 110 | - | _ = i | |
| 111 | - | handler(mode) | |
| 112 | - | } | |
| 113 | - | default: | |
| 114 | - | } | |
| 115 | - | } | |
| 116 | - | ||
| 117 | - | // OrgKdeKwinServerDecorationInterface is the protocol interface name. | |
| 118 | - | const OrgKdeKwinServerDecorationInterface = "org_kde_kwin_server_decoration" | |
| 119 | - | ||
| 120 | - | // OrgKdeKwinServerDecoration is the generated binding for org_kde_kwin_server_decoration version 1. | |
| 121 | - | type OrgKdeKwinServerDecoration struct { | |
| 122 | - | wl.BaseProxy | |
| 123 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 124 | - | // handlers while another goroutine dispatches events. | |
| 125 | - | handlersMu sync.Mutex | |
| 126 | - | onMode []func(mode uint32) | |
| 127 | - | } | |
| 128 | - | ||
| 129 | - | // NewOrgKdeKwinServerDecoration returns an unbound OrgKdeKwinServerDecoration. | |
| 130 | - | func NewOrgKdeKwinServerDecoration(ctx *wl.Context) *OrgKdeKwinServerDecoration { | |
| 131 | - | obj := &OrgKdeKwinServerDecoration{} | |
| 132 | - | obj.SetContext(ctx) | |
| 133 | - | ctx.Register(obj) | |
| 134 | - | return obj | |
| 135 | - | } | |
| 136 | - | ||
| 137 | - | // release the server decoration object | |
| 138 | - | func (o *OrgKdeKwinServerDecoration) Release() error { | |
| 139 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "org_kde_kwin_server_decoration.release", Destructor: true}); err != nil { | |
| 140 | - | return err | |
| 141 | - | } | |
| 142 | - | return nil | |
| 143 | - | } | |
| 144 | - | ||
| 145 | - | // The decoration mode the surface wants to use. | |
| 146 | - | func (o *OrgKdeKwinServerDecoration) RequestMode(mode uint32) error { | |
| 147 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "org_kde_kwin_server_decoration.request_mode"}, wl.ArgUint(mode)); err != nil { | |
| 148 | - | return err | |
| 149 | - | } | |
| 150 | - | return nil | |
| 151 | - | } | |
| 152 | - | ||
| 153 | - | // OnMode registers a handler for the mode event. | |
| 154 | - | // | |
| 155 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 156 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 157 | - | func (o *OrgKdeKwinServerDecoration) OnMode(handler func(mode uint32)) { | |
| 158 | - | if handler == nil { | |
| 159 | - | return | |
| 160 | - | } | |
| 161 | - | o.handlersMu.Lock() | |
| 162 | - | defer o.handlersMu.Unlock() | |
| 163 | - | o.onMode = append(o.onMode, handler) | |
| 164 | - | } | |
| 165 | - | ||
| 166 | - | // handlersForMode returns the handlers registered for mode, taken | |
| 167 | - | // under the lock so a handler may register another handler while events are | |
| 168 | - | // being dispatched. | |
| 169 | - | func (o *OrgKdeKwinServerDecoration) handlersForMode() []func(mode uint32) { | |
| 170 | - | o.handlersMu.Lock() | |
| 171 | - | defer o.handlersMu.Unlock() | |
| 172 | - | return o.onMode | |
| 173 | - | } | |
| 174 | - | ||
| 175 | - | // EventSignature returns the declared event argument types in wire order. | |
| 176 | - | func (o *OrgKdeKwinServerDecoration) EventSignature(opcode uint16) (string, bool) { | |
| 177 | - | switch opcode { | |
| 178 | - | case 0: | |
| 179 | - | return "uint,", true | |
| 180 | - | default: | |
| 181 | - | return "", false | |
| 182 | - | } | |
| 183 | - | } | |
| 184 | - | ||
| 185 | - | // Dispatch decodes one event on org_kde_kwin_server_decoration and calls the registered handlers. | |
| 186 | - | func (o *OrgKdeKwinServerDecoration) Dispatch(event *wl.Event) { | |
| 187 | - | switch event.Opcode { | |
| 188 | - | case 0: // mode | |
| 189 | - | mode := event.Uint32() | |
| 190 | - | ||
| 191 | - | for i, handler := range o.handlersForMode() { | |
| 192 | - | _ = i | |
| 193 | - | handler(mode) | |
| 194 | - | } | |
| 195 | - | default: | |
| 196 | - | } | |
| 197 | - | } | |
D protocol/layershell/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package layershell | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p layershell -o wlr-layer-shell-unstable-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_output=github.com/bnema/wlturbo/protocol/core -import xdg_popup=github.com/bnema/wlturbo/protocol/xdgshell wlr-layer-shell-unstable-v1.xml | |
D protocol/layershell/wlr-layer-shell-unstable-v1.xml +0 -407
| @@ -1,407 +0,0 @@ | |||
| 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="5"> | |
| 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="5"> | |
| 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 | - | <entry name="invalid_exclusive_edge" value="4" summary="exclusive edge is invalid given the surface anchors"/> | |
| 371 | - | </enum> | |
| 372 | - | ||
| 373 | - | <enum name="anchor" bitfield="true"> | |
| 374 | - | <entry name="top" value="1" summary="the top edge of the anchor rectangle"/> | |
| 375 | - | <entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/> | |
| 376 | - | <entry name="left" value="4" summary="the left edge of the anchor rectangle"/> | |
| 377 | - | <entry name="right" value="8" summary="the right edge of the anchor rectangle"/> | |
| 378 | - | </enum> | |
| 379 | - | ||
| 380 | - | <!-- Version 2 additions --> | |
| 381 | - | ||
| 382 | - | <request name="set_layer" since="2"> | |
| 383 | - | <description summary="change the layer of the surface"> | |
| 384 | - | Change the layer that the surface is rendered on. | |
| 385 | - | ||
| 386 | - | Layer is double-buffered, see wl_surface.commit. | |
| 387 | - | </description> | |
| 388 | - | <arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/> | |
| 389 | - | </request> | |
| 390 | - | ||
| 391 | - | <!-- Version 5 additions --> | |
| 392 | - | ||
| 393 | - | <request name="set_exclusive_edge" since="5"> | |
| 394 | - | <description summary="set the edge the exclusive zone will be applied to"> | |
| 395 | - | Requests an edge for the exclusive zone to apply. The exclusive | |
| 396 | - | edge will be automatically deduced from anchor points when possible, | |
| 397 | - | but when the surface is anchored to a corner, it will be necessary | |
| 398 | - | to set it explicitly to disambiguate, as it is not possible to deduce | |
| 399 | - | which one of the two corner edges should be used. | |
| 400 | - | ||
| 401 | - | The edge must be one the surface is anchored to, otherwise the | |
| 402 | - | invalid_exclusive_edge protocol error will be raised. | |
| 403 | - | </description> | |
| 404 | - | <arg name="edge" type="uint" enum="anchor"/> | |
| 405 | - | </request> | |
| 406 | - | </interface> | |
| 407 | - | </protocol> | |
D protocol/layershell/wlr-layer-shell-unstable-v1_generated.go +0 -335
| @@ -1,335 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: wlr_layer_shell_unstable_v1 | |
| 3 | - | // Source: wlr-layer-shell-unstable-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2017 Drew DeVault | |
| 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 | - | ||
| 29 | - | package layershell | |
| 30 | - | ||
| 31 | - | import ( | |
| 32 | - | "sync" | |
| 33 | - | ||
| 34 | - | cross_wl_output "github.com/bnema/wlturbo/protocol/core" | |
| 35 | - | cross_wl_surface "github.com/bnema/wlturbo/protocol/core" | |
| 36 | - | cross_xdg_popup "github.com/bnema/wlturbo/protocol/xdgshell" | |
| 37 | - | "github.com/bnema/wlturbo/wl" | |
| 38 | - | ) | |
| 39 | - | ||
| 40 | - | // ERROR_ROLE is the error role value. | |
| 41 | - | const ERROR_ROLE = 0 | |
| 42 | - | ||
| 43 | - | // ERROR_INVALID_LAYER is the error invalid_layer value. | |
| 44 | - | const ERROR_INVALID_LAYER = 1 | |
| 45 | - | ||
| 46 | - | // ERROR_ALREADY_CONSTRUCTED is the error already_constructed value. | |
| 47 | - | const ERROR_ALREADY_CONSTRUCTED = 2 | |
| 48 | - | ||
| 49 | - | // LAYER_BACKGROUND is the layer background value. | |
| 50 | - | const LAYER_BACKGROUND = 0 | |
| 51 | - | ||
| 52 | - | // LAYER_BOTTOM is the layer bottom value. | |
| 53 | - | const LAYER_BOTTOM = 1 | |
| 54 | - | ||
| 55 | - | // LAYER_TOP is the layer top value. | |
| 56 | - | const LAYER_TOP = 2 | |
| 57 | - | ||
| 58 | - | // LAYER_OVERLAY is the layer overlay value. | |
| 59 | - | const LAYER_OVERLAY = 3 | |
| 60 | - | ||
| 61 | - | // KEYBOARD_INTERACTIVITY_NONE is the keyboard_interactivity none value. | |
| 62 | - | const KEYBOARD_INTERACTIVITY_NONE = 0 | |
| 63 | - | ||
| 64 | - | // KEYBOARD_INTERACTIVITY_EXCLUSIVE is the keyboard_interactivity exclusive value. | |
| 65 | - | const KEYBOARD_INTERACTIVITY_EXCLUSIVE = 1 | |
| 66 | - | ||
| 67 | - | // KEYBOARD_INTERACTIVITY_ON_DEMAND is the keyboard_interactivity on_demand value. | |
| 68 | - | const KEYBOARD_INTERACTIVITY_ON_DEMAND = 2 | |
| 69 | - | ||
| 70 | - | // ERROR_INVALID_SURFACE_STATE is the error invalid_surface_state value. | |
| 71 | - | const ERROR_INVALID_SURFACE_STATE = 0 | |
| 72 | - | ||
| 73 | - | // ERROR_INVALID_SIZE is the error invalid_size value. | |
| 74 | - | const ERROR_INVALID_SIZE = 1 | |
| 75 | - | ||
| 76 | - | // ERROR_INVALID_ANCHOR is the error invalid_anchor value. | |
| 77 | - | const ERROR_INVALID_ANCHOR = 2 | |
| 78 | - | ||
| 79 | - | // ERROR_INVALID_KEYBOARD_INTERACTIVITY is the error invalid_keyboard_interactivity value. | |
| 80 | - | const ERROR_INVALID_KEYBOARD_INTERACTIVITY = 3 | |
| 81 | - | ||
| 82 | - | // ERROR_INVALID_EXCLUSIVE_EDGE is the error invalid_exclusive_edge value. | |
| 83 | - | const ERROR_INVALID_EXCLUSIVE_EDGE = 4 | |
| 84 | - | ||
| 85 | - | // ANCHOR_TOP is the anchor top value. | |
| 86 | - | const ANCHOR_TOP = 1 | |
| 87 | - | ||
| 88 | - | // ANCHOR_BOTTOM is the anchor bottom value. | |
| 89 | - | const ANCHOR_BOTTOM = 2 | |
| 90 | - | ||
| 91 | - | // ANCHOR_LEFT is the anchor left value. | |
| 92 | - | const ANCHOR_LEFT = 4 | |
| 93 | - | ||
| 94 | - | // ANCHOR_RIGHT is the anchor right value. | |
| 95 | - | const ANCHOR_RIGHT = 8 | |
| 96 | - | ||
| 97 | - | // LayerShellInterface is the protocol interface name. | |
| 98 | - | const LayerShellInterface = "zwlr_layer_shell_v1" | |
| 99 | - | ||
| 100 | - | // LayerShell is the generated binding for zwlr_layer_shell_v1 version 5. | |
| 101 | - | type LayerShell struct { | |
| 102 | - | wl.BaseProxy | |
| 103 | - | } | |
| 104 | - | ||
| 105 | - | // NewLayerShell returns an unbound LayerShell. | |
| 106 | - | func NewLayerShell(ctx *wl.Context) *LayerShell { | |
| 107 | - | obj := &LayerShell{} | |
| 108 | - | obj.SetContext(ctx) | |
| 109 | - | ctx.Register(obj) | |
| 110 | - | return obj | |
| 111 | - | } | |
| 112 | - | ||
| 113 | - | // Create a layer surface for an existing surface. This assigns the role of layer_surface, or raises a protocol error if another role is already assigned. Creating a layer surface from a wl_surface which has a buffer attached or committed is a client error, and any attempts by a client to attach or manipulate a buffer prior to the first layer_surface.configure call must also be treated as errors. After creating a layer_surface object and setting it up, the client must perform an initial commit without any buffer attached. The compositor will reply with a layer_surface.configure event. The client must acknowledge it and is then allowed to attach a buffer to map the surface. You may pass NULL for output to allow the compositor to decide which output to use. Generally this will be the one that the user most recently interacted with. Clients can specify a namespace that defines the purpose of the layer surface. | |
| 114 | - | func (o *LayerShell) GetLayerSurface(surface *cross_wl_surface.Surface, output *cross_wl_output.Output, layer uint32, namespace string) (*LayerSurface, error) { | |
| 115 | - | var arg1 wl.Object | |
| 116 | - | if surface != nil { | |
| 117 | - | arg1 = surface | |
| 118 | - | } | |
| 119 | - | var arg2 wl.Object | |
| 120 | - | if output != nil { | |
| 121 | - | arg2 = output | |
| 122 | - | } | |
| 123 | - | child := &LayerSurface{} | |
| 124 | - | child.SetContext(o.Context()) | |
| 125 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwlr_layer_shell_v1.get_layer_surface", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1), wl.ArgObject(arg2), wl.ArgUint(layer), wl.ArgString(namespace)); err != nil { | |
| 126 | - | return nil, err | |
| 127 | - | } | |
| 128 | - | return child, nil | |
| 129 | - | } | |
| 130 | - | ||
| 131 | - | // This request indicates that the client will not use the layer_shell object any more. Objects that have been created through this instance are not affected. | |
| 132 | - | func (o *LayerShell) Destroy() error { | |
| 133 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "zwlr_layer_shell_v1.destroy", Since: 3, Destructor: true}); err != nil { | |
| 134 | - | return err | |
| 135 | - | } | |
| 136 | - | return nil | |
| 137 | - | } | |
| 138 | - | ||
| 139 | - | // EventSignature returns the declared event argument types in wire order. | |
| 140 | - | func (o *LayerShell) EventSignature(opcode uint16) (string, bool) { | |
| 141 | - | switch opcode { | |
| 142 | - | default: | |
| 143 | - | return "", false | |
| 144 | - | } | |
| 145 | - | } | |
| 146 | - | ||
| 147 | - | // Dispatch decodes one event on zwlr_layer_shell_v1 and calls the registered handlers. | |
| 148 | - | func (o *LayerShell) Dispatch(event *wl.Event) { | |
| 149 | - | switch event.Opcode { | |
| 150 | - | default: | |
| 151 | - | } | |
| 152 | - | } | |
| 153 | - | ||
| 154 | - | // LayerSurfaceInterface is the protocol interface name. | |
| 155 | - | const LayerSurfaceInterface = "zwlr_layer_surface_v1" | |
| 156 | - | ||
| 157 | - | // LayerSurface is the generated binding for zwlr_layer_surface_v1 version 5. | |
| 158 | - | type LayerSurface struct { | |
| 159 | - | wl.BaseProxy | |
| 160 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 161 | - | // handlers while another goroutine dispatches events. | |
| 162 | - | handlersMu sync.Mutex | |
| 163 | - | onConfigure []func(serial uint32, width uint32, height uint32) | |
| 164 | - | onClosed []func() | |
| 165 | - | } | |
| 166 | - | ||
| 167 | - | // NewLayerSurface returns an unbound LayerSurface. | |
| 168 | - | func NewLayerSurface(ctx *wl.Context) *LayerSurface { | |
| 169 | - | obj := &LayerSurface{} | |
| 170 | - | obj.SetContext(ctx) | |
| 171 | - | ctx.Register(obj) | |
| 172 | - | return obj | |
| 173 | - | } | |
| 174 | - | ||
| 175 | - | // Sets the size of the surface in surface-local coordinates. The compositor will display the surface centered with respect to its anchors. If you pass 0 for either value, the compositor will assign it and inform you of the assignment in the configure event. You must set your anchor to opposite edges in the dimensions you omit; not doing so is a protocol error. Both values are 0 by default. Size is double-buffered, see wl_surface.commit. | |
| 176 | - | func (o *LayerSurface) SetSize(width uint32, height uint32) error { | |
| 177 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwlr_layer_surface_v1.set_size"}, wl.ArgUint(width), wl.ArgUint(height)); err != nil { | |
| 178 | - | return err | |
| 179 | - | } | |
| 180 | - | return nil | |
| 181 | - | } | |
| 182 | - | ||
| 183 | - | // Requests that the compositor anchor the surface to the specified edges and corners. If two orthogonal edges are specified (e.g. 'top' and 'left'), then the anchor point will be the intersection of the edges (e.g. the top left corner of the output); otherwise the anchor point will be centered on that edge, or in the center if none is specified. Anchor is double-buffered, see wl_surface.commit. | |
| 184 | - | func (o *LayerSurface) SetAnchor(anchor uint32) error { | |
| 185 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "zwlr_layer_surface_v1.set_anchor"}, wl.ArgUint(anchor)); err != nil { | |
| 186 | - | return err | |
| 187 | - | } | |
| 188 | - | return nil | |
| 189 | - | } | |
| 190 | - | ||
| 191 | - | // Requests that the compositor avoids occluding an area with other surfaces. The compositor's use of this information is implementation-dependent - do not assume that this region will not actually be occluded. A positive value is only meaningful if the surface is anchored to one edge or an edge and both perpendicular edges. If the surface is not anchored, anchored to only two perpendicular edges (a corner), anchored to only two parallel edges or anchored to all edges, a positive value will be treated the same as zero. A positive zone is the distance from the edge in surface-local coordinates to consider exclusive. Surfaces that do not wish to have an exclusive zone may instead specify how they should interact with surfaces that do. If set to zero, the surface indicates that it would like to be moved to avoid occluding surfaces with a positive exclusive zone. If set to -1, the surface indicates that it would not like to be moved to accommodate for other surfaces, and the compositor should extend it all the way to the edges it is anchored to. For example, a panel might set its exclusive zone to 10, so that maximized shell surfaces are not shown on top of it. A notification might set its exclusive zone to 0, so that it is moved to avoid occluding the panel, but shell surfaces are shown underneath it. A wallpaper or lock screen might set their exclusive zone to -1, so that they stretch below or over the panel. The default value is 0. Exclusive zone is double-buffered, see wl_surface.commit. | |
| 192 | - | func (o *LayerSurface) SetExclusiveZone(zone int32) error { | |
| 193 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 2, Name: "zwlr_layer_surface_v1.set_exclusive_zone"}, wl.ArgInt(zone)); err != nil { | |
| 194 | - | return err | |
| 195 | - | } | |
| 196 | - | return nil | |
| 197 | - | } | |
| 198 | - | ||
| 199 | - | // Requests that the surface be placed some distance away from the anchor point on the output, in surface-local coordinates. Setting this value for edges you are not anchored to has no effect. The exclusive zone includes the margin. Margin is double-buffered, see wl_surface.commit. | |
| 200 | - | func (o *LayerSurface) SetMargin(top int32, right int32, bottom int32, left int32) error { | |
| 201 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 3, Name: "zwlr_layer_surface_v1.set_margin"}, wl.ArgInt(top), wl.ArgInt(right), wl.ArgInt(bottom), wl.ArgInt(left)); err != nil { | |
| 202 | - | return err | |
| 203 | - | } | |
| 204 | - | return nil | |
| 205 | - | } | |
| 206 | - | ||
| 207 | - | // Set how keyboard events are delivered to this surface. By default, layer shell surfaces do not receive keyboard events; this request can be used to change this. This setting is inherited by child surfaces set by the get_popup request. Layer surfaces receive pointer, touch, and tablet events normally. If you do not want to receive them, set the input region on your surface to an empty region. Keyboard interactivity is double-buffered, see wl_surface.commit. | |
| 208 | - | func (o *LayerSurface) SetKeyboardInteractivity(keyboardInteractivity uint32) error { | |
| 209 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 4, Name: "zwlr_layer_surface_v1.set_keyboard_interactivity"}, wl.ArgUint(keyboardInteractivity)); err != nil { | |
| 210 | - | return err | |
| 211 | - | } | |
| 212 | - | return nil | |
| 213 | - | } | |
| 214 | - | ||
| 215 | - | // This assigns an xdg_popup's parent to this layer_surface. This popup should have been created via xdg_surface::get_popup with the parent set to NULL, and this request must be invoked before committing the popup's initial state. See the documentation of xdg_popup for more details about what an xdg_popup is and how it is used. | |
| 216 | - | func (o *LayerSurface) GetPopup(popup *cross_xdg_popup.XdgPopup) error { | |
| 217 | - | var arg0 wl.Object | |
| 218 | - | if popup != nil { | |
| 219 | - | arg0 = popup | |
| 220 | - | } | |
| 221 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 5, Name: "zwlr_layer_surface_v1.get_popup"}, wl.ArgObject(arg0)); err != nil { | |
| 222 | - | return err | |
| 223 | - | } | |
| 224 | - | return nil | |
| 225 | - | } | |
| 226 | - | ||
| 227 | - | // When a configure event is received, if a client commits the surface in response to the configure event, then the client must make an ack_configure request sometime before the commit request, passing along the serial of the configure event. If the client receives multiple configure events before it can respond to one, it only has to ack the last configure event. A client is not required to commit immediately after sending an ack_configure request - it may even ack_configure several times before its next surface commit. A client may send multiple ack_configure requests before committing, but only the last request sent before a commit indicates which configure event the client really is responding to. | |
| 228 | - | func (o *LayerSurface) AckConfigure(serial uint32) error { | |
| 229 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 6, Name: "zwlr_layer_surface_v1.ack_configure"}, wl.ArgUint(serial)); err != nil { | |
| 230 | - | return err | |
| 231 | - | } | |
| 232 | - | return nil | |
| 233 | - | } | |
| 234 | - | ||
| 235 | - | // This request destroys the layer surface. | |
| 236 | - | func (o *LayerSurface) Destroy() error { | |
| 237 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 7, Name: "zwlr_layer_surface_v1.destroy", Destructor: true}); err != nil { | |
| 238 | - | return err | |
| 239 | - | } | |
| 240 | - | return nil | |
| 241 | - | } | |
| 242 | - | ||
| 243 | - | // Change the layer that the surface is rendered on. Layer is double-buffered, see wl_surface.commit. | |
| 244 | - | func (o *LayerSurface) SetLayer(layer uint32) error { | |
| 245 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 8, Name: "zwlr_layer_surface_v1.set_layer", Since: 2}, wl.ArgUint(layer)); err != nil { | |
| 246 | - | return err | |
| 247 | - | } | |
| 248 | - | return nil | |
| 249 | - | } | |
| 250 | - | ||
| 251 | - | // Requests an edge for the exclusive zone to apply. The exclusive edge will be automatically deduced from anchor points when possible, but when the surface is anchored to a corner, it will be necessary to set it explicitly to disambiguate, as it is not possible to deduce which one of the two corner edges should be used. The edge must be one the surface is anchored to, otherwise the invalid_exclusive_edge protocol error will be raised. | |
| 252 | - | func (o *LayerSurface) SetExclusiveEdge(edge uint32) error { | |
| 253 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 9, Name: "zwlr_layer_surface_v1.set_exclusive_edge", Since: 5}, wl.ArgUint(edge)); err != nil { | |
| 254 | - | return err | |
| 255 | - | } | |
| 256 | - | return nil | |
| 257 | - | } | |
| 258 | - | ||
| 259 | - | // OnConfigure registers a handler for the configure event. | |
| 260 | - | // | |
| 261 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 262 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 263 | - | func (o *LayerSurface) OnConfigure(handler func(serial uint32, width uint32, height uint32)) { | |
| 264 | - | if handler == nil { | |
| 265 | - | return | |
| 266 | - | } | |
| 267 | - | o.handlersMu.Lock() | |
| 268 | - | defer o.handlersMu.Unlock() | |
| 269 | - | o.onConfigure = append(o.onConfigure, handler) | |
| 270 | - | } | |
| 271 | - | ||
| 272 | - | // handlersForConfigure returns the handlers registered for configure, taken | |
| 273 | - | // under the lock so a handler may register another handler while events are | |
| 274 | - | // being dispatched. | |
| 275 | - | func (o *LayerSurface) handlersForConfigure() []func(serial uint32, width uint32, height uint32) { | |
| 276 | - | o.handlersMu.Lock() | |
| 277 | - | defer o.handlersMu.Unlock() | |
| 278 | - | return o.onConfigure | |
| 279 | - | } | |
| 280 | - | ||
| 281 | - | // OnClosed registers a handler for the closed event. | |
| 282 | - | // | |
| 283 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 284 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 285 | - | func (o *LayerSurface) OnClosed(handler func()) { | |
| 286 | - | if handler == nil { | |
| 287 | - | return | |
| 288 | - | } | |
| 289 | - | o.handlersMu.Lock() | |
| 290 | - | defer o.handlersMu.Unlock() | |
| 291 | - | o.onClosed = append(o.onClosed, handler) | |
| 292 | - | } | |
| 293 | - | ||
| 294 | - | // handlersForClosed returns the handlers registered for closed, taken | |
| 295 | - | // under the lock so a handler may register another handler while events are | |
| 296 | - | // being dispatched. | |
| 297 | - | func (o *LayerSurface) handlersForClosed() []func() { | |
| 298 | - | o.handlersMu.Lock() | |
| 299 | - | defer o.handlersMu.Unlock() | |
| 300 | - | return o.onClosed | |
| 301 | - | } | |
| 302 | - | ||
| 303 | - | // EventSignature returns the declared event argument types in wire order. | |
| 304 | - | func (o *LayerSurface) EventSignature(opcode uint16) (string, bool) { | |
| 305 | - | switch opcode { | |
| 306 | - | case 0: | |
| 307 | - | return "uint,uint,uint,", true | |
| 308 | - | case 1: | |
| 309 | - | return "", true | |
| 310 | - | default: | |
| 311 | - | return "", false | |
| 312 | - | } | |
| 313 | - | } | |
| 314 | - | ||
| 315 | - | // Dispatch decodes one event on zwlr_layer_surface_v1 and calls the registered handlers. | |
| 316 | - | func (o *LayerSurface) Dispatch(event *wl.Event) { | |
| 317 | - | switch event.Opcode { | |
| 318 | - | case 0: // configure | |
| 319 | - | serial := event.Uint32() | |
| 320 | - | width := event.Uint32() | |
| 321 | - | height := event.Uint32() | |
| 322 | - | ||
| 323 | - | for i, handler := range o.handlersForConfigure() { | |
| 324 | - | _ = i | |
| 325 | - | handler(serial, width, height) | |
| 326 | - | } | |
| 327 | - | case 1: // closed | |
| 328 | - | ||
| 329 | - | for i, handler := range o.handlersForClosed() { | |
| 330 | - | _ = i | |
| 331 | - | handler() | |
| 332 | - | } | |
| 333 | - | default: | |
| 334 | - | } | |
| 335 | - | } | |
D protocol/linuxdmabuf/linux-dmabuf-v1.xml +0 -623 collapsed to keep the page light
D protocol/linuxdmabuf/linux-dmabuf-v1_generated.go +0 -630 collapsed to keep the page light
D protocol/linuxdmabuf/table.go +0 -68
| @@ -1,68 +0,0 @@ | |||
| 1 | - | package linuxdmabuf | |
| 2 | - | ||
| 3 | - | import ( | |
| 4 | - | "encoding/binary" | |
| 5 | - | "fmt" | |
| 6 | - | "io" | |
| 7 | - | ||
| 8 | - | "github.com/bnema/wlturbo/wl" | |
| 9 | - | "golang.org/x/sys/unix" | |
| 10 | - | ) | |
| 11 | - | ||
| 12 | - | // FormatEntry is one 16-byte format-table record. Padding is ignored. | |
| 13 | - | type FormatEntry struct { | |
| 14 | - | Format uint32 | |
| 15 | - | Modifier uint64 | |
| 16 | - | } | |
| 17 | - | ||
| 18 | - | // ReadFormatTable consumes an owned format_table descriptor, even on error. | |
| 19 | - | // It reads a bounded snapshot with pread rather than mapping compositor-owned | |
| 20 | - | // memory, avoiding SIGBUS if the backing file is unexpectedly truncated. | |
| 21 | - | func ReadFormatTable(fd *wl.OwnedFD, size uint32) ([]FormatEntry, error) { | |
| 22 | - | if fd == nil { | |
| 23 | - | return nil, fmt.Errorf("missing format table descriptor") | |
| 24 | - | } | |
| 25 | - | n, err := fd.Take() | |
| 26 | - | if err != nil { | |
| 27 | - | return nil, err | |
| 28 | - | } | |
| 29 | - | defer unix.Close(n) | |
| 30 | - | if size%16 != 0 || size > 16<<20 { | |
| 31 | - | return nil, fmt.Errorf("invalid format table size %d", size) | |
| 32 | - | } | |
| 33 | - | b := make([]byte, size) | |
| 34 | - | for off := 0; off < len(b); { | |
| 35 | - | read, e := unix.Pread(n, b[off:], int64(off)) | |
| 36 | - | off += read | |
| 37 | - | if e == unix.EINTR { | |
| 38 | - | continue | |
| 39 | - | } | |
| 40 | - | if e != nil { | |
| 41 | - | return nil, e | |
| 42 | - | } | |
| 43 | - | if read == 0 { | |
| 44 | - | return nil, io.ErrUnexpectedEOF | |
| 45 | - | } | |
| 46 | - | } | |
| 47 | - | entries := make([]FormatEntry, size/16) | |
| 48 | - | for i := range entries { | |
| 49 | - | off := i * 16 | |
| 50 | - | entries[i] = FormatEntry{binary.NativeEndian.Uint32(b[off:]), binary.NativeEndian.Uint64(b[off+8:])} | |
| 51 | - | } | |
| 52 | - | return entries, nil | |
| 53 | - | } | |
| 54 | - | ||
| 55 | - | // TrancheIndices decodes the uint16 indices into a format table. | |
| 56 | - | func TrancheIndices(data []byte, count int) ([]uint16, error) { | |
| 57 | - | if len(data)%2 != 0 { | |
| 58 | - | return nil, fmt.Errorf("odd tranche indices length") | |
| 59 | - | } | |
| 60 | - | indices := make([]uint16, len(data)/2) | |
| 61 | - | for i := range indices { | |
| 62 | - | indices[i] = binary.NativeEndian.Uint16(data[i*2:]) | |
| 63 | - | if int(indices[i]) >= count { | |
| 64 | - | return nil, fmt.Errorf("format table index %d out of range", indices[i]) | |
| 65 | - | } | |
| 66 | - | } | |
| 67 | - | return indices, nil | |
| 68 | - | } | |
D protocol/linuxdmabuf/table_test.go +0 -28
| @@ -1,28 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package linuxdmabuf_test | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "encoding/binary" | |
| 7 | - | "github.com/bnema/wlturbo/protocol/linuxdmabuf" | |
| 8 | - | "testing" | |
| 9 | - | ) | |
| 10 | - | ||
| 11 | - | func TestTrancheIndices(t *testing.T) { | |
| 12 | - | b := make([]byte, 4) | |
| 13 | - | binary.NativeEndian.PutUint16(b, 1) | |
| 14 | - | binary.NativeEndian.PutUint16(b[2:], 0) | |
| 15 | - | got, e := linuxdmabuf.TrancheIndices(b, 2) | |
| 16 | - | if e != nil || len(got) != 2 || got[0] != 1 || got[1] != 0 { | |
| 17 | - | t.Fatalf("indices %v %v", got, e) | |
| 18 | - | } | |
| 19 | - | if _, e = linuxdmabuf.TrancheIndices(b, 1); e == nil { | |
| 20 | - | t.Fatal("out of range accepted") | |
| 21 | - | } | |
| 22 | - | if _, e = linuxdmabuf.TrancheIndices(b[:3], 2); e == nil { | |
| 23 | - | t.Fatal("odd length accepted") | |
| 24 | - | } | |
| 25 | - | if _, e = linuxdmabuf.ReadFormatTable(nil, 0); e == nil { | |
| 26 | - | t.Fatal("missing fd accepted") | |
| 27 | - | } | |
| 28 | - | } | |
D protocol/negotiation_test.go +0 -50
| @@ -1,50 +0,0 @@ | |||
| 1 | - | //go:build linux | |
| 2 | - | ||
| 3 | - | package protocol_test | |
| 4 | - | ||
| 5 | - | import ( | |
| 6 | - | "encoding/binary" | |
| 7 | - | "errors" | |
| 8 | - | "testing" | |
| 9 | - | ||
| 10 | - | "github.com/bnema/wlturbo" | |
| 11 | - | "github.com/bnema/wlturbo/protocol/xdgshell" | |
| 12 | - | ) | |
| 13 | - | ||
| 14 | - | func TestAnnouncedVersionNegotiation(t *testing.T) { | |
| 15 | - | c, p := pair(t) | |
| 16 | - | d, e := wlturbo.ConnectFromConn(c) | |
| 17 | - | noerr(t, e) | |
| 18 | - | defer d.Close() | |
| 19 | - | request(t, p) | |
| 20 | - | iface := xdgshell.XdgWmBaseInterface | |
| 21 | - | if v, e := d.Registry().BindNegotiated(iface, 6, xdgshell.NewXdgWmBase(d.Context())); v != 0 || !errors.Is(e, wlturbo.ErrGlobalNotFound) { | |
| 22 | - | t.Fatalf("missing: %d %v", v, e) | |
| 23 | - | } | |
| 24 | - | if v, e := d.Registry().BindNegotiated(iface, 0, xdgshell.NewXdgWmBase(d.Context())); v != 0 || e == nil || errors.Is(e, wlturbo.ErrGlobalNotFound) { | |
| 25 | - | t.Fatalf("unsupported zero: %d %v", v, e) | |
| 26 | - | } | |
| 27 | - | for i, version := range []uint32{2, 9} { | |
| 28 | - | name := uint32(30 + i) | |
| 29 | - | announcement := append(msg(0, 0, name)[8:], str(iface)...) | |
| 30 | - | announcement = append(announcement, msg(0, 0, version)[8:]...) | |
| 31 | - | send(t, p, payload(d.Registry().ID(), 0, announcement...)) | |
| 32 | - | noerr(t, d.Dispatch()) | |
| 33 | - | proxy := xdgshell.NewXdgWmBase(d.Context()) | |
| 34 | - | if v, e := d.Registry().BindNegotiated(iface, 0, proxy); v != 0 || e == nil || errors.Is(e, wlturbo.ErrGlobalNotFound) { | |
| 35 | - | t.Fatalf("supported zero with global: %d %v", v, e) | |
| 36 | - | } | |
| 37 | - | negotiated, e := d.Registry().BindNegotiated(iface, 6, proxy) | |
| 38 | - | noerr(t, e) | |
| 39 | - | want := version | |
| 40 | - | if want > 6 { | |
| 41 | - | want = 6 | |
| 42 | - | } | |
| 43 | - | _, op, body := request(t, p) | |
| 44 | - | if op != 0 || negotiated != want || binary.NativeEndian.Uint32(body) != name || binary.NativeEndian.Uint32(body[len(body)-8:]) != want || binary.NativeEndian.Uint32(body[len(body)-4:]) != proxy.ID() { | |
| 45 | - | t.Fatalf("server=%d negotiated=%d wire=%x", version, negotiated, body) | |
| 46 | - | } | |
| 47 | - | send(t, p, msg(d.Registry().ID(), 1, name)) | |
| 48 | - | noerr(t, d.Dispatch()) | |
| 49 | - | } | |
| 50 | - | } | |
D protocol/outputmanagement/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package outputmanagement | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p outputmanagement -o wlr-output-management-unstable-v1_generated.go wlr-output-management-unstable-v1.xml | |
D protocol/outputmanagement/wlr-output-management-unstable-v1.xml +0 -611 collapsed to keep the page light
D protocol/outputmanagement/wlr-output-management-unstable-v1_generated.go +0 -1146 collapsed to keep the page light
D protocol/outputpower/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package outputpower | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p outputpower -o wlr-output-power-management-unstable-v1_generated.go -import wl_output=github.com/bnema/wlturbo/protocol/core wlr-output-power-management-unstable-v1.xml | |
D protocol/outputpower/wlr-output-power-management-unstable-v1.xml +0 -128
| @@ -1,128 +0,0 @@ | |||
| 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 an 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="nonexistent 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> | |
D protocol/outputpower/wlr-output-power-management-unstable-v1_generated.go +0 -209
| @@ -1,209 +0,0 @@ | |||
| 1 | - | // Code generated by wlturbo-scanner. DO NOT EDIT. | |
| 2 | - | // Protocol: wlr_output_power_management_unstable_v1 | |
| 3 | - | // Source: wlr-output-power-management-unstable-v1.xml | |
| 4 | - | ||
| 5 | - | // Upstream protocol copyright and license: | |
| 6 | - | // Copyright © 2019 Purism SPC | |
| 7 | - | // | |
| 8 | - | // Permission is hereby granted, free of charge, to any person obtaining a | |
| 9 | - | // copy of this software and associated documentation files (the "Software"), | |
| 10 | - | // to deal in the Software without restriction, including without limitation | |
| 11 | - | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 12 | - | // and/or sell copies of the Software, and to permit persons to whom the | |
| 13 | - | // Software is furnished to do so, subject to the following conditions: | |
| 14 | - | // | |
| 15 | - | // The above copyright notice and this permission notice (including the next | |
| 16 | - | // paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | // Software. | |
| 18 | - | // | |
| 19 | - | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | - | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | - | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 22 | - | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | - | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 24 | - | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 25 | - | // DEALINGS IN THE SOFTWARE. | |
| 26 | - | ||
| 27 | - | package outputpower | |
| 28 | - | ||
| 29 | - | import ( | |
| 30 | - | "sync" | |
| 31 | - | ||
| 32 | - | cross_wl_output "github.com/bnema/wlturbo/protocol/core" | |
| 33 | - | "github.com/bnema/wlturbo/wl" | |
| 34 | - | ) | |
| 35 | - | ||
| 36 | - | // MODE_OFF is the mode off value. | |
| 37 | - | const MODE_OFF = 0 | |
| 38 | - | ||
| 39 | - | // MODE_ON is the mode on value. | |
| 40 | - | const MODE_ON = 1 | |
| 41 | - | ||
| 42 | - | // ERROR_INVALID_MODE is the error invalid_mode value. | |
| 43 | - | const ERROR_INVALID_MODE = 1 | |
| 44 | - | ||
| 45 | - | // OutputPowerManagerInterface is the protocol interface name. | |
| 46 | - | const OutputPowerManagerInterface = "zwlr_output_power_manager_v1" | |
| 47 | - | ||
| 48 | - | // OutputPowerManager is the generated binding for zwlr_output_power_manager_v1 version 1. | |
| 49 | - | type OutputPowerManager struct { | |
| 50 | - | wl.BaseProxy | |
| 51 | - | } | |
| 52 | - | ||
| 53 | - | // NewOutputPowerManager returns an unbound OutputPowerManager. | |
| 54 | - | func NewOutputPowerManager(ctx *wl.Context) *OutputPowerManager { | |
| 55 | - | obj := &OutputPowerManager{} | |
| 56 | - | obj.SetContext(ctx) | |
| 57 | - | ctx.Register(obj) | |
| 58 | - | return obj | |
| 59 | - | } | |
| 60 | - | ||
| 61 | - | // Create an output power management mode control that can be used to adjust the power management mode for a given output. | |
| 62 | - | func (o *OutputPowerManager) GetOutputPower(output *cross_wl_output.Output) (*OutputPower, error) { | |
| 63 | - | var arg1 wl.Object | |
| 64 | - | if output != nil { | |
| 65 | - | arg1 = output | |
| 66 | - | } | |
| 67 | - | child := &OutputPower{} | |
| 68 | - | child.SetContext(o.Context()) | |
| 69 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwlr_output_power_manager_v1.get_output_power", Child: child}, wl.ArgObject(child), wl.ArgObject(arg1)); err != nil { | |
| 70 | - | return nil, err | |
| 71 | - | } | |
| 72 | - | return child, nil | |
| 73 | - | } | |
| 74 | - | ||
| 75 | - | // All objects created by the manager will still remain valid, until their appropriate destroy request has been called. | |
| 76 | - | func (o *OutputPowerManager) Destroy() error { | |
| 77 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "zwlr_output_power_manager_v1.destroy", Destructor: true}); err != nil { | |
| 78 | - | return err | |
| 79 | - | } | |
| 80 | - | return nil | |
| 81 | - | } | |
| 82 | - | ||
| 83 | - | // EventSignature returns the declared event argument types in wire order. | |
| 84 | - | func (o *OutputPowerManager) EventSignature(opcode uint16) (string, bool) { | |
| 85 | - | switch opcode { | |
| 86 | - | default: | |
| 87 | - | return "", false | |
| 88 | - | } | |
| 89 | - | } | |
| 90 | - | ||
| 91 | - | // Dispatch decodes one event on zwlr_output_power_manager_v1 and calls the registered handlers. | |
| 92 | - | func (o *OutputPowerManager) Dispatch(event *wl.Event) { | |
| 93 | - | switch event.Opcode { | |
| 94 | - | default: | |
| 95 | - | } | |
| 96 | - | } | |
| 97 | - | ||
| 98 | - | // OutputPowerInterface is the protocol interface name. | |
| 99 | - | const OutputPowerInterface = "zwlr_output_power_v1" | |
| 100 | - | ||
| 101 | - | // OutputPower is the generated binding for zwlr_output_power_v1 version 1. | |
| 102 | - | type OutputPower struct { | |
| 103 | - | wl.BaseProxy | |
| 104 | - | // handlersMu guards the handler slices: a client may register or replace | |
| 105 | - | // handlers while another goroutine dispatches events. | |
| 106 | - | handlersMu sync.Mutex | |
| 107 | - | onMode []func(mode uint32) | |
| 108 | - | onFailed []func() | |
| 109 | - | } | |
| 110 | - | ||
| 111 | - | // NewOutputPower returns an unbound OutputPower. | |
| 112 | - | func NewOutputPower(ctx *wl.Context) *OutputPower { | |
| 113 | - | obj := &OutputPower{} | |
| 114 | - | obj.SetContext(ctx) | |
| 115 | - | ctx.Register(obj) | |
| 116 | - | return obj | |
| 117 | - | } | |
| 118 | - | ||
| 119 | - | // Set an output's power save mode to the given mode. The mode change is effective immediately. If the output does not support the given mode a failed event is sent. | |
| 120 | - | func (o *OutputPower) SetMode(mode uint32) error { | |
| 121 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 0, Name: "zwlr_output_power_v1.set_mode"}, wl.ArgUint(mode)); err != nil { | |
| 122 | - | return err | |
| 123 | - | } | |
| 124 | - | return nil | |
| 125 | - | } | |
| 126 | - | ||
| 127 | - | // Destroys the output power management mode control object. | |
| 128 | - | func (o *OutputPower) Destroy() error { | |
| 129 | - | if err := o.Context().RequestArgs(wl.Request{Proxy: o, Opcode: 1, Name: "zwlr_output_power_v1.destroy", Destructor: true}); err != nil { | |
| 130 | - | return err | |
| 131 | - | } | |
| 132 | - | return nil | |
| 133 | - | } | |
| 134 | - | ||
| 135 | - | // OnMode registers a handler for the mode event. | |
| 136 | - | // | |
| 137 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 138 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 139 | - | func (o *OutputPower) OnMode(handler func(mode uint32)) { | |
| 140 | - | if handler == nil { | |
| 141 | - | return | |
| 142 | - | } | |
| 143 | - | o.handlersMu.Lock() | |
| 144 | - | defer o.handlersMu.Unlock() | |
| 145 | - | o.onMode = append(o.onMode, handler) | |
| 146 | - | } | |
| 147 | - | ||
| 148 | - | // handlersForMode returns the handlers registered for mode, taken | |
| 149 | - | // under the lock so a handler may register another handler while events are | |
| 150 | - | // being dispatched. | |
| 151 | - | func (o *OutputPower) handlersForMode() []func(mode uint32) { | |
| 152 | - | o.handlersMu.Lock() | |
| 153 | - | defer o.handlersMu.Unlock() | |
| 154 | - | return o.onMode | |
| 155 | - | } | |
| 156 | - | ||
| 157 | - | // OnFailed registers a handler for the failed event. | |
| 158 | - | // | |
| 159 | - | // Handlers are appended, so a second call adds another handler rather than | |
| 160 | - | // replacing the first. Registration is safe while another goroutine dispatches. | |
| 161 | - | func (o *OutputPower) OnFailed(handler func()) { | |
| 162 | - | if handler == nil { | |
| 163 | - | return | |
| 164 | - | } | |
| 165 | - | o.handlersMu.Lock() | |
| 166 | - | defer o.handlersMu.Unlock() | |
| 167 | - | o.onFailed = append(o.onFailed, handler) | |
| 168 | - | } | |
| 169 | - | ||
| 170 | - | // handlersForFailed returns the handlers registered for failed, taken | |
| 171 | - | // under the lock so a handler may register another handler while events are | |
| 172 | - | // being dispatched. | |
| 173 | - | func (o *OutputPower) handlersForFailed() []func() { | |
| 174 | - | o.handlersMu.Lock() | |
| 175 | - | defer o.handlersMu.Unlock() | |
| 176 | - | return o.onFailed | |
| 177 | - | } | |
| 178 | - | ||
| 179 | - | // EventSignature returns the declared event argument types in wire order. | |
| 180 | - | func (o *OutputPower) EventSignature(opcode uint16) (string, bool) { | |
| 181 | - | switch opcode { | |
| 182 | - | case 0: | |
| 183 | - | return "uint,", true | |
| 184 | - | case 1: | |
| 185 | - | return "", true | |
| 186 | - | default: | |
| 187 | - | return "", false | |
| 188 | - | } | |
| 189 | - | } | |
| 190 | - | ||
| 191 | - | // Dispatch decodes one event on zwlr_output_power_v1 and calls the registered handlers. | |
| 192 | - | func (o *OutputPower) Dispatch(event *wl.Event) { | |
| 193 | - | switch event.Opcode { | |
| 194 | - | case 0: // mode | |
| 195 | - | mode := event.Uint32() | |
| 196 | - | ||
| 197 | - | for i, handler := range o.handlersForMode() { | |
| 198 | - | _ = i | |
| 199 | - | handler(mode) | |
| 200 | - | } | |
| 201 | - | case 1: // failed | |
| 202 | - | ||
| 203 | - | for i, handler := range o.handlersForFailed() { | |
| 204 | - | _ = i | |
| 205 | - | handler() | |
| 206 | - | } | |
| 207 | - | default: | |
| 208 | - | } | |
| 209 | - | } | |
D protocol/performance_test.go +0 -393 collapsed to keep the page light
D protocol/pointerconstraints/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package pointerconstraints | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p pointerconstraints -o pointer-constraints-unstable-v1_generated.go -import wl_pointer=github.com/bnema/wlturbo/protocol/core -import wl_region=github.com/bnema/wlturbo/protocol/core -import wl_surface=github.com/bnema/wlturbo/protocol/core pointer-constraints-unstable-v1.xml | |
D protocol/pointerconstraints/pointer-constraints-unstable-v1.xml +0 -334 collapsed to keep the page light
D protocol/pointerconstraints/pointer-constraints-unstable-v1_generated.go +0 -369 collapsed to keep the page light
D protocol/pointerwarp/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package pointerwarp | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p pointerwarp -o pointer-warp-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_pointer=github.com/bnema/wlturbo/protocol/core pointer-warp-v1.xml | |
D protocol/pointerwarp/pointer-warp-v1.xml +0 -72
| @@ -1,72 +0,0 @@ | |||
| 1 | - | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | - | <protocol name="pointer_warp_v1"> | |
| 3 | - | <copyright> | |
| 4 | - | Copyright © 2024 Neal Gompa | |
| 5 | - | Copyright © 2024 Xaver Hugl | |
| 6 | - | Copyright © 2024 Matthias Klumpp | |
| 7 | - | Copyright © 2024 Vlad Zahorodnii | |
| 8 | - | ||
| 9 | - | Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 | - | copy of this software and associated documentation files (the "Software"), | |
| 11 | - | to deal in the Software without restriction, including without limitation | |
| 12 | - | the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 | - | and/or sell copies of the Software, and to permit persons to whom the | |
| 14 | - | Software is furnished to do so, subject to the following conditions: | |
| 15 | - | The above copyright notice and this permission notice (including the next | |
| 16 | - | paragraph) shall be included in all copies or substantial portions of the | |
| 17 | - | Software. | |
| 18 | - | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 | - | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 20 | - | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 21 | - | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 22 | - | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 23 | - | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 24 | - | DEALINGS IN THE SOFTWARE. | |
| 25 | - | </copyright> | |
| 26 | - | ||
| 27 | - | <interface name="wp_pointer_warp_v1" version="1"> | |
| 28 | - | <description summary="reposition the pointer to a location on a surface"> | |
| 29 | - | This global interface allows applications to request the pointer to be | |
| 30 | - | moved to a position relative to a wl_surface. | |
| 31 | - | ||
| 32 | - | Note that if the desired behavior is to constrain the pointer to an area | |
| 33 | - | or lock it to a position, this protocol does not provide a reliable way | |
| 34 | - | to do that. The pointer constraint and pointer lock protocols should be | |
| 35 | - | used for those use cases instead. | |
| 36 | - | ||
| 37 | - | Warning! The protocol described in this file is currently in the testing | |
| 38 | - | phase. Backward compatible changes may be added together with the | |
| 39 | - | corresponding interface version bump. Backward incompatible changes can | |
| 40 | - | only be done by creating a new major version of the extension. | |
| 41 | - | </description> | |
| 42 | - | ||
| 43 | - | <request name="destroy" type="destructor"> | |
| 44 | - | <description summary="destroy the warp manager"> | |
| 45 | - | Destroy the pointer warp manager. | |
| 46 | - | </description> | |
| 47 | - | </request> | |
| 48 | - | ||
| 49 | - | <request name="warp_pointer"> | |
| 50 | - | <description summary="reposition the pointer"> | |
| 51 | - | Request the compositor to move the pointer to a surface-local position. | |
| 52 | - | Whether or not the compositor honors the request is implementation defined, | |
| 53 | - | but it should | |
| 54 | - | - honor it if the surface has pointer focus, including | |
| 55 | - | when it has an implicit pointer grab | |
| 56 | - | - reject it if the enter serial is incorrect | |
| 57 | - | - reject it if the requested position is outside of the surface | |
| 58 | - | ||
| 59 | - | Note that the enter serial is valid for any surface of the client, | |
| 60 | - | and does not have to be from the surface the pointer is warped to. | |
| 61 | - | ||
| 62 | - | </description> | |
| 63 | - | <arg name="surface" type="object" interface="wl_surface" | |
| 64 | - | summary="surface to position the pointer on"/> | |
| 65 | - | <arg name="pointer" type="object" interface="wl_pointer" | |
| 66 | - | summary="the pointer that should be repositioned"/> | |
| 67 | - | <arg name="x" type="fixed"/> | |
| 68 | - | <arg name="y" type="fixed"/> | |
| 69 | - | <arg name="serial" type="uint" summary="serial number of the enter event"/> | |
| 70 | - | </request> | |
| 71 | - | </interface> | |
| 72 | - | </protocol> | |
D protocol/pointerwarp/pointer-warp-v1_generated.go +0 -89 collapsed to keep the page light
D protocol/presentation/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package presentation | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p presentation -o presentation-time_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_output=github.com/bnema/wlturbo/protocol/core presentation-time.xml | |
D protocol/presentation/presentation-time.xml +0 -268 collapsed to keep the page light
D protocol/presentation/presentation-time_generated.go +0 -277 collapsed to keep the page light
D protocol/primaryselection/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package primaryselection | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p primaryselection -o primary-selection-unstable-v1_generated.go -import wl_seat=github.com/bnema/wlturbo/protocol/core primary-selection-unstable-v1.xml | |
D protocol/primaryselection/primary-selection-unstable-v1.xml +0 -225 collapsed to keep the page light
D protocol/primaryselection/primary-selection-unstable-v1_generated.go +0 -420 collapsed to keep the page light
D protocol/relativepointer/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package relativepointer | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p relativepointer -o relative-pointer-unstable-v1_generated.go -import wl_pointer=github.com/bnema/wlturbo/protocol/core relative-pointer-unstable-v1.xml | |
D protocol/relativepointer/relative-pointer-unstable-v1.xml +0 -136 collapsed to keep the page light
D protocol/relativepointer/relative-pointer-unstable-v1_generated.go +0 -167 collapsed to keep the page light
D protocol/render_extensions_test.go +0 -864 collapsed to keep the page light
D protocol/screencopy/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package screencopy | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p screencopy -o wlr-screencopy-unstable-v1_generated.go -import wl_output=github.com/bnema/wlturbo/protocol/core -import wl_buffer=github.com/bnema/wlturbo/protocol/core wlr-screencopy-unstable-v1.xml | |
D protocol/screencopy/wlr-screencopy-unstable-v1.xml +0 -234 collapsed to keep the page light
D protocol/screencopy/wlr-screencopy-unstable-v1_generated.go +0 -410 collapsed to keep the page light
D protocol/session_lock_test.go +0 -222 collapsed to keep the page light
D protocol/shortcutsinhibit/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package shortcutsinhibit | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p shortcutsinhibit -o keyboard-shortcuts-inhibit-unstable-v1_generated.go -import wl_seat=github.com/bnema/wlturbo/protocol/core -import wl_surface=github.com/bnema/wlturbo/protocol/core keyboard-shortcuts-inhibit-unstable-v1.xml | |
D protocol/shortcutsinhibit/keyboard-shortcuts-inhibit-unstable-v1.xml +0 -143 collapsed to keep the page light
D protocol/shortcutsinhibit/keyboard-shortcuts-inhibit-unstable-v1_generated.go +0 -199 collapsed to keep the page light
D protocol/tablet/tablet-v2.xml +0 -1297 collapsed to keep the page light
D protocol/tablet/tablet-v2_generated.go +0 -2286 large diff (2286 lines changed): collapsed
D protocol/tearingcontrol/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package tearingcontrol | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p tearingcontrol -o tearing-control-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core tearing-control-v1.xml | |
D protocol/tearingcontrol/tearing-control-v1.xml +0 -123 collapsed to keep the page light
D protocol/tearingcontrol/tearing-control-v1_generated.go +0 -141 collapsed to keep the page light
D protocol/textinput/text-input-unstable-v3.xml +0 -604 collapsed to keep the page light
D protocol/textinput/text-input-unstable-v3_generated.go +0 -628 collapsed to keep the page light
D protocol/viewporter/viewporter.xml +0 -177 collapsed to keep the page light
D protocol/viewporter/viewporter_generated.go +0 -155 collapsed to keep the page light
D protocol/virtualkeyboard/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package virtualkeyboard | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p virtualkeyboard -o virtual-keyboard-unstable-v1_generated.go -import wl_seat=github.com/bnema/wlturbo/protocol/core virtual-keyboard-unstable-v1.xml | |
D protocol/virtualkeyboard/virtual-keyboard-unstable-v1.xml +0 -113 collapsed to keep the page light
D protocol/virtualkeyboard/virtual-keyboard-unstable-v1_generated.go +0 -149 collapsed to keep the page light
D protocol/wayland.xml +0 -3442 large diff (3442 lines changed): collapsed
D protocol/wlr_extensions_test.go +0 -652 collapsed to keep the page light
D protocol/workspace/ext-workspace-v1.xml +0 -422
| @@ -1,422 +0,0 @@ | |||
| 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> | |
D protocol/workspace/ext-workspace-v1_generated.go +0 -758 collapsed to keep the page light
D protocol/workspace/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package workspace | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p workspace -o ext-workspace-v1_generated.go -import wl_output=github.com/bnema/wlturbo/protocol/core ext-workspace-v1.xml | |
D protocol/xdgactivation/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package xdgactivation | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p xdgactivation -o xdg-activation-v1_generated.go -import wl_surface=github.com/bnema/wlturbo/protocol/core -import wl_seat=github.com/bnema/wlturbo/protocol/core xdg-activation-v1.xml | |
D protocol/xdgactivation/xdg-activation-v1.xml +0 -200 collapsed to keep the page light
D protocol/xdgactivation/xdg-activation-v1_generated.go +0 -214 collapsed to keep the page light
D protocol/xdgdecoration/generate.go +0 -3
| @@ -1,3 +0,0 @@ | |||
| 1 | - | package xdgdecoration | |
| 2 | - | ||
| 3 | - | //go:generate go run ../../cmd/wlturbo-scanner -p xdgdecoration -o xdg-decoration-unstable-v1_generated.go -import xdg_toplevel=github.com/bnema/wlturbo/protocol/xdgshell xdg-decoration-unstable-v1.xml | |