diff --git a/.gitignore b/.gitignore index 2a77f90..c18dd8d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1 @@ __pycache__/ - -vendor/casilda/builddir/ -vendor/casilda/prefix/ diff --git a/run.sh b/run.sh index c51c20e..e9ea40c 100755 --- a/run.sh +++ b/run.sh @@ -2,12 +2,9 @@ set -e dir="$(CDPATH= cd -- "$(dirname "$0")" && pwd)" -prefix="$dir/vendor/casilda/prefix" +libdir="$HOME/.local/lib/x86_64-linux-gnu" -typelib_dir="$(dirname "$(find "$prefix" -name Casilda-1.0.typelib | head -1)")" -libdir="$(dirname "$(find "$prefix" -name 'libcasilda-1.0.so*' -type l | head -1)")" - -export GI_TYPELIB_PATH="$typelib_dir${GI_TYPELIB_PATH:+:$GI_TYPELIB_PATH}" +export GI_TYPELIB_PATH="$libdir/girepository-1.0${GI_TYPELIB_PATH:+:$GI_TYPELIB_PATH}" export LD_LIBRARY_PATH="$libdir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" -exec uv run tabbed_casilda.py "$@" +exec uv run "$dir/tabbed_casilda.py" "$@" diff --git a/tabbed_casilda.py b/tabbed_casilda.py index 8e04d33..c45e202 100644 --- a/tabbed_casilda.py +++ b/tabbed_casilda.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # /// script -# requires-python = ">=3.11" +# requires-python = ">=3.11,<3.14" # dependencies = [ # "PyGObject", # ] @@ -18,7 +18,6 @@ from gi.repository import GLib, Gtk, Casilda def make_tab(notebook, command): compositor = Casilda.Compositor() - compositor.props.maximized = True label = Gtk.Label(label=command) notebook.append_page(compositor, label) argv = shlex.split(command) diff --git a/vendor/build.sh b/vendor/build.sh deleted file mode 100755 index 6736115..0000000 --- a/vendor/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -set -e - -cd "$(dirname "$0")/casilda" - -if [ ! -f builddir/build.ninja ]; then - meson setup builddir --prefix "$PWD/prefix" -fi - -meson compile -C builddir -meson install -C builddir diff --git a/vendor/casilda/.gitlab-ci.yml b/vendor/casilda/.gitlab-ci.yml deleted file mode 100644 index 6eaa1b7..0000000 --- a/vendor/casilda/.gitlab-ci.yml +++ /dev/null @@ -1,16 +0,0 @@ -image: debian:sid-slim -create-pages: - pages: - # The folder that contains the files to be exposed at the Page URL - publish: _build/docs/casilda/ - rules: - # This ensures that only pushes to the default branch will trigger a pages deploy - - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH - changes: - - meson.build - before_script: - - apt-get update - - apt-get install -y libgtk-4-dev libwlroots-0.19-dev libgirepository-1.0-dev gi-docgen meson ninja-build - script: - - meson setup --wipe --prefix=/usr -Ddocumentation=True _build - - ninja -C _build diff --git a/vendor/casilda/CHANGELOG.md b/vendor/casilda/CHANGELOG.md deleted file mode 100644 index 0aa73f9..0000000 --- a/vendor/casilda/CHANGELOG.md +++ /dev/null @@ -1,66 +0,0 @@ -# Changelog - -This documents user relevant changes, closed issues from -(Gitlab)[https://gitlab.gnome.org/jpu/casilda/-/issues/] and -packaging changes like new dependencies or build system changes. - -Casilda used even/odd minor numbers to differentiate between stable and -development releases. - -## 1.2.1 - -2026-03-17 - 1.2.1 Bugfix release - - - Fix GdkTexture leak - -## 1.2.0 - -2026-03-06 - 1.2 Release - - - Migrated to wlroots 0.19 - -### Packaging - - - Casilda now depends on wlroots 0.19 instead of 0.18 - -### Issues - - - #12 "Support for wlroots-0.19" - -## 1.0.0 - -2025-09-11 - 1.0 Release - - - Add dmabuf support (Val Packett) - - Added vapi generation (PaladinDev) - - Add library soname (Benson Muite - - Implement GtkScrollable iface - - Add casilda_compositor_get_client_socket_fd() - - Add casilda_compositor_spawn_async() - - Remove bg-color property - - Render windows and popups directly in snapshot() - - Position windows on center of widget - - Position transient windows on center of parent - - Fix unmaximize - -### Packaging - - - API/soname version bumped from 0.1 to 1.0 - - Small API break (bg-color property was removed) - - Do not install private header casilda-wayland-source.h - -### Issues - - - #8 "Investigate using WAYLAND_SOCKET" - - #7 "Implement GtkScrollable iface" - - #11 "Resource leak causing crash with dmabuf" - - #3 " Unmaximize not working properly" - - #2 "Add dmabuff support" (Val Packett) - - #9 "Bad performance" - - #10 "Add a soname to shared library" (Benson Muite) - -## 0.2.0 - -2024-09-13 - First Stable Release - - - Rename and cleanup CmbCompositor from Cambalache into its own library diff --git a/vendor/casilda/COPYING b/vendor/casilda/COPYING deleted file mode 100644 index 4362b49..0000000 --- a/vendor/casilda/COPYING +++ /dev/null @@ -1,502 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[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.] - - Preamble - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 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". - - 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. - - 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".) - - "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. - - 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. - - 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. - - 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. - - 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: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - 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. - - 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. - - (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.) - -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. - -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. - -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. - - 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. - - 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. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 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. - - 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. - - 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. - - 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. - - 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. - - 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.) - - 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. - - 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. - - 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: - - 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.) - - 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. - - 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. - - 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. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - 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. - - 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. - - 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: - - 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. - - 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. - - 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. - - 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. - - 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. - - 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. - -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. - -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. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 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. - - 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. - -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. - - 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. - - NO WARRANTY - - 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. - - 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. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - 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). - - 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. - - - Copyright (C) - - 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. - - 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. - - 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. - -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: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/vendor/casilda/README.md b/vendor/casilda/README.md deleted file mode 100644 index 3def3f8..0000000 --- a/vendor/casilda/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# Casilda - -A simple Wayland compositor widget for Gtk 4 which can be used to embed other -processes windows in your Gtk 4 application. - -It was originally created for Cambalache's workspace using wlroots, -a modular library to create Wayland compositors. - -Following Wayland tradition, this library is named after my hometown in -Santa Fe, Argentina. - -## License - -Casilda is distributed under the [GNU Lesser General Public License](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html), -version 2.1 only (LGPL) as described in the COPYING file. - -## Source code - -Source code lives on GNOME gitlab [here](https://gitlab.gnome.org/jpu/casilda) - -`git clone https://gitlab.gnome.org/jpu/casilda.git` - -## Dependencies - -* [Meson](http://mesonbuild.com) build system -* [GTK](http://www.gtk.org) Version 4 -* wlroots - Library to create Wayland compositors - - -## Manual installation - -This is a regular meson package and can be installed the usual way. - -```bash -# Configure project in _build directory -meson setup --wipe --prefix=~/.local _build . - -# Build and install in ~/.local -ninja -C _build install -``` - -## How to use it - -To add a Wayland compositor to your application all you have to do is create a -CasildaCompositor widget and pack it as any other widget. - -```c -compositor = casilda_compositor_new (NULL); -gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (compositor)); -gtk_window_present (GTK_WINDOW (window)); -``` - -The easiest way to show another process window in the compositor is to spawn the -process using the helper function provided by Casilda - -```c -gchar *argv[] = { "/usr/bin/gtk4-demo", NULL }; -casilda_compositor_spawn_async (compositor, NULL, argv, NULL, G_SPAWN_DEFAULT, NULL, NULL, NULL, NULL); -``` - -## API - -Casilda uses gi-docgen to generate it's API reference documentation and is [available online.](https://jpu.pages.gitlab.gnome.org/casilda/) - -## Contributing - -If you are interested in contributing you can open an issue [here](https://gitlab.gnome.org/jpu/casilda/-/issues) -and/or a merge request [here](https://gitlab.gnome.org/jpu/casilda/-/merge_requests) - -## Contact - -You can hang with us and ask us questions on Cambalache Matrix at #cambalache:gnome.org - -[Matrix](https://matrix.to/#/#cambalache:gnome.org) diff --git a/vendor/casilda/docs/casilda.toml.in b/vendor/casilda/docs/casilda.toml.in deleted file mode 100644 index 2c1405f..0000000 --- a/vendor/casilda/docs/casilda.toml.in +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Juan Pablo Ugarte -# SPDX-License-Identifier: CC0-1.0 - -[library] -version = "@VERSION@" -description = "A simple Wayland compositor widget for Gtk 4" -authors = "Juan Pablo Ugarte" -license = "LGPL-2.1-only" -website_url = "https://gitlab.gnome.org/jpu/casilda" -browse_url = "https://gitlab.gnome.org/jpu/casilda" -repository_url = "https://gitlab.gnome.org/jpu/casilda.git" -docs_url = "https://jpu.pages.gitlab.gnome.org/casilda/" -devhelp = true -search_index = true - -dependencies = [ - "Gtk-4.0", - "GLib-2.0", - "GObject-2.0" -] - -[dependencies."Gtk-4.0"] -name = "Gtk" -description = "The GTK toolkit" -docs_url = "https://docs.gtk.org/gtk4/" - -[dependencies."GLib-2.0"] -name = "GLib" -description = "The base utility library" -docs_url = "https://docs.gtk.org/glib/" - -[dependencies."GObject-2.0"] -name = "GObject" -description = "The base type system library" -docs_url = "https://docs.gtk.org/gobject/" - -[source-location] -base_url = "https://gitlab.gnome.org/jpu/casilda/-/blob/@VERSION@/" - -[extra] -urlmap_file = "urlmap.js" \ No newline at end of file diff --git a/vendor/casilda/docs/meson.build b/vendor/casilda/docs/meson.build deleted file mode 100644 index 3729996..0000000 --- a/vendor/casilda/docs/meson.build +++ /dev/null @@ -1,32 +0,0 @@ -toml_conf = configuration_data() -toml_conf.set('VERSION', meson.project_version()) - -docs_dir = get_option('datadir') / 'doc' - -casilda_toml = configure_file( - input: 'casilda.toml.in', - output: 'casilda.toml', - configuration: toml_conf, - install: true, - install_dir: docs_dir / 'casilda', -) - -custom_target('casilda-doc', - input: [ casilda_toml, casilda_gir[0] ], - output: 'casilda', - command: [ - gidocgen, - 'generate', - ['--quiet', '--no-namespace-dir'], - '--add-include-path=@0@'.format(meson.current_source_dir() / '../src'), - '--add-include-path=@0@'.format(meson.current_build_dir() / '../src'), - '--config=@INPUT0@', - '--output-dir=@OUTPUT@', - '--content-dir=@0@'.format(meson.current_source_dir()), - '@INPUT1@', - ], - build_by_default: true, - install: true, - install_dir: docs_dir, - install_tag: 'doc', -) \ No newline at end of file diff --git a/vendor/casilda/docs/urlmap.js b/vendor/casilda/docs/urlmap.js deleted file mode 100644 index badc30c..0000000 --- a/vendor/casilda/docs/urlmap.js +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2025 Juan Pablo Ugarte -// SPDX-License-Identifier: LGPL-2.1-only - -baseURLs = [ - [ 'GLib', 'https://docs.gtk.org/glib/' ], - [ 'GObject', 'https://docs.gtk.org/gobject/' ], - [ 'Gio', 'https://docs.gtk.org/gio/' ], - [ 'Gdk', 'https://docs.gtk.org/gdk4/' ], - [ 'Gtk', 'https://docs.gtk.org/gtk4/' ], -] diff --git a/vendor/casilda/examples/compositor.c b/vendor/casilda/examples/compositor.c deleted file mode 100644 index 7ed78b4..0000000 --- a/vendor/casilda/examples/compositor.c +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include "casilda-compositor.h" - -/* Do not listen on any socket by default */ -gchar *socket = NULL; - - -static void -activate (GtkApplication *app, G_GNUC_UNUSED gpointer user_data) -{ - CasildaCompositor *compositor; - GtkWidget *window, *sw; - - window = gtk_application_window_new (app); - gtk_window_set_title (GTK_WINDOW (window), "Casilda Compositor"); - gtk_window_set_default_size (GTK_WINDOW (window), 800, 600); - - if (socket) - g_message ("Listening on %s", socket); - else - g_message ("Not listening in any socket, you can pass a socket path as parameter"); - - sw = gtk_scrolled_window_new (); - compositor = casilda_compositor_new (socket); - - gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), GTK_WIDGET (compositor)); - gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (sw)); - gtk_window_present (GTK_WINDOW (window)); - - gchar *argv[2] = { - "/usr/bin/gtk4-demo", - NULL - }; - - casilda_compositor_spawn_async (compositor, NULL, argv, NULL, G_SPAWN_DEFAULT, NULL, NULL, NULL, NULL); -} - -int -main (int argc, char **argv) -{ - g_autoptr(GtkApplication) app = NULL; - - app = gtk_application_new ("ar.xjuan.casilda.Example", G_APPLICATION_DEFAULT_FLAGS); - g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); - - if (argc >= 2) - socket = argv[1]; - - return g_application_run (G_APPLICATION (app), 0, NULL); -} diff --git a/vendor/casilda/examples/compositor.js b/vendor/casilda/examples/compositor.js deleted file mode 100755 index b818802..0000000 --- a/vendor/casilda/examples/compositor.js +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/gjs -m - -import System from 'system'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk?version=4.0'; -import Casilda from 'gi://Casilda?version=1.0'; - - -let CasildaApplication = GObject.registerClass({}, - class CasildaApplication extends Gtk.Application { - constructor() { - super({ - application_id: 'ar.xjuan.casilda.Gjs.Example' - }); - } - - vfunc_activate() { - let compositor = new Casilda.Compositor(); - - let window = new Gtk.ApplicationWindow({ - application: this, - title: 'Casilda Compositor', - default_width: 800, - default_height: 600, - child: compositor - }); - - window.connect('close-request', () => { - this.quit(); - }); - - compositor.spawn_async ( - null, - ["/usr/bin/gtk4-demo"], - null, - GLib.SpawnFlags.DEFAULT, - null - ); - - window.present(); - } -}); - -let app = new CasildaApplication(); -app.run([System.programInvocationName].concat(ARGV)); diff --git a/vendor/casilda/examples/compositor.py b/vendor/casilda/examples/compositor.py deleted file mode 100755 index b97edb4..0000000 --- a/vendor/casilda/examples/compositor.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/python3 - -import gi -import sys - -gi.require_version("Gtk", "4.0") -gi.require_version("Casilda", "1.0") -from gi.repository import GLib, Gtk, Casilda - - -class CasildaApplication(Gtk.Application): - def __init__(self): - super().__init__(application_id="ar.xjuan.casilda.PyGObject.Example") - - def do_activate(self): - compositor = Casilda.Compositor() - - window = Gtk.ApplicationWindow( - application=self, - title="Casilda Compositor", - default_width=800, - default_height=600, - child=compositor - ) - - compositor.spawn_async ( - None, - ["/usr/bin/gtk4-demo"], - None, - GLib.SpawnFlags.DEFAULT - ) - - window.present() - - -if __name__ == "__main__": - app = CasildaApplication() - sys.exit(app.run(sys.argv)) diff --git a/vendor/casilda/examples/meson.build b/vendor/casilda/examples/meson.build deleted file mode 100644 index 838df01..0000000 --- a/vendor/casilda/examples/meson.build +++ /dev/null @@ -1,9 +0,0 @@ -executable('compositor', - sources: 'compositor.c', - dependencies: [casilda_dep], -) - -executable('nested', - sources: 'nested.c', - dependencies: [casilda_dep], -) diff --git a/vendor/casilda/examples/nested.c b/vendor/casilda/examples/nested.c deleted file mode 100644 index 4d6e3d2..0000000 --- a/vendor/casilda/examples/nested.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include "casilda-compositor.h" - -/* Do not listen on any socket by default */ -gchar *socket = NULL; -gchar *dirname; - - -static void -activate (GtkApplication *app, G_GNUC_UNUSED gpointer user_data) -{ - CasildaCompositor *compositor; - GtkWidget *window; - - window = gtk_application_window_new (app); - gtk_window_set_title (GTK_WINDOW (window), "Nested Casilda Compositor"); - gtk_window_set_default_size (GTK_WINDOW (window), 1024, 768); - - if (socket) - g_message ("Listening on %s", socket); - else - g_message ("Not listening in any socket, you can pass a socket path as parameter"); - - compositor = casilda_compositor_new (socket); - gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (compositor)); - gtk_window_present (GTK_WINDOW (window)); - - gchar *argv[2] = { - g_build_path ("/", dirname, "compositor", NULL), - NULL - }; - - g_message("Running %s", argv[0]); - casilda_compositor_spawn_async (compositor, NULL, argv, NULL, G_SPAWN_DEFAULT, NULL, NULL, NULL, NULL); -} - -int -main (int argc, char **argv) -{ - g_autoptr(GtkApplication) app = NULL; - - dirname = g_path_get_dirname (argv[0]); - - app = gtk_application_new ("ar.xjuan.casilda.NestedExample", G_APPLICATION_DEFAULT_FLAGS); - g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); - - if (argc >= 2) - socket = argv[1]; - - return g_application_run (G_APPLICATION (app), 0, NULL); -} diff --git a/vendor/casilda/meson.build b/vendor/casilda/meson.build deleted file mode 100644 index ffb1b8b..0000000 --- a/vendor/casilda/meson.build +++ /dev/null @@ -1,51 +0,0 @@ -project('casilda','c', - version: '1.2.1', - meson_version: '>= 1.0.0', - default_options: [ - 'warning_level=2', - 'werror=false', - 'c_std=c11', - ], -) - -pkg = import('pkgconfig') -gnome = import('gnome') - -version_split = meson.project_version().split('.') - -epoxy_dep = dependency('epoxy', version: '>=1.5') -gtk4_dep = dependency('gtk4', version: '>= 4.14') -pixman_dep = dependency('pixman-1', version: '>=0.42.0') -wayland_protocols_deps = dependency('wayland-protocols', - version: '>=1.32', - fallback: 'wayland-protocols', - default_options: ['tests=false'], -) -wayland_scanner_dep = dependency('wayland-scanner', native: true) -wayland_server_dep = dependency('wayland-server', version: '>=1.22') -wlroots_dep = dependency('wlroots-0.19', version: '>= 0.19') -x11_xcb_dep = dependency('x11-xcb', version: '>=1.8.7', required : false) -xkbcommon_x11_dep = dependency('xkbcommon-x11', version: '>=1.5', required : false) -xkbcommon = dependency( - 'xkbcommon', - fallback: 'libxkbcommon', - default_options: [ - 'enable-tools=false', - 'enable-x11=false', - 'enable-docs=false', - 'enable-xkbregistry=false', - ], -) - -config_h = configuration_data() -config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) -configure_file(output: 'config.h', configuration: config_h) -add_project_arguments(['-I' + meson.project_build_root()], language: 'c') - -gidocgen = find_program('gi-docgen', required: get_option('documentation'), native: true) - -subdir('src') -subdir('examples') -if get_option('documentation') - subdir('docs') -endif diff --git a/vendor/casilda/meson_options.txt b/vendor/casilda/meson_options.txt deleted file mode 100644 index e27a9d2..0000000 --- a/vendor/casilda/meson_options.txt +++ /dev/null @@ -1,12 +0,0 @@ -option( - 'vapi', - type: 'boolean', - value: false, - description: 'Whether to build vapi files' -) -option( - 'documentation', - type: 'boolean', - value: false, - description : 'Build API reference documentation' -) \ No newline at end of file diff --git a/vendor/casilda/src/casilda-compositor.c b/vendor/casilda/src/casilda-compositor.c deleted file mode 100644 index 38b271f..0000000 --- a/vendor/casilda/src/casilda-compositor.c +++ /dev/null @@ -1,3025 +0,0 @@ -/* - * Casilda Wayland Compositor Widget - * - * Copyright (C) 2024-2025 Juan Pablo Ugarte - * - * 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; - * version 2.1 of the License. - * - * 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. - * - * 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 - * - * Authors: - * Juan Pablo Ugarte - * - * SPDX-License-Identifier: LGPL-2.1-only - */ - -/** - * CasildaCompositor: - * - * A simple Wayland compositor widget for Gtk 4. - * - * It was originally created for Cambalache's workspace using (wlroots)[https://gitlab.freedesktop.org/wlroots/wlroots], - * a modular library to create Wayland compositors. - * - * Following Wayland tradition, this library is named after my hometown in Santa Fe, Argentina. - * - * To embed another process window in your Gtk 4 application all you have to do is create a CasildaCompositor widget - * and add it in the hierarchy just like any other widget. - * - * You can specify which UNIX socket the compositor will listen for clients connections or use - * [method@Casilda.Compositor.get_client_socket_fd] to get a already connected socket to the compositor. - * - * ```c - * compositor = casilda_compositor_new ("/tmp/casilda-example.sock"); - * gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (compositor)); - * ``` - * - * Once the compositor is running you can connect to it by specifying the socket in WAYLAND_DISPLAY environment variable. - * - * ```bash - * export GDK_BACKEND=wayland - * export WAYLAND_DISPLAY=/tmp/casilda-example.sock - * gtk4-demo - * ``` - * - * If you do not want any client being able to connect to the compositor you can pass NULL as socket and spawn the client - * with [method@Casilda.Compositor.spawn_async] or get an already connected socket with - * [method@Casilda.Compositor.get_client_socket_fd] and pass it to the client on WAYLAND_SOCKET env variable. - * - * ```c - * compositor = casilda_compositor_new (NULL); - * gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (compositor)); - * gtk_window_present (GTK_WINDOW (window)); - * - * gchar *argv[] = { "/usr/bin/gtk4-demo", NULL }; - * casilda_compositor_spawn_async (compositor, NULL, argv, NULL, G_SPAWN_DEFAULT, NULL, NULL, NULL, NULL); - * ``` - * - * Python example running gtk4-demo with [method@Casilda.Compositor.spawn_async] - * - * ```python - * import gi - * import sys - * - * gi.require_version("Gtk", "4.0") - * gi.require_version("Casilda", "1.0") - * from gi.repository import GLib, Gtk, Casilda - * - * - * class CasildaApplication(Gtk.Application): - * def __init__(self): - * super().__init__(application_id="ar.xjuan.casilda.PyGObject.Example") - * - * def do_activate(self): - * compositor = Casilda.Compositor() - * - * window = Gtk.ApplicationWindow( - * application=self, - * title="Casilda Compositor", - * default_width=800, - * default_height=600, - * child=compositor - * ) - * - * compositor.spawn_async ( - * None, - * ["/usr/bin/gtk4-demo"], - * None, - * GLib.SpawnFlags.DEFAULT - * ) - * - * window.present() - * - * - * if __name__ == "__main__": - * app = CasildaApplication() - * sys.exit(app.run(sys.argv)) - * ``` - * - * and the same in Javascript: - * - * ```javascript - * import System from 'system'; - * import GLib from 'gi://GLib'; - * import GObject from 'gi://GObject'; - * import Gtk from 'gi://Gtk?version=4.0'; - * import Casilda from 'gi://Casilda?version=1.0'; - * - * - * let CasildaApplication = GObject.registerClass({}, - * class CasildaApplication extends Gtk.Application { - * constructor() { - * super({ - * application_id: 'ar.xjuan.casilda.Gjs.Example' - * }); - * } - * - * vfunc_activate() { - * let compositor = new Casilda.Compositor(); - * - * let window = new Gtk.ApplicationWindow({ - * application: this, - * title: 'Casilda Compositor', - * default_width: 800, - * default_height: 600, - * child: compositor - * }); - * - * window.connect('close-request', () => { - * this.quit(); - * }); - * - * compositor.spawn_async ( - * null, - * ["/usr/bin/gtk4-demo"], - * null, - * GLib.SpawnFlags.DEFAULT, - * null - * ); - * - * window.present(); - * } - * }); - * - * let app = new CasildaApplication(); - * app.run([System.programInvocationName].concat(ARGV)); - * ``` - */ - -#define _POSIX_C_SOURCE 199309L /* clock_gettime */ -#define WLR_USE_UNSTABLE 1 -#define G_LOG_DOMAIN "Casilda" -#define ENABLE_TEXTURE_DEBUG 0 -#define ENABLE_BORDERS 0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "xdg-shell-protocol.h" -#include - -#include -#include - -#ifdef GDK_WINDOWING_WAYLAND -#include -#endif - -#if defined(GDK_WINDOWING_X11) && defined(HAVE_X11_XCB) -#include -#include -#include -#endif - -#include "casilda-compositor.h" -#include "casilda-wayland-source.h" - -/* Auto free helpers */ -typedef struct wlr_texture WlrTexture; -typedef struct wlr_output_state WlrOutputState; -G_DEFINE_AUTOPTR_CLEANUP_FUNC (WlrTexture, wlr_texture_destroy); -G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (WlrOutputState, wlr_output_state_finish); -G_DEFINE_AUTOPTR_CLEANUP_FUNC (cairo_surface_t, cairo_surface_destroy); -G_DEFINE_AUTOPTR_CLEANUP_FUNC (pixman_image_t, pixman_image_unref); - -typedef enum { - CASILDA_POINTER_MODE_FOWARD, - CASILDA_POINTER_MODE_RESIZE, - CASILDA_POINTER_MODE_MOVE, -} CasildaPointerMode; - -typedef struct CasildaCompositorToplevel CasildaCompositorToplevel; -typedef struct CasildaCompositorPopup CasildaCompositorPopup; - -typedef struct -{ - GtkWidget *self; - - /* wayland main loop integration */ - GSource *wl_source; - - /* Event controllers */ - GtkEventController *motion_controller; - GtkEventController *scroll_controller; - GtkEventController *key_controller; - GtkGesture *click_gesture; - - /* Frame Clock state */ - GdkFrameClock *frame_clock; - gboolean frame_clock_updating; - gulong frame_clock_source; - guint defered_present_event_source; - struct wlr_output_event_present defered_present_event; - - /* Renderer context */ - GdkGLContext *gl_context; - - /* Wayland display */ - struct wl_display *wl_display; - - /* wlroots objects */ - struct wlr_renderer *renderer; - struct wlr_allocator *allocator; - - /* Custom wlr objects */ - struct wlr_keyboard keyboard; - struct wlr_pointer pointer; - struct wlr_backend backend; - struct wlr_output output; - - /* wlr interfaces */ - struct wlr_backend_impl backend_impl; - struct wlr_output_impl output_impl; - - /* XDG shell */ - struct wlr_xdg_shell *xdg_shell; - struct wl_listener new_xdg_toplevel; - struct wl_listener new_xdg_popup; - GList *toplevels; - - /* XDG activation */ - struct wlr_xdg_activation_v1 *xdg_activation; - struct wl_listener request_activate; - - GHashTable *toplevel_state; - - /* Toplevel resize state */ - gdouble pointer_x, pointer_y; /* Current pointer position */ - CasildaCompositorToplevel *grabbed_toplevel; - CasildaPointerMode pointer_mode; - gdouble grab_x, grab_y; - struct wlr_box grab_box; - uint32_t resize_edges; - - /* Virtual Seat */ - struct wlr_seat *seat; - struct wl_listener request_cursor; - struct wl_listener request_set_selection; - - struct wl_listener on_request_cursor; - struct wl_listener on_cursor_surface_commit; - gint hotspot_x; - gint hotspot_y; - GdkTexture *cursor_gdk_texture; - GdkCursor *cursor_gdk_cursor; - - struct sockaddr_un abstract_socket; - - /* GObject properties */ - gchar *socket; - - /* Force all toplevels to be maximized */ - gboolean maximized; - - GtkAdjustment *adjustment[2]; -} CasildaCompositorPrivate; - - -struct _CasildaCompositor -{ - GtkWidget parent; -}; - - -typedef struct -{ - gboolean maximized, fullscreen; - gint x, y, width, height; -} CasildaCompositorToplevelState; - - -typedef struct -{ - struct wl_listener new_subsurface; - GList *list; -} CasildaCompositorSurfaces; - - -struct CasildaCompositorToplevel -{ - CasildaCompositorPrivate *priv; - struct wlr_xdg_toplevel *xdg_toplevel; - - GList *toplevels; - GList *popups; - - CasildaCompositorSurfaces subsurfaces; - gboolean needs_update; - - gint x; - gint y; - - CasildaCompositorToplevelState old_state; - - /* This points to priv->toplevel_state[app_id] */ - CasildaCompositorToplevelState *state; - - /* Events */ - struct wl_listener map; - struct wl_listener unmap; - struct wl_listener commit; - struct wl_listener destroy; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_maximize; - struct wl_listener request_fullscreen; - struct wl_listener set_app_id; -}; - -struct CasildaCompositorPopup -{ - CasildaCompositorPrivate *priv; - - CasildaCompositorToplevel *toplevel; - CasildaCompositorPopup *parent; - - struct wlr_xdg_popup *xdg_popup; - - CasildaCompositorSurfaces subsurfaces; - GList *popups; - - struct wl_listener commit; - struct wl_listener destroy; -}; - -typedef struct -{ - CasildaCompositorPrivate *priv; - CasildaCompositorSurfaces *parent; - - struct wlr_subsurface *wlr_subsurface; - - struct wl_listener commit; - struct wl_listener destroy; -} CasildaCompositorSubsurface; - - -enum { - PROP_0, - PROP_SOCKET, - PROP_MAXIMIZED, - - N_PROPERTIES, - - PROP_HADJUSTMENT, - PROP_VADJUSTMENT, - PROP_HSCROLL_POLICY, - PROP_VSCROLL_POLICY -}; - -static GParamSpec *properties[N_PROPERTIES]; - -G_DEFINE_TYPE_WITH_CODE (CasildaCompositor, casilda_compositor, GTK_TYPE_WIDGET, - G_ADD_PRIVATE (CasildaCompositor) - G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL)) -#define GET_PRIVATE(d) ((CasildaCompositorPrivate *) casilda_compositor_get_instance_private ((CasildaCompositor *) d)) - - -static void casilda_compositor_wlr_init (CasildaCompositorPrivate *priv); -static void casilda_compositor_toplevel_configure (CasildaCompositorToplevel *toplevel, - gint x, - gint y, - gint width, - gint height); - -#define FORMAT_UNSUPPORTED ((GdkMemoryFormat)-1) - -static inline GdkMemoryFormat -_gdk_format_from_pixman_format (pixman_format_code_t pixman_format) -{ - /* Annoyingly, GDK's formats are literal while pixman's are endian-independent */ - switch (pixman_format) - { - case PIXMAN_rgba_float: - return GDK_MEMORY_R32G32B32A32_FLOAT; - - case PIXMAN_rgb_float: - return GDK_MEMORY_R32G32B32_FLOAT; - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - case PIXMAN_a8r8g8b8: - return GDK_MEMORY_B8G8R8A8; - - case PIXMAN_x8r8g8b8: - return GDK_MEMORY_B8G8R8X8; - - case PIXMAN_a8b8g8r8: - return GDK_MEMORY_R8G8B8A8; - - case PIXMAN_x8b8g8r8: - return GDK_MEMORY_R8G8B8X8; - - case PIXMAN_r8g8b8a8: - return GDK_MEMORY_A8B8G8R8; - - case PIXMAN_r8g8b8x8: - return GDK_MEMORY_X8B8G8R8; - - case PIXMAN_r8g8b8: - return GDK_MEMORY_B8G8R8; - - case PIXMAN_b8g8r8: - return GDK_MEMORY_R8G8B8; -#else - case PIXMAN_a8r8g8b8: - return GDK_MEMORY_A8R8G8B8; - - case PIXMAN_x8r8g8b8: - return GDK_MEMORY_X8R8G8B8; - - case PIXMAN_a8b8g8r8: - return GDK_MEMORY_A8B8G8R8; - - case PIXMAN_x8b8g8r8: - return GDK_MEMORY_X8B8G8R8; - - case PIXMAN_r8g8b8a8: - return GDK_MEMORY_R8G8B8A8; - - case PIXMAN_r8g8b8x8: - return GDK_MEMORY_R8G8B8X8; - - case PIXMAN_r8g8b8: - return GDK_MEMORY_R8G8B8; - - case PIXMAN_b8g8r8: - return GDK_MEMORY_B8G8R8; -#endif - - case PIXMAN_a8: - return GDK_MEMORY_A8; - - default: - return FORMAT_UNSUPPORTED; - } - - return FORMAT_UNSUPPORTED; -} - -/* Literally the same type internally, but no public conversion API.. */ -static inline cairo_region_t * -cairo_region_from_pixman (pixman_region32_t *pixman_region) -{ - cairo_region_t *region = cairo_region_create (); - const pixman_box32_t *rects = NULL; - int n_rects = 0; - - rects = pixman_region32_rectangles (pixman_region, &n_rects); - for (int i = 0; i < n_rects; i++) - { - const pixman_box32_t *r = &rects[i]; - cairo_region_union_rectangle (region, &(cairo_rectangle_int_t){ r->x1, r->y1, r->x2 - r->x1, r->y2 - r->y1 }); - } - - return region; -} - -static inline GdkTexture * -wlr_gl_texture_as_gdk (WlrTexture *texture, GdkGLContext *gl_context, pixman_region32_t *damage, GdkTexture *prev) -{ - if (prev && damage && !pixman_region32_not_empty (damage)) - return g_object_ref (prev); - - g_autoptr(GdkGLTextureBuilder) builder = gdk_gl_texture_builder_new(); - g_autoptr(GError) error = NULL; - struct wlr_gles2_texture_attribs attribs = {0}; - - wlr_gles2_texture_get_attribs(texture, &attribs); - - gdk_gl_texture_builder_set_context (builder, gl_context); - gdk_gl_texture_builder_set_id (builder, attribs.tex); - gdk_gl_texture_builder_set_width (builder, texture->width); - gdk_gl_texture_builder_set_height (builder, texture->height); - - gdk_gl_texture_builder_set_update_texture (builder, prev); - - if (damage && pixman_region32_not_empty (damage)) - { - cairo_region_t *region = cairo_region_from_pixman (damage); - gdk_gl_texture_builder_set_update_region (builder, region); - cairo_region_destroy (region); - } - - return gdk_gl_texture_builder_build (builder, NULL, NULL); -} - -static inline GdkTexture * -wlr_pixman_texture_as_gdk (WlrTexture *texture, pixman_region32_t *damage, GdkTexture *prev) -{ - g_autoptr(GdkMemoryTextureBuilder) builder = gdk_memory_texture_builder_new(); - g_autoptr(GBytes) bytes = NULL; - pixman_image_t *image = NULL; - GdkMemoryFormat format; - - if (!(image = wlr_pixman_texture_get_image (texture))) - return NULL; - - format = _gdk_format_from_pixman_format (pixman_image_get_format (image)); - - if (format == FORMAT_UNSUPPORTED) - { - g_warning_once ("Unsupported texture format %x", format); - return NULL; - } - - gint h = pixman_image_get_height (image); - gint stride = pixman_image_get_stride (image); - - gdk_memory_texture_builder_set_format (builder, format); - gdk_memory_texture_builder_set_width (builder, pixman_image_get_width (image)); - gdk_memory_texture_builder_set_height (builder, h); - gdk_memory_texture_builder_set_stride (builder, stride); - gdk_memory_texture_builder_set_update_texture (builder, prev); - - bytes = g_bytes_new_static (pixman_image_get_data (image), stride * h); - gdk_memory_texture_builder_set_bytes (builder, bytes); - - if (damage != NULL && pixman_region32_not_empty (damage)) - { - cairo_region_t *region = cairo_region_from_pixman (damage); - gdk_memory_texture_builder_set_update_region (builder, region); - cairo_region_destroy (region); - } - - return gdk_memory_texture_builder_build (builder); -} - -static GdkTexture * -wlr_texture_as_gdk (WlrTexture *texture, GdkGLContext *gl_context, pixman_region32_t *damage, GdkTexture *prev) -{ - if (wlr_texture_is_gles2 (texture)) - return wlr_gl_texture_as_gdk (texture, gl_context, damage, prev); - - if (wlr_texture_is_pixman (texture)) - return wlr_pixman_texture_as_gdk (texture, damage, prev); - - return NULL; -} - -static gboolean -xdg_surface_get_data (struct wlr_xdg_surface *xdg_surface, struct wlr_surface **surface, struct wlr_box *geometry) -{ - if (!xdg_surface || !(*surface = xdg_surface->surface) || !xdg_surface->surface->buffer) - return TRUE; - - if (geometry) - *geometry = xdg_surface->geometry; - - return FALSE; -} - - -#if ENABLE_BORDERS -static void -debug_snapshot_border (GtkSnapshot *snapshot, - gint x, gint y, gint w, gint h, - gfloat r, gfloat g, gfloat b) -{ -#define COLOR { r, g, b, 1 } - gtk_snapshot_append_border (snapshot, - &GSK_ROUNDED_RECT_INIT (x, y, w, h), - (float[4]) { 1, 1, 1, 1 }, - (GdkRGBA[4]) { COLOR, COLOR, COLOR, COLOR }); -#undef COLOR -} -#else -#define debug_snapshot_border(s,x,y,w,h,r,g,b) -#endif - - -#if ENABLE_TEXTURE_DEBUG -static gint texture_count = 0; - -static void texture_weak_ref_callback (G_GNUC_UNUSED gpointer data, GObject* object) -{ - texture_count--; - g_message("%s object=%p texture_count=%d", __func__, object, texture_count); -} - -static void texture_debug_add_weak (gpointer object) -{ - g_object_weak_ref(G_OBJECT(object), texture_weak_ref_callback, NULL); - texture_count++; - - g_message("%s object=%p texture_count=%d", __func__, object, texture_count); -} - -#else -#define texture_debug_add_weak(o) -#endif - -typedef struct { - GtkSnapshot *snapshot; - GdkGLContext *gl_context; - gfloat scale; - struct timespec now; -} SnapshotData; - -static void -snapshot_surfaces (struct wlr_surface *surface, int sx, int sy, void *data) -{ - SnapshotData *sdata = data; - struct wlr_texture *texture = wlr_surface_get_texture (surface); - gint w, h; - - g_autoptr(GdkTexture) tex = wlr_texture_as_gdk (texture, sdata->gl_context, &surface->buffer_damage, surface->data); - texture_debug_add_weak (tex); - - w = gdk_texture_get_width (tex); - h = gdk_texture_get_height (tex); - - gtk_snapshot_save (sdata->snapshot); - gtk_snapshot_translate (sdata->snapshot, &GRAPHENE_POINT_INIT (sx, sy)); - - if (sdata->scale > 1.0) { - w = w / sdata->scale; - h = h / sdata->scale; - } - - gdk_paintable_snapshot (GDK_PAINTABLE (tex), sdata->snapshot, w, h); - gtk_snapshot_restore (sdata->snapshot); - - wlr_surface_send_frame_done (surface, &sdata->now); - - g_set_object (&surface->data, tex); -} - -static void -snapshot_surface (struct wlr_surface *surface, SnapshotData *data, gint x, gint y) -{ - gtk_snapshot_save (data->snapshot); - gtk_snapshot_translate (data->snapshot, &GRAPHENE_POINT_INIT (x, y)); - wlr_surface_for_each_surface (surface, snapshot_surfaces, data); - gtk_snapshot_restore (data->snapshot); -} - -static void -casilda_compositor_snapshot_popup (CasildaCompositorPopup *popup, SnapshotData *data, gint parent_x, gint parent_y) -{ - struct wlr_surface *psurface; - struct wlr_box pbox = {0, }; - - if (!popup->xdg_popup || xdg_surface_get_data (popup->xdg_popup->base, &psurface, &pbox)) - return; - - gint popup_x = parent_x + popup->xdg_popup->current.geometry.x; - gint popup_y = parent_y + popup->xdg_popup->current.geometry.y; - - snapshot_surface (psurface, data, popup_x - pbox.x, popup_y - pbox.y); - - for (GList *l = popup->popups; l; l = g_list_next (l)) - casilda_compositor_snapshot_popup (l->data, data, popup_x, popup_y); -} - - -static void -casilda_compositor_snapshot_toplevel (CasildaCompositorToplevel *toplevel, SnapshotData *data) -{ - struct wlr_surface *surface; - struct wlr_box tbox = {0, }; - - if (!toplevel->xdg_toplevel || xdg_surface_get_data (toplevel->xdg_toplevel->base, &surface, &tbox)) - return; - - gboolean has_transient = toplevel->toplevels != NULL; - - if (has_transient) - { - graphene_matrix_t matrix; - graphene_vec4_t offset; - - graphene_matrix_init_from_float (&matrix, - (float[16]) { - 0.8, 0, 0, 0, - 0, 0.8, 0, 0, - 0, 0, 0.8, 0, - 0, 0, 0, 1 - }); - - graphene_vec4_init (&offset, 0, 0, 0, 0); - gtk_snapshot_push_color_matrix (data->snapshot, &matrix, &offset); - } - - snapshot_surface (surface, data, toplevel->x - tbox.x, toplevel->y - tbox.y); - - /* Recurse toplevel popups */ - for (GList *l = toplevel->popups; l; l = g_list_next (l)) - casilda_compositor_snapshot_popup (l->data, data, toplevel->x, toplevel->y); - - if (has_transient) - gtk_snapshot_pop (data->snapshot); - - /* Recurse toplevel transient windows */ - for (GList *l = toplevel->toplevels; l; l = g_list_next (l)) - casilda_compositor_snapshot_toplevel (l->data, data); -} - -static void -casilda_compositor_get_scroll_offset(CasildaCompositorPrivate *priv, gint *x, gint *y) -{ - if (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]) - *x = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); - else - *x = 0; - - if (priv->adjustment[GTK_ORIENTATION_VERTICAL]) - *y = gtk_adjustment_get_value (priv->adjustment[GTK_ORIENTATION_VERTICAL]); - else - *y = 0; -} - -static inline gboolean -casilda_compositor_is_scrollable(CasildaCompositorPrivate *priv) -{ - return priv->adjustment[GTK_ORIENTATION_HORIZONTAL] && priv->adjustment[GTK_ORIENTATION_VERTICAL]; -} - -static void -casilda_compositor_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (widget); - SnapshotData data = { snapshot, priv->gl_context, 1.0, {0, } }; - gint x, y; - - data.scale = gdk_surface_get_scale (gtk_native_get_surface (gtk_widget_get_native (widget))); - clock_gettime (CLOCK_MONOTONIC, &data.now); - - /* Translate by scrollable offset */ - casilda_compositor_get_scroll_offset(priv, &x, &y); - - gtk_snapshot_save (snapshot); - gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (-x, -y)); - - /* Iterate all toplevels */ - for (GList *l = g_list_last (priv->toplevels); l; l = g_list_previous (l)) - casilda_compositor_snapshot_toplevel (l->data, &data); - - if (priv->frame_clock_updating) - { - gdk_frame_clock_end_updating (priv->frame_clock); - priv->frame_clock_updating = FALSE; - } - - gtk_snapshot_restore (snapshot); -} - -static void -casilda_compositor_queue_draw (CasildaCompositorPrivate *priv) -{ - if (!priv->frame_clock_updating) - { - priv->frame_clock_updating = TRUE; - gdk_frame_clock_begin_updating (priv->frame_clock); - } - - gtk_widget_queue_draw (priv->self); -} - -static void compositor_update_adjustment_toplevel (CasildaCompositorPrivate *priv, CasildaCompositorToplevel *toplevel); - -static void -compositor_update_adjustment (CasildaCompositorPrivate *priv, GList *toplevels) -{ - for (GList *l = toplevels; l; l = g_list_next (l)) - { - CasildaCompositorToplevel *toplevel = l->data; - - compositor_update_adjustment_toplevel (priv, toplevel); - - if (toplevel->toplevels) - compositor_update_adjustment (priv, toplevel->toplevels); - } -} - -static void -compositor_update_adjustment_toplevel (CasildaCompositorPrivate *priv, CasildaCompositorToplevel *toplevel) -{ - struct wlr_box tbox = {0, }; - - if (!casilda_compositor_is_scrollable(priv) || !toplevel->xdg_toplevel) - return; - - tbox = toplevel->xdg_toplevel->base->geometry; - - gint w = toplevel->x + tbox.width; - gint h = toplevel->y + tbox.height; - - if (w > gtk_adjustment_get_upper (priv->adjustment[GTK_ORIENTATION_HORIZONTAL])) - gtk_adjustment_set_upper (priv->adjustment[GTK_ORIENTATION_HORIZONTAL], w); - - if (h > gtk_adjustment_get_upper (priv->adjustment[GTK_ORIENTATION_VERTICAL])) - gtk_adjustment_set_upper (priv->adjustment[GTK_ORIENTATION_VERTICAL], h); - - if (toplevel->toplevels) - compositor_update_adjustment (priv, toplevel->toplevels); -} - -static void -casilda_compositor_size_allocate (GtkWidget *widget, int w, int h, G_GNUC_UNUSED int b) -{ - double scale = gdk_surface_get_scale (gtk_native_get_surface (gtk_widget_get_native (widget))); - CasildaCompositorPrivate *priv = GET_PRIVATE (widget); - struct wlr_output_state state; - - w = w * scale; - h = h * scale; - - if (casilda_compositor_is_scrollable(priv)) - { - gtk_adjustment_set_page_size (priv->adjustment[GTK_ORIENTATION_HORIZONTAL], w); - gtk_adjustment_set_page_size (priv->adjustment[GTK_ORIENTATION_VERTICAL], h); - gtk_adjustment_set_upper (priv->adjustment[GTK_ORIENTATION_HORIZONTAL], w); - gtk_adjustment_set_upper (priv->adjustment[GTK_ORIENTATION_VERTICAL], h); - - /* Update scrollable values */ - compositor_update_adjustment (priv, priv->toplevels); - - w = gtk_adjustment_get_upper (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); - h = gtk_adjustment_get_upper (priv->adjustment[GTK_ORIENTATION_VERTICAL]); - } - - wlr_output_state_init (&state); - wlr_output_state_set_enabled (&state, true); - wlr_output_state_set_custom_mode (&state, w, h, 0); - wlr_output_state_set_scale (&state, scale); - wlr_output_commit_state (&priv->output, &state); - wlr_output_state_finish (&state); - - /* Resize maximized/fullscreen windows */ - for (GList *l = priv->toplevels; l; l = g_list_next (l)) - { - CasildaCompositorToplevel *toplevel = l->data; - - if (priv->maximized || toplevel->xdg_toplevel->current.maximized || toplevel->xdg_toplevel->current.fullscreen) - { - if (priv->maximized) - { - toplevel->xdg_toplevel->scheduled.maximized = TRUE; - toplevel->xdg_toplevel->scheduled.fullscreen = FALSE; - } - - casilda_compositor_toplevel_configure (toplevel, 0, 0, w, h); - } - } -} - -static void -casilda_compositor_cursor_handler_remove (CasildaCompositorPrivate *priv) -{ - if (priv->on_cursor_surface_commit.notify) - { - wl_list_remove (&priv->on_cursor_surface_commit.link); - memset (&priv->on_cursor_surface_commit, 0, sizeof (struct wl_listener)); - } -} - -static void -casilda_compositor_reset_cursor (CasildaCompositorPrivate *priv) -{ - if (priv->self) - gtk_widget_set_cursor (priv->self, NULL); - - g_clear_object (&priv->cursor_gdk_cursor); - g_clear_object (&priv->cursor_gdk_texture); -} - -static void -casilda_compositor_reset_pointer_mode (CasildaCompositorPrivate *priv) -{ - priv->pointer_mode = CASILDA_POINTER_MODE_FOWARD; - priv->grabbed_toplevel = NULL; -} - -static CasildaCompositorToplevel * -get_toplevel_from_popup_at_pointer (CasildaCompositorToplevel *toplevel, - CasildaCompositorPopup *popup, - gint parent_x, - gint parent_y, - struct wlr_surface **surface, - double *sx, - double *sy) -{ - CasildaCompositorPrivate *priv = toplevel->priv; - struct wlr_xdg_surface *xdg_surface; - - if (!popup->xdg_popup || !(xdg_surface = popup->xdg_popup->base)) - return NULL; - - struct wlr_box geo = xdg_surface->geometry; - - gint popup_x = parent_x + popup->xdg_popup->current.geometry.x; - gint popup_y = parent_y + popup->xdg_popup->current.geometry.y; - - for (GList *pl = g_list_last(popup->popups); pl; pl = g_list_previous (pl)) - { - CasildaCompositorToplevel *t; - if ((t = get_toplevel_from_popup_at_pointer (toplevel, pl->data, popup_x, popup_y, surface, sx, sy))) - return toplevel; - } - - double psx = priv->pointer_x - popup_x + geo.x; - double psy = priv->pointer_y - popup_y + geo.y; - - struct wlr_surface *s = wlr_surface_surface_at (xdg_surface->surface, psx, psy, sx, sy); - - if (s) - { - if (surface) - *surface = s; - - return toplevel; - } - - return NULL; -} - -static CasildaCompositorToplevel * -get_toplevel_at_pointer (CasildaCompositorToplevel *toplevel, - struct wlr_surface **surface, - double *sx, - double *sy) -{ - CasildaCompositorPrivate *priv = toplevel->priv; - struct wlr_xdg_surface *xdg_surface; - - if (!toplevel->xdg_toplevel || !(xdg_surface = toplevel->xdg_toplevel->base)) - return NULL; - - /* Recurse toplevels first */ - for (GList *l = toplevel->toplevels; l; l = g_list_next (l)) - { - CasildaCompositorToplevel *toplevel = get_toplevel_at_pointer (l->data, surface, sx, sy); - if (toplevel) - return toplevel; - } - - /* Then iterate popups */ - for (GList *pl = g_list_last (toplevel->popups); pl; pl = g_list_previous (pl)) - { - CasildaCompositorToplevel *t; - if ((t = get_toplevel_from_popup_at_pointer (toplevel, pl->data, toplevel->x, toplevel->y, surface, sx, sy))) - return toplevel; - } - - struct wlr_box box = xdg_surface->geometry; - double tsx = priv->pointer_x - toplevel->x + box.x; - double tsy = priv->pointer_y - toplevel->y + box.y; - - struct wlr_surface *s = wlr_surface_surface_at (xdg_surface->surface, tsx, tsy, sx, sy); - - if (s) - { - if (surface) - *surface = s; - - return toplevel; - } - - return NULL; -} - -static CasildaCompositorToplevel * -casilda_compositor_get_toplevel_at_pointer (CasildaCompositorPrivate *priv, - struct wlr_surface **surface, - double *sx, - double *sy) -{ - if (surface) - *surface = NULL; - - for (GList *l = priv->toplevels; l; l = g_list_next (l)) - { - CasildaCompositorToplevel *toplevel = get_toplevel_at_pointer (l->data, surface, sx, sy); - if (toplevel) - return toplevel; - } - - return NULL; -} - -static void -casilda_compositor_toplevel_set_position (CasildaCompositorToplevel *toplevel, gint x, gint y) -{ - toplevel->x = x; - toplevel->y = y; - - casilda_compositor_queue_draw (toplevel->priv); - - compositor_update_adjustment_toplevel (toplevel->priv, toplevel); -} - -static void -casilda_compositor_toplevel_configure (CasildaCompositorToplevel *toplevel, - gint x, - gint y, - gint width, - gint height) -{ - casilda_compositor_toplevel_set_position (toplevel, x, y); - - if (width && height) - { - toplevel->xdg_toplevel->scheduled.width = width; - toplevel->xdg_toplevel->scheduled.height = height; - wlr_xdg_surface_schedule_configure (toplevel->xdg_toplevel->base); - } -} - -static void -casilda_compositor_toplevel_save_position (CasildaCompositorToplevel *toplevel) -{ - CasildaCompositorToplevelState *state = toplevel->state; - - if (!state) - return; - - /* Get position from scene node */ - state->x = toplevel->x; - state->y = toplevel->y; - - g_debug ("%s %s %dx%d %dx%d maximized=%d fullscreen=%d", - __func__, - toplevel->xdg_toplevel->app_id, - state->x, - state->y, - state->width, - state->height, - state->maximized, - state->fullscreen); -} - -static void -casilda_compositor_toplevel_save_size (CasildaCompositorToplevel *toplevel, - gint width, - gint height) -{ - CasildaCompositorToplevelState *state = toplevel->state; - - if (!state) - return; - - /* Assign current state from toplevel */ - state->width = width; - state->height = height; - - g_debug ("%s %s %dx%d %dx%d maximized=%d fullscreen=%d", - __func__, - toplevel->xdg_toplevel->app_id, - state->x, - state->y, - state->width, - state->height, - state->maximized, - state->fullscreen); -} - -static void -casilda_compositor_toplevel_toggle_maximize_fullscreen (CasildaCompositorToplevel *toplevel, - gboolean fullscreen) -{ - CasildaCompositorPrivate *priv = toplevel->priv; - struct wlr_xdg_toplevel *xdg_toplevel = toplevel->xdg_toplevel; - CasildaCompositorToplevelState *state = toplevel->state; - gboolean value; - - if (!xdg_toplevel->base->initialized || !xdg_toplevel->base->configured) - return; - - if (fullscreen) - { - value = xdg_toplevel->requested.fullscreen; - if (xdg_toplevel->current.fullscreen == value) - return; - - xdg_toplevel->scheduled.fullscreen = value; - - if (state) - state->fullscreen = value; - } - else - { - value = xdg_toplevel->requested.maximized; - if (xdg_toplevel->current.maximized == value) - return; - - xdg_toplevel->scheduled.maximized = value; - - if (state) - state->maximized = value; - } - - if (value) - { - GtkWidget *widget = priv->self; - struct wlr_box geometry = xdg_toplevel->base->geometry; - - toplevel->old_state.x = toplevel->x; - toplevel->old_state.y = toplevel->y; - toplevel->old_state.width = geometry.width; - toplevel->old_state.height = geometry.height; - - casilda_compositor_toplevel_configure (toplevel, - 0, 0, - gtk_widget_get_width (widget), - gtk_widget_get_height (widget)); - } - else - { - casilda_compositor_toplevel_configure (toplevel, - toplevel->old_state.x, - toplevel->old_state.y, - toplevel->old_state.width, - toplevel->old_state.height); - } -} - -static void -casilda_compositor_toplevel_set_maximized (CasildaCompositorToplevel *toplevel, - gboolean maximized) -{ - struct wlr_xdg_toplevel *xdg_toplevel = toplevel->xdg_toplevel; - CasildaCompositorPrivate *priv = toplevel->priv; - CasildaCompositorToplevelState *state = toplevel->state; - - if (!xdg_toplevel->base->initialized || !xdg_toplevel->base->configured) - return; - - if (maximized) - { - struct wlr_box geometry = xdg_toplevel->base->geometry; - - toplevel->old_state.x = toplevel->x; - toplevel->old_state.y = toplevel->y; - toplevel->old_state.width = geometry.width; - toplevel->old_state.height = geometry.height; - - xdg_toplevel->scheduled.maximized = TRUE; - xdg_toplevel->scheduled.fullscreen = FALSE; - - if (state) - state->maximized = TRUE; - - casilda_compositor_toplevel_configure (toplevel, - 0, 0, - gtk_widget_get_width (priv->self), - gtk_widget_get_height (priv->self)); - } - else - { - xdg_toplevel->scheduled.maximized = FALSE; - - if (state) - state->maximized = FALSE; - - casilda_compositor_toplevel_configure (toplevel, - toplevel->old_state.x, - toplevel->old_state.y, - toplevel->old_state.width, - toplevel->old_state.height); - } -} - -/** - * casilda_compositor_set_maximized: - * @compositor: a #CasildaCompositor - * @maximized: whether to force all toplevels to be maximized - * - * When set to %TRUE all toplevels, current and future, are forced to be - * maximized and fill the compositor widget. When set to %FALSE maximized - * toplevels are restored to their previous size. - */ -void -casilda_compositor_set_maximized (CasildaCompositor *compositor, - gboolean maximized) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (compositor); - - g_return_if_fail (CASILDA_IS_COMPOSITOR (compositor)); - - if (priv->maximized == maximized) - return; - - priv->maximized = maximized; - - for (GList *l = priv->toplevels; l; l = g_list_next (l)) - { - CasildaCompositorToplevel *toplevel = l->data; - - if (toplevel->xdg_toplevel->base->surface->mapped) - casilda_compositor_toplevel_set_maximized (toplevel, maximized); - } -} - -static void -casilda_compositor_handle_pointer_resize_toplevel (CasildaCompositorPrivate *priv) -{ - CasildaCompositorToplevel *toplevel = priv->grabbed_toplevel; - struct wlr_xdg_toplevel *xdg_toplevel = toplevel->xdg_toplevel; - struct wlr_box box; - gint border_x = priv->pointer_x - priv->grab_x; - gint border_y = priv->pointer_y - priv->grab_y; - gint new_left = priv->grab_box.x; - gint new_right = priv->grab_box.x + priv->grab_box.width; - gint new_top = priv->grab_box.y; - gint new_bottom = priv->grab_box.y + priv->grab_box.height; - gint new_width, new_height, min_width, min_height; - - min_width = xdg_toplevel->current.min_width; - min_height = xdg_toplevel->current.min_height; - - if (priv->resize_edges & WLR_EDGE_TOP) - { - new_top = border_y; - if (new_top >= new_bottom) - new_top = new_bottom - 1; - } - else if (priv->resize_edges & WLR_EDGE_BOTTOM) - { - new_bottom = border_y; - if (new_bottom <= new_top) - new_bottom = new_top + 1; - } - - if (priv->resize_edges & WLR_EDGE_LEFT) - { - new_left = border_x; - if (new_left >= new_right) - new_left = new_right - 1; - } - else if (priv->resize_edges & WLR_EDGE_RIGHT) - { - new_right = border_x; - if (new_right <= new_left) - new_right = new_left + 1; - } - - new_width = new_right - new_left; - new_height = new_bottom - new_top; - - if (new_width < min_width && new_height < min_height) - return; - - if (new_width < min_width) - { - if (priv->resize_edges & WLR_EDGE_LEFT) - new_left -= min_width - new_width; - new_width = min_width; - } - - if (new_height < min_height) - { - if (priv->resize_edges & WLR_EDGE_TOP) - new_top -= min_height - new_height; - new_height = min_height; - } - - box = toplevel->xdg_toplevel->base->geometry; - - wlr_xdg_toplevel_set_size (toplevel->xdg_toplevel, new_width, new_height); - - /* FIXME: we probably need to wait for the new size to be in effect - * before setting the position - */ - casilda_compositor_toplevel_set_position (toplevel, new_left - box.x, new_top - box.y); - - casilda_compositor_toplevel_save_position (toplevel); - casilda_compositor_toplevel_save_size (toplevel, new_width, new_height); -} - -static void -casilda_compositor_handle_pointer_motion (CasildaCompositorPrivate *priv) -{ - if (priv->grabbed_toplevel && priv->pointer_mode == CASILDA_POINTER_MODE_MOVE) - { - /* Unmaximize maximized windows on move */ - if (priv->grabbed_toplevel && priv->grabbed_toplevel->xdg_toplevel->current.maximized) - { - struct wlr_box geometry = priv->grabbed_toplevel->xdg_toplevel->base->geometry; - gfloat ratio = priv->grab_x / (gfloat)geometry.width; - - /* Adjust grab position */ - priv->grab_x = priv->grabbed_toplevel->old_state.width * ratio; - - priv->grabbed_toplevel->old_state.x = priv->pointer_x - priv->grab_x; - priv->grabbed_toplevel->old_state.y = priv->pointer_y - priv->grab_y; - priv->grabbed_toplevel->xdg_toplevel->requested.maximized = FALSE; - casilda_compositor_toplevel_toggle_maximize_fullscreen(priv->grabbed_toplevel, FALSE); - return; - } - - casilda_compositor_toplevel_set_position (priv->grabbed_toplevel, - priv->pointer_x - priv->grab_x, - priv->pointer_y - priv->grab_y); - - casilda_compositor_toplevel_save_position (priv->grabbed_toplevel); - } - else if (priv->pointer_mode == CASILDA_POINTER_MODE_RESIZE) - { - casilda_compositor_handle_pointer_resize_toplevel (priv); - } - else - { - CasildaCompositorToplevel *toplevel; - struct wlr_surface *surface; - double sx, sy; - - toplevel = casilda_compositor_get_toplevel_at_pointer (priv, &surface, &sx, &sy); - - if (!toplevel) - casilda_compositor_reset_cursor (priv); - - if (surface) - { - uint32_t time = gtk_event_controller_get_current_event_time (priv->motion_controller); - wlr_seat_pointer_notify_enter (priv->seat, surface, sx, sy); - wlr_seat_pointer_notify_motion (priv->seat, time, sx, sy); - } - else - { - wlr_seat_pointer_clear_focus (priv->seat); - } - } -} - -static void -on_motion_controller_enter (G_GNUC_UNUSED GtkEventControllerMotion *self, - gdouble x, - gdouble y, - CasildaCompositorPrivate *priv) -{ - gint x_offset, y_offset; - - casilda_compositor_get_scroll_offset (priv, &x_offset, &y_offset); - - priv->pointer_x = x + x_offset; - priv->pointer_y = y + y_offset; - casilda_compositor_handle_pointer_motion (priv); - wlr_seat_pointer_notify_frame (priv->seat); -} - -static void -on_motion_controller_leave (G_GNUC_UNUSED GtkEventControllerMotion *self, - CasildaCompositorPrivate *priv) -{ - wlr_seat_pointer_clear_focus (priv->seat); -} - -static void -on_motion_controller_motion (G_GNUC_UNUSED GtkEventControllerMotion *self, - gdouble x, - gdouble y, - CasildaCompositorPrivate *priv) -{ - gint x_offset, y_offset; - - casilda_compositor_get_scroll_offset (priv, &x_offset, &y_offset); - - /* Clamp pointer to widget coordinates */ - x = CLAMP (x, 0, gtk_widget_get_width (priv->self)); - y = CLAMP (y, 0, gtk_widget_get_height (priv->self)); - - /* Add scrollable offset */ - priv->pointer_x = x + x_offset; - priv->pointer_y = y + y_offset; - - casilda_compositor_handle_pointer_motion (priv); - wlr_seat_pointer_notify_frame (priv->seat); -} - -static gboolean -on_scroll_controller_scroll (GtkEventControllerScroll *self, - gdouble dx, - gdouble dy, - CasildaCompositorPrivate *priv) -{ - uint32_t time_msec = gtk_event_controller_get_current_event_time (GTK_EVENT_CONTROLLER (self)); - gint idx, idy; - - idx = dx * WLR_POINTER_AXIS_DISCRETE_STEP; - idy = dy * WLR_POINTER_AXIS_DISCRETE_STEP; - - if (idx != 0) - { - wlr_seat_pointer_notify_axis (priv->seat, - time_msec, - WL_POINTER_AXIS_HORIZONTAL_SCROLL, - idx, - idx, - WL_POINTER_AXIS_SOURCE_WHEEL, - WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); - } - - if (idy != 0) - { - wlr_seat_pointer_notify_axis (priv->seat, - time_msec, - WL_POINTER_AXIS_VERTICAL_SCROLL, - idy, - idy, - WL_POINTER_AXIS_SOURCE_WHEEL, - WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL); - } - - wlr_seat_pointer_notify_frame (priv->seat); - - return TRUE; -} - -static void -casilda_compositor_focus_toplevel (CasildaCompositorToplevel *toplevel, - struct wlr_surface *surface) -{ - CasildaCompositorPrivate *priv = toplevel->priv; - struct wlr_surface *focused_surface = priv->seat->keyboard_state.focused_surface; - struct wlr_xdg_toplevel *xdg_toplevel = toplevel->xdg_toplevel; - - if (focused_surface == surface || toplevel->toplevels) - return; - - if (focused_surface) - { - struct wlr_xdg_toplevel *focused_toplevel = - wlr_xdg_toplevel_try_from_wlr_surface (focused_surface); - - if (focused_toplevel) - wlr_xdg_toplevel_set_activated (focused_toplevel, false); - } - - /* Move it to the front */ - wlr_xdg_toplevel_set_activated (xdg_toplevel, true); - - if (xdg_toplevel->parent) - { - CasildaCompositorToplevel *parent = xdg_toplevel->parent->base->data; - if (parent) - { - parent->toplevels = g_list_remove (parent->toplevels, toplevel); - parent->toplevels = g_list_prepend (parent->toplevels, toplevel); - } - } - else - { - priv->toplevels = g_list_remove (priv->toplevels, toplevel); - priv->toplevels = g_list_prepend (priv->toplevels, toplevel); - } - - wlr_seat_keyboard_notify_enter (priv->seat, - xdg_toplevel->base->surface, - priv->keyboard.keycodes, - priv->keyboard.num_keycodes, - &priv->keyboard.modifiers); -} - -static void -casilda_compositor_seat_pointer_notify (GtkGestureClick *self, - CasildaCompositorPrivate *priv, - gint button, - enum wl_pointer_button_state state) -{ - uint32_t time_msec, wl_button; - struct wlr_surface *surface = NULL; - CasildaCompositorToplevel *toplevel; - double sx, sy; - - button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (self)); - - if (button == 1) - { - wl_button = BTN_LEFT; - } - else if (button == 2) - { - wl_button = BTN_MIDDLE; - } - else if (button == 3) - { - wl_button = BTN_RIGHT; - } - else - { - g_warning ("%s unknown button %u", __func__, button); - return; - } - - time_msec = gtk_event_controller_get_current_event_time (GTK_EVENT_CONTROLLER (self)); - - wlr_seat_pointer_notify_button (priv->seat, time_msec, wl_button, state); - wlr_seat_pointer_notify_frame (priv->seat); - - toplevel = casilda_compositor_get_toplevel_at_pointer (priv, &surface, &sx, &sy); - - if (state == WL_POINTER_BUTTON_STATE_RELEASED) - casilda_compositor_reset_pointer_mode (priv); - else if (toplevel) - casilda_compositor_focus_toplevel (toplevel, surface); -} - -static void -on_click_gesture_pressed (GtkGestureClick *self, - G_GNUC_UNUSED gint n_press, - G_GNUC_UNUSED gdouble x, - G_GNUC_UNUSED gdouble y, - CasildaCompositorPrivate *priv) -{ - gint button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (self)); - - gtk_widget_grab_focus (priv->self); - - casilda_compositor_seat_pointer_notify (self, priv, button, WL_POINTER_BUTTON_STATE_PRESSED); -} - -static void -on_click_gesture_released (GtkGestureClick *self, - G_GNUC_UNUSED gint n_press, - G_GNUC_UNUSED gdouble x, - G_GNUC_UNUSED gdouble y, - CasildaCompositorPrivate *priv) -{ - gint button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (self)); - - casilda_compositor_seat_pointer_notify (self, priv, button, WL_POINTER_BUTTON_STATE_RELEASED); -} - -static void -casilda_compositor_seat_key_notify (GtkEventControllerKey *self, - CasildaCompositorPrivate *priv, - uint32_t key, - uint32_t state) -{ - uint32_t time_msec = gtk_event_controller_get_current_event_time (GTK_EVENT_CONTROLLER (self)); - - wlr_seat_keyboard_notify_key (priv->seat, time_msec, key - 8, state); -} - -static gboolean -on_key_controller_key_pressed (GtkEventControllerKey *self, - G_GNUC_UNUSED guint keyval, - guint keycode, - G_GNUC_UNUSED GdkModifierType state, - CasildaCompositorPrivate *priv) -{ - casilda_compositor_seat_key_notify (self, priv, keycode, WL_KEYBOARD_KEY_STATE_PRESSED); - return TRUE; -} - -static void -on_key_controller_key_released (GtkEventControllerKey * self, - G_GNUC_UNUSED guint keyval, - guint keycode, - G_GNUC_UNUSED GdkModifierType state, - CasildaCompositorPrivate *priv) -{ - casilda_compositor_seat_key_notify (self, priv, keycode, WL_KEYBOARD_KEY_STATE_RELEASED); -} - -static gboolean -on_key_controller_modifiers (G_GNUC_UNUSED GtkEventControllerKey *self, - GdkModifierType state, - CasildaCompositorPrivate *priv) -{ - struct wlr_keyboard_modifiers modifiers = { 0, }; - guint wl_state = 0; - - if (state & GDK_SHIFT_MASK) - wl_state |= WLR_MODIFIER_SHIFT; - else if (state & GDK_LOCK_MASK) - wl_state |= WLR_MODIFIER_CAPS; - else if (state & GDK_CONTROL_MASK) - wl_state |= WLR_MODIFIER_CTRL; - else if (state & GDK_ALT_MASK) - wl_state |= WLR_MODIFIER_ALT; - else if (state & GDK_SUPER_MASK) - wl_state |= WLR_MODIFIER_LOGO; - else if (state & GDK_HYPER_MASK) - wl_state |= WLR_MODIFIER_MOD2; - else if (state & GDK_META_MASK) - wl_state |= WLR_MODIFIER_MOD3; - - modifiers.depressed = wl_state; - - wlr_seat_keyboard_notify_modifiers (priv->seat, &modifiers); - - return TRUE; -} - -static void -cursor_handle_surface_commit (struct wl_listener *listener, void *data) -{ - CasildaCompositorPrivate *priv = wl_container_of (listener, priv, on_cursor_surface_commit); - struct wlr_surface *surface = data; - WlrTexture *texture = NULL; - - texture = wlr_surface_get_texture (surface); - - if (!texture) - return; - - g_autoptr(GdkTexture) tex = wlr_texture_as_gdk (texture, priv->gl_context, NULL, NULL); - texture_debug_add_weak (tex); - - g_set_object (&priv->cursor_gdk_texture, tex); - - priv->hotspot_x -= surface->current.dx; - priv->hotspot_y -= surface->current.dy; - - if (!tex) - return; - - /* Finally create cursor from texture */ - g_autoptr (GdkCursor) gdk_cursor = gdk_cursor_new_from_texture (tex, priv->hotspot_x, priv->hotspot_y, NULL); - g_set_object (&priv->cursor_gdk_cursor, gdk_cursor); - - /* Set cursor */ - if (gdk_cursor) - gtk_widget_set_cursor (priv->self, priv->cursor_gdk_cursor); -} - -static void -on_seat_request_cursor (struct wl_listener *listener, void *data) -{ - CasildaCompositorPrivate *priv = wl_container_of (listener, priv, on_request_cursor); - struct wlr_seat_pointer_request_set_cursor_event *event = data; - struct wlr_seat_client *focused_client = priv->seat->pointer_state.focused_client; - struct wlr_surface *surface = event->surface; - - if (focused_client != event->seat_client) - return; - - if (!surface) - return; - - priv->hotspot_x = event->hotspot_x; - priv->hotspot_y = event->hotspot_y; - - wlr_surface_send_enter (surface, &priv->output); - - /* We only keep track of the last cursor change */ - casilda_compositor_cursor_handler_remove (priv); - - /* Update cursor once the surface has been committed */ - wl_signal_add (&surface->events.commit, &priv->on_cursor_surface_commit); - priv->on_cursor_surface_commit.notify = cursor_handle_surface_commit; -} - -static bool -casilda_compositor_backend_start (struct wlr_backend *wlr_backend) -{ - CasildaCompositorPrivate *priv = wl_container_of (wlr_backend, priv, backend); - g_info ("Starting Casilda backend at %s", priv->socket); - return true; -} - -static void -casilda_compositor_backend_destroy (struct wlr_backend *wlr_backend) -{ - CasildaCompositorPrivate *priv = wl_container_of (wlr_backend, priv, backend); - - wlr_backend_finish (&priv->backend); - wlr_output_destroy (&priv->output); -} - -static bool -casilda_compositor_output_commit (G_GNUC_UNUSED struct wlr_output *wlr_output, - G_GNUC_UNUSED const struct wlr_output_state *state) -{ - return TRUE; -} - -static void -casilda_compositor_output_destroy (G_GNUC_UNUSED struct wlr_output *wlr_output) -{ - /* TODO: disconnect from GdkFrameClock */ -} - -static void -casilda_compositor_backend_init (CasildaCompositorPrivate *priv) -{ - /* Backend implementation */ - priv->backend_impl.start = casilda_compositor_backend_start; - priv->backend_impl.destroy = casilda_compositor_backend_destroy; - - /* Init wlroots backend */ - wlr_backend_init (&priv->backend, &priv->backend_impl); - - /* Set basic capabilities, DMABUF will be set after initializing GL Context */ - priv->backend.buffer_caps = WLR_BUFFER_CAP_DATA_PTR | WLR_BUFFER_CAP_SHM; -} - -static void -casilda_compositor_output_init (CasildaCompositorPrivate *priv) -{ - struct wlr_output_state state; - - wlr_output_state_init (&state); - - /* Initialize custom output iface */ - priv->output_impl.commit = casilda_compositor_output_commit; - priv->output_impl.destroy = casilda_compositor_output_destroy; - - /* Actual size will be set on size_allocate() */ - wlr_output_state_set_custom_mode (&state, 0, 0, 0); - - /* Init wlr output */ - wlr_output_init (&priv->output, - &priv->backend, - &priv->output_impl, - wl_display_get_event_loop (priv->wl_display), - &state); - - /* Set a name */ - wlr_output_set_name (&priv->output, "CasildaCompositor"); - wlr_output_set_description (&priv->output, "CasildaCompositor output"); - - /* Init output rendering */ - wlr_output_init_render (&priv->output, priv->allocator, priv->renderer); - - /* Make output global */ - wlr_output_create_global (&priv->output, priv->wl_display); - - wlr_output_state_finish (&state); -} - -static void -casilda_pointer_mode_init (CasildaCompositorPrivate *priv) -{ - wlr_pointer_init (&priv->pointer, NULL, "Casilda-pointer"); - - priv->on_request_cursor.notify = on_seat_request_cursor; - wl_signal_add (&priv->seat->events.request_set_cursor, - &priv->on_request_cursor); - - priv->motion_controller = gtk_event_controller_motion_new (); - priv->scroll_controller = gtk_event_controller_scroll_new (GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES | - GTK_EVENT_CONTROLLER_SCROLL_DISCRETE); - priv->click_gesture = gtk_gesture_click_new (); - gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->click_gesture), 0); - - g_signal_connect (priv->motion_controller, "enter", - G_CALLBACK (on_motion_controller_enter), - priv); - g_signal_connect (priv->motion_controller, "leave", - G_CALLBACK (on_motion_controller_leave), - priv); - g_signal_connect (priv->motion_controller, "motion", - G_CALLBACK (on_motion_controller_motion), - priv); - - g_signal_connect (priv->scroll_controller, "scroll", - G_CALLBACK (on_scroll_controller_scroll), - priv); - - g_signal_connect (priv->click_gesture, "pressed", - G_CALLBACK (on_click_gesture_pressed), - priv); - g_signal_connect (priv->click_gesture, "released", - G_CALLBACK (on_click_gesture_released), - priv); - - gtk_widget_add_controller (priv->self, priv->motion_controller); - gtk_widget_add_controller (priv->self, priv->scroll_controller); - gtk_widget_add_controller (priv->self, GTK_EVENT_CONTROLLER (priv->click_gesture)); - - g_object_ref (priv->motion_controller); - g_object_ref (priv->scroll_controller); - g_object_ref (priv->click_gesture); -} - -static void -casilda_compositor_keyboard_init (CasildaCompositorPrivate *priv) -{ - struct xkb_keymap *keymap = NULL; - struct xkb_state *state = NULL; - GdkDevice *gkeyboard; - GdkDisplay *gdisplay; - GdkSeat *gseat; - - wlr_keyboard_init (&priv->keyboard, NULL, "Casilda-keyboard"); - - gdisplay = gtk_widget_get_display (priv->self); - gseat = gdk_display_get_default_seat (gdisplay); - gkeyboard = gdk_seat_get_keyboard (gseat); - -#ifdef GDK_WINDOWING_WAYLAND - if (GDK_IS_WAYLAND_DEVICE (gkeyboard)) - { - keymap = gdk_wayland_device_get_xkb_keymap (gkeyboard); - - /* TODO: add a way to get keymap state from gtk wayland backend - * Or even better add a way to get the layout directly - */ - - xkb_keymap_ref (keymap); - } -#endif - -#if defined(GDK_WINDOWING_X11) && defined(HAVE_X11_XCB) - if (GDK_IS_X11_DEVICE_XI2 (gkeyboard)) - { -G_GNUC_BEGIN_IGNORE_DEPRECATIONS - struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS); - Display *dpy = gdk_x11_display_get_xdisplay (GDK_X11_DISPLAY (gdisplay)); - - keymap = xkb_x11_keymap_new_from_device (context, - XGetXCBConnection (dpy), - gdk_x11_device_get_id (gkeyboard), - XKB_KEYMAP_COMPILE_NO_FLAGS); - state = xkb_x11_state_new_from_device (keymap, - XGetXCBConnection (dpy), - gdk_x11_device_get_id (gkeyboard)); - xkb_context_unref (context); -G_GNUC_END_IGNORE_DEPRECATIONS - } -#endif - - /* Fallback to US */ - if (keymap == NULL) - { - struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS); - keymap = xkb_keymap_new_from_names (context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkb_context_unref (context); - } - - /* Set keymap */ - wlr_keyboard_set_keymap (&priv->keyboard, keymap); - - /* Update layout if present */ - if (state) - { - gint active_layout = -1; - - for (guint i = 0; i < xkb_keymap_num_layouts (keymap); i++) - { - if (xkb_state_layout_index_is_active (state, - i, - XKB_STATE_LAYOUT_EFFECTIVE)) - active_layout = i; - - g_debug ("\t %i %s", i, xkb_keymap_layout_get_name (keymap, i)); - } - - if (active_layout >= 0) - { - wlr_keyboard_notify_modifiers (&priv->keyboard, - priv->keyboard.modifiers.depressed, - priv->keyboard.modifiers.latched, - priv->keyboard.modifiers.locked, - active_layout); - } - xkb_state_unref (state); - } - - xkb_keymap_unref (keymap); - - wlr_seat_set_keyboard (priv->seat, &priv->keyboard); - - priv->key_controller = gtk_event_controller_key_new (); - g_signal_connect (priv->key_controller, "key-pressed", - G_CALLBACK (on_key_controller_key_pressed), - priv); - g_signal_connect (priv->key_controller, "key-released", - G_CALLBACK (on_key_controller_key_released), - priv); - g_signal_connect (priv->key_controller, "modifiers", - G_CALLBACK (on_key_controller_modifiers), - priv); - gtk_widget_add_controller (priv->self, priv->key_controller); - g_object_ref (priv->key_controller); -} - -static void -casilda_compositor_init (CasildaCompositor *compositor) -{ - GtkWidget *widget = GTK_WIDGET (compositor); - - gtk_widget_set_overflow (widget, GTK_OVERFLOW_HIDDEN); - gtk_widget_set_focusable (widget, TRUE); -} - -static void -casilda_compositor_constructed (GObject *object) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (object); - - priv->self = GTK_WIDGET (object); - - /* Toplevel state */ - priv->toplevel_state = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); - - casilda_compositor_backend_init (priv); - casilda_compositor_wlr_init (priv); - casilda_compositor_output_init (priv); - casilda_pointer_mode_init (priv); - casilda_compositor_keyboard_init (priv); - - casilda_compositor_reset_pointer_mode (priv); - - priv->wl_source = casilda_wayland_source_new (priv->wl_display); - g_source_attach (priv->wl_source, NULL); - - /* Start the backend. */ - if (!wlr_backend_start (&priv->backend)) - /* TODO: handle error */ - g_warning("Could not start backend"); - - G_OBJECT_CLASS (casilda_compositor_parent_class)->constructed (object); -} - -static void -casilda_compositor_dispose (GObject *object) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (object); - - g_clear_object (&priv->motion_controller); - g_clear_object (&priv->scroll_controller); - g_clear_object (&priv->key_controller); - g_clear_object (&priv->click_gesture); - g_clear_object (&priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); - g_clear_object (&priv->adjustment[GTK_ORIENTATION_VERTICAL]); - - casilda_compositor_reset_cursor (priv); - - g_clear_object (&priv->gl_context); - - G_OBJECT_CLASS (casilda_compositor_parent_class)->dispose (object); -} - -static void -casilda_compositor_finalize (GObject *object) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (object); - - /* Unlink signals */ - wl_list_remove (&priv->new_xdg_toplevel.link); - wl_list_remove (&priv->new_xdg_popup.link); - wl_list_remove (&priv->request_activate.link); - wl_list_remove (&priv->request_set_selection.link); - - wl_list_remove (&priv->on_request_cursor.link); - - g_clear_pointer (&priv->toplevel_state, g_hash_table_destroy); - g_clear_pointer (&priv->socket, g_free); - - wl_display_destroy_clients (priv->wl_display); - - wlr_keyboard_finish (&priv->keyboard); - wlr_pointer_finish (&priv->pointer); - wlr_allocator_destroy (priv->allocator); - wlr_renderer_destroy (priv->renderer); - wlr_backend_destroy (&priv->backend); - wl_display_destroy (priv->wl_display); - - g_source_destroy (priv->wl_source); - - G_OBJECT_CLASS (casilda_compositor_parent_class)->finalize (object); -} - -static void -compositor_adjustment_value_changed (G_GNUC_UNUSED GtkAdjustment *adjustment, gpointer data) -{ - gtk_widget_queue_draw (GTK_WIDGET (data)); -} - -static void -compositor_set_adjustment (CasildaCompositor *compositor, GtkOrientation orientation, GtkAdjustment *adjustment) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (compositor); - GtkAdjustment **adjustment_prop = &priv->adjustment[orientation]; - - if (adjustment == *adjustment_prop) - return; - - if (*adjustment_prop) - g_signal_handlers_disconnect_by_func (*adjustment_prop, compositor_adjustment_value_changed, compositor); - - g_set_object (adjustment_prop, adjustment); - - if (adjustment) - { - g_signal_connect (adjustment, "value-changed", G_CALLBACK (compositor_adjustment_value_changed), compositor); - - compositor_adjustment_value_changed (adjustment, compositor); - } -} - -static void -casilda_compositor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (object); - - g_return_if_fail (CASILDA_IS_COMPOSITOR (object)); - - switch (prop_id) - { - case PROP_SOCKET: - g_set_str (&priv->socket, g_value_get_string (value)); - break; - case PROP_MAXIMIZED: - casilda_compositor_set_maximized (CASILDA_COMPOSITOR (object), - g_value_get_boolean (value)); - break; - case PROP_HADJUSTMENT: - compositor_set_adjustment (CASILDA_COMPOSITOR (object), GTK_ORIENTATION_HORIZONTAL, g_value_get_object (value)); - break; - case PROP_VADJUSTMENT: - compositor_set_adjustment (CASILDA_COMPOSITOR (object), GTK_ORIENTATION_VERTICAL, g_value_get_object (value)); - break; - case PROP_HSCROLL_POLICY: - case PROP_VSCROLL_POLICY: - g_warning ("Property %s is ignored", pspec->name); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -casilda_compositor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - CasildaCompositorPrivate *priv; - - g_return_if_fail (CASILDA_IS_COMPOSITOR (object)); - priv = GET_PRIVATE (object); - - switch (prop_id) - { - case PROP_SOCKET: - g_value_set_string (value, priv->socket); - break; - case PROP_MAXIMIZED: - g_value_set_boolean (value, priv->maximized); - break; - case PROP_HADJUSTMENT: - g_value_set_object (value, priv->adjustment[GTK_ORIENTATION_HORIZONTAL]); - break; - case PROP_VADJUSTMENT: - g_value_set_object (value, priv->adjustment[GTK_ORIENTATION_VERTICAL]); - break; - case PROP_HSCROLL_POLICY: - case PROP_VSCROLL_POLICY: - g_value_set_enum (value, GTK_SCROLL_NATURAL); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -on_casilda_compositor_frame_clock_update (G_GNUC_UNUSED GdkFrameClock *self, - CasildaCompositorPrivate *priv) -{ - wlr_output_send_frame (&priv->output); -} - -static void -casilda_compositor_realize (GtkWidget *widget) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (widget); - - GTK_WIDGET_CLASS (casilda_compositor_parent_class)->realize (widget); - - priv->frame_clock = gtk_widget_get_frame_clock (widget); - priv->frame_clock_source = - g_signal_connect (priv->frame_clock, "update", - G_CALLBACK (on_casilda_compositor_frame_clock_update), - priv); -} - -static void -casilda_compositor_unrealize (GtkWidget *widget) -{ - CasildaCompositorPrivate *priv = GET_PRIVATE (widget); - - if (priv->frame_clock && priv->frame_clock_source) - { - g_signal_handler_disconnect (priv->frame_clock, priv->frame_clock_source); - priv->frame_clock_source = 0; - } - - priv->frame_clock = NULL; - - GTK_WIDGET_CLASS (casilda_compositor_parent_class)->unrealize (widget); -} - -static void -casilda_compositor_class_init (CasildaCompositorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - object_class->constructed = casilda_compositor_constructed; - object_class->dispose = casilda_compositor_dispose; - object_class->finalize = casilda_compositor_finalize; - object_class->set_property = casilda_compositor_set_property; - object_class->get_property = casilda_compositor_get_property; - - widget_class->snapshot = casilda_compositor_snapshot; - widget_class->size_allocate = casilda_compositor_size_allocate; - widget_class->realize = casilda_compositor_realize; - widget_class->unrealize = casilda_compositor_unrealize; - - /* GtkScrollable implementation */ - g_object_class_override_property (object_class, PROP_HADJUSTMENT, "hadjustment"); - g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment"); - g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy"); - g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy"); - - /* Properties */ - - /** - * CasildaCompositor:socket: - * - * Wayland socket the compositor will listen on. - * - * If NULL you can still use WAYLAND_SOCKET with an fd returned by - * casilda_compositor_get_client_socket_fd() instead of setting up WAYLAND_DISPLAY. - * - */ - properties[PROP_SOCKET] = - g_param_spec_string ("socket", "", "", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - /** - * CasildaCompositor:maximized: - * - * When set to %TRUE all toplevels, current and future, are forced to be - * maximized and fill the compositor widget. - */ - properties[PROP_MAXIMIZED] = - g_param_spec_boolean ("maximized", "", "", FALSE, G_PARAM_READWRITE); - - g_object_class_install_properties (object_class, N_PROPERTIES, properties); -} - -/* wlroots */ - -static void -seat_request_set_selection (struct wl_listener *listener, void *data) -{ - CasildaCompositorPrivate *priv = wl_container_of (listener, priv, request_set_selection); - struct wlr_seat_request_set_selection_event *event = data; - - wlr_seat_set_selection (priv->seat, event->source, event->serial); - /* TODO: integrate with Gtk clipboard */ -} - -static void -xdg_toplevel_map (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorToplevel *toplevel = wl_container_of (listener, toplevel, map); - CasildaCompositorPrivate *priv = toplevel->priv; - struct wlr_xdg_toplevel *xdg_toplevel = toplevel->xdg_toplevel; - CasildaCompositorToplevelState *state = toplevel->state; - struct wlr_box box; - gint offset_x, offset_y; - - casilda_compositor_get_scroll_offset (priv, &offset_x, &offset_y); - - box = xdg_toplevel->base->geometry; - - if (xdg_toplevel->parent) - { - CasildaCompositorToplevel *parent = xdg_toplevel->parent->base->data; - - if (parent) - { - struct wlr_box parent_box = parent->xdg_toplevel->base->geometry; - - /* Start in the middle of the parent window and cap to 0,0 */ - toplevel->x = MAX(offset_x, parent->x + (parent_box.width - box.width) / 2); - toplevel->y = MAX(offset_y, parent->y + (parent_box.height - box.height) / 2); - - parent->toplevels = g_list_prepend (parent->toplevels, toplevel); - } - } - else - { - /* Start in the middle of the compositor viewport */ - toplevel->x = offset_x + MAX(0, (gtk_widget_get_width (toplevel->priv->self) - box.width) / 2); - toplevel->y = offset_y + MAX(0, (gtk_widget_get_height (toplevel->priv->self) - box.height) / 2); - - toplevel->priv->toplevels = g_list_prepend (toplevel->priv->toplevels, toplevel); - } - - if (priv->maximized && !xdg_toplevel->requested.fullscreen) - { - if (state) - state->maximized = TRUE; - - xdg_toplevel->scheduled.maximized = TRUE; - xdg_toplevel->scheduled.fullscreen = FALSE; - - toplevel->old_state.x = toplevel->x; - toplevel->old_state.y = toplevel->y; - toplevel->old_state.width = box.width; - toplevel->old_state.height = box.height; - - casilda_compositor_toplevel_configure (toplevel, - 0, 0, - gtk_widget_get_width (priv->self), - gtk_widget_get_height (priv->self)); - - casilda_compositor_focus_toplevel (toplevel, xdg_toplevel->base->surface); - casilda_compositor_queue_draw (priv); - return; - } - - if (state) - { - /* Restore this window state */ - xdg_toplevel->scheduled.fullscreen = state->fullscreen; - xdg_toplevel->scheduled.maximized = state->maximized; - - g_debug ("%s %s %dx%d %dx%d maximized=%d fullscreen=%d", - __func__, - xdg_toplevel->app_id, - state->x, - state->y, - state->width, - state->height, - state->maximized, - state->fullscreen); - - if (state->fullscreen || state->maximized) - { - GtkWidget *widget = toplevel->priv->self; - - toplevel->old_state = *state; - - casilda_compositor_toplevel_configure (toplevel, - 0, 0, - gtk_widget_get_width (widget), - gtk_widget_get_height (widget)); - } - else - { - casilda_compositor_toplevel_configure (toplevel, - state->x, - state->y, - state->width, - state->height); - } - } - else - casilda_compositor_focus_toplevel (toplevel, xdg_toplevel->base->surface); - - casilda_compositor_queue_draw (toplevel->priv); -} - -static void -xdg_toplevel_unmap (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorToplevel *toplevel = wl_container_of (listener, toplevel, unmap); - struct wlr_xdg_toplevel *xdg_toplevel = toplevel->xdg_toplevel; - - if (toplevel == toplevel->priv->grabbed_toplevel) - casilda_compositor_reset_pointer_mode (toplevel->priv); - - toplevel->state = NULL; - - if (xdg_toplevel->parent) - { - CasildaCompositorToplevel *parent = xdg_toplevel->parent->base->data; - if (parent) - { - parent->toplevels = g_list_remove (parent->toplevels, toplevel); - - /* focus parent */ - casilda_compositor_focus_toplevel (parent, parent->xdg_toplevel->base->surface); - } - } - else - toplevel->priv->toplevels = g_list_remove (toplevel->priv->toplevels, toplevel); - - casilda_compositor_queue_draw (toplevel->priv); -} - -static void -xdg_toplevel_commit (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorToplevel *toplevel = wl_container_of (listener, toplevel, commit); - - if (toplevel->xdg_toplevel->base->initial_commit) - wlr_xdg_toplevel_set_size (toplevel->xdg_toplevel, 0, 0); - - casilda_compositor_queue_draw (toplevel->priv); - toplevel->needs_update = TRUE; -} - - -static void -xdg_subsurface_commit (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorSubsurface *subsurface = wl_container_of (listener, subsurface, commit); - casilda_compositor_queue_draw (subsurface->priv); -} - -static void -xdg_subsurface_destroy (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorSubsurface *subsurface = wl_container_of (listener, subsurface, destroy); - - wl_list_remove (&subsurface->commit.link); - wl_list_remove (&subsurface->destroy.link); - - /* Unref texture */ - g_clear_object (&subsurface->wlr_subsurface->surface->data); - - subsurface->parent->list = g_list_remove (subsurface->parent->list, subsurface); - - g_free (subsurface); -} - -static void -xdg_subsurface_new_subsurface (struct wl_listener *listener, void *data) -{ - CasildaCompositorSurfaces *subsurfaces = wl_container_of (listener, subsurfaces, new_subsurface); - struct wlr_subsurface *wlr_subsurface = data; - struct wlr_xdg_toplevel *xdg_toplevel; - struct wlr_xdg_popup *xdg_popup; - - CasildaCompositorSubsurface *subsurface = g_new0 (CasildaCompositorSubsurface, 1); - - if ((xdg_toplevel = wlr_xdg_toplevel_try_from_wlr_surface (wlr_subsurface->parent))) - { - CasildaCompositorToplevel *toplevel = xdg_toplevel->base->data; - subsurface->priv = toplevel->priv; - } - else if ((xdg_popup = wlr_xdg_popup_try_from_wlr_surface(wlr_subsurface->parent))) - { - CasildaCompositorPopup *popup = xdg_popup->base->data; - subsurface->priv = popup->priv; - } - - subsurface->parent = subsurfaces; - subsurface->wlr_subsurface = wlr_subsurface; - - subsurfaces->list = g_list_append (subsurfaces->list, subsurface); - - subsurface->commit.notify = xdg_subsurface_commit; - wl_signal_add (&wlr_subsurface->surface->events.commit, &subsurface->commit); - - subsurface->destroy.notify = xdg_subsurface_destroy; - wl_signal_add (&wlr_subsurface->events.destroy, &subsurface->destroy); -} - - -static void -compositor_subsurfaces_init (CasildaCompositorSurfaces *subsurfaces, struct wlr_surface *surface) -{ - subsurfaces->new_subsurface.notify = xdg_subsurface_new_subsurface; - wl_signal_add (&surface->events.new_subsurface, &subsurfaces->new_subsurface); -} - -static void -compositor_subsurfaces_fini (CasildaCompositorSurfaces *subsurfaces) -{ - wl_list_remove (&subsurfaces->new_subsurface.link); -} - -static void -xdg_toplevel_destroy (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorToplevel *toplevel = wl_container_of (listener, toplevel, destroy); - - casilda_compositor_cursor_handler_remove(toplevel->priv); - - wl_list_remove (&toplevel->map.link); - wl_list_remove (&toplevel->unmap.link); - wl_list_remove (&toplevel->commit.link); - wl_list_remove (&toplevel->destroy.link); - wl_list_remove (&toplevel->request_move.link); - wl_list_remove (&toplevel->request_resize.link); - wl_list_remove (&toplevel->request_maximize.link); - wl_list_remove (&toplevel->request_fullscreen.link); - wl_list_remove (&toplevel->set_app_id.link); - - compositor_subsurfaces_fini (&toplevel->subsurfaces); - - /* FIXME: need to do something if these are not empty */ - g_list_free (toplevel->toplevels); - g_list_free (toplevel->popups); - - /* Unref texture */ - g_clear_object (&toplevel->xdg_toplevel->base->surface->data); - - g_free (toplevel); -} - -static gboolean -casilda_compositor_toplevel_has_focus (CasildaCompositorToplevel *toplevel) -{ - CasildaCompositorPrivate *priv = toplevel->priv; - struct wlr_surface *focused_surface = priv->seat->pointer_state.focused_surface; - - if (focused_surface) - return toplevel->xdg_toplevel->base->surface == wlr_surface_get_root_surface (focused_surface); - - return FALSE; -} - -static void -xdg_toplevel_request_move (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorToplevel *toplevel = wl_container_of (listener, toplevel, request_move); - CasildaCompositorPrivate *priv = toplevel->priv; - - if (!casilda_compositor_toplevel_has_focus (toplevel)) - return; - - priv->grabbed_toplevel = toplevel; - priv->pointer_mode = CASILDA_POINTER_MODE_MOVE; - priv->grab_x = priv->pointer_x - toplevel->x; - priv->grab_y = priv->pointer_y - toplevel->y; -} - -static void -xdg_toplevel_request_resize (struct wl_listener *listener, void *data) -{ - CasildaCompositorToplevel *toplevel = wl_container_of (listener, toplevel, request_resize); - CasildaCompositorPrivate *priv = toplevel->priv; - struct wlr_xdg_toplevel_resize_event *event = data; - struct wlr_box box; - double border_x, border_y; - - if (!casilda_compositor_toplevel_has_focus (toplevel)) - return; - - priv->grabbed_toplevel = toplevel; - priv->pointer_mode = CASILDA_POINTER_MODE_RESIZE; - priv->resize_edges = event->edges; - - box = toplevel->xdg_toplevel->base->geometry; - - border_x = toplevel->x + box.x + - ((event->edges & WLR_EDGE_RIGHT) ? box.width : 0); - border_y = toplevel->y + box.y + - ((event->edges & WLR_EDGE_BOTTOM) ? box.height : 0); - priv->grab_x = priv->pointer_x - border_x; - priv->grab_y = priv->pointer_y - border_y; - - priv->grab_box = box; - priv->grab_box.x += toplevel->x; - priv->grab_box.y += toplevel->y; -} - -static void -xdg_toplevel_request_maximize (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorToplevel *toplevel = - wl_container_of (listener, toplevel, request_maximize); - - casilda_compositor_toplevel_toggle_maximize_fullscreen (toplevel, FALSE); -} - -static void -xdg_toplevel_request_fullscreen (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorToplevel *toplevel = - wl_container_of (listener, toplevel, request_fullscreen); - - casilda_compositor_toplevel_toggle_maximize_fullscreen (toplevel, TRUE); -} - -static void -xdg_toplevel_set_app_id (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorToplevel *toplevel = wl_container_of (listener, toplevel, set_app_id); - const gchar *app_id = toplevel->xdg_toplevel->app_id; - - /* - * NOTE: set_app_id is not supported - * Instead it is used as a window unique id to keep track of windows state - * Ideally this should be implemented with a session extension. - */ - if (!g_str_has_prefix (app_id, "Casilda:")) - return; - - toplevel->state = g_hash_table_lookup (toplevel->priv->toplevel_state, app_id); - - if (!toplevel->state) - { - /* Allocate new state struct */ - toplevel->state = g_new0 (CasildaCompositorToplevelState, 1); - - /* Start new windows in the top left corner */ - toplevel->state->x = 32; - toplevel->state->y = 32; - - /* Insert it in out server hash table */ - g_hash_table_insert (toplevel->priv->toplevel_state, - g_strdup (app_id), - toplevel->state); - } - - g_debug ("%s %s %dx%d %dx%d", - __func__, - toplevel->xdg_toplevel->app_id, - toplevel->state->x, - toplevel->state->y, - toplevel->state->width, - toplevel->state->height); -} - -static void -server_new_xdg_toplevel (struct wl_listener *listener, void *data) -{ - CasildaCompositorPrivate *priv = wl_container_of (listener, priv, new_xdg_toplevel); - struct wlr_xdg_toplevel *xdg_toplevel = data; - CasildaCompositorToplevel *toplevel; - - toplevel = g_new0 (CasildaCompositorToplevel, 1); - toplevel->priv = priv; - toplevel->xdg_toplevel = xdg_toplevel; - - /* Back Reference */ - toplevel->xdg_toplevel->base->data = toplevel; - - toplevel->map.notify = xdg_toplevel_map; - wl_signal_add (&xdg_toplevel->base->surface->events.map, &toplevel->map); - toplevel->unmap.notify = xdg_toplevel_unmap; - wl_signal_add (&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap); - toplevel->commit.notify = xdg_toplevel_commit; - wl_signal_add (&xdg_toplevel->base->surface->events.commit, &toplevel->commit); - - compositor_subsurfaces_init (&toplevel->subsurfaces, xdg_toplevel->base->surface); - - toplevel->destroy.notify = xdg_toplevel_destroy; - wl_signal_add (&xdg_toplevel->events.destroy, &toplevel->destroy); - - toplevel->request_move.notify = xdg_toplevel_request_move; - wl_signal_add (&xdg_toplevel->events.request_move, &toplevel->request_move); - toplevel->request_resize.notify = xdg_toplevel_request_resize; - wl_signal_add (&xdg_toplevel->events.request_resize, &toplevel->request_resize); - toplevel->request_maximize.notify = xdg_toplevel_request_maximize; - wl_signal_add (&xdg_toplevel->events.request_maximize, &toplevel->request_maximize); - toplevel->request_fullscreen.notify = xdg_toplevel_request_fullscreen; - wl_signal_add (&xdg_toplevel->events.request_fullscreen, &toplevel->request_fullscreen); - - toplevel->set_app_id.notify = xdg_toplevel_set_app_id; - wl_signal_add (&xdg_toplevel->events.set_app_id, &toplevel->set_app_id); -} - -static void -xdg_popup_commit (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorPopup *popup = wl_container_of (listener, popup, commit); - - if (popup->xdg_popup->base->initial_commit) - wlr_xdg_surface_schedule_configure (popup->xdg_popup->base); - - casilda_compositor_queue_draw (popup->priv); -} - -static void -xdg_popup_destroy (struct wl_listener *listener, G_GNUC_UNUSED void *data) -{ - CasildaCompositorPopup *popup = wl_container_of (listener, popup, destroy); - - if (popup->toplevel) - popup->toplevel->popups = g_list_remove (popup->toplevel->popups, popup); - - if (popup->parent) - popup->parent->popups = g_list_remove (popup->parent->popups, popup); - - wl_list_remove (&popup->commit.link); - wl_list_remove (&popup->destroy.link); - - compositor_subsurfaces_fini (&popup->subsurfaces); - - g_list_free (popup->popups); - - /* Clear texture */ - g_clear_object (&popup->xdg_popup->base->surface->data); - - g_free (popup); -} - -static void -server_new_xdg_popup (G_GNUC_UNUSED struct wl_listener *listener, void *data) -{ - CasildaCompositorPrivate *priv = wl_container_of (listener, priv, new_xdg_popup); - struct wlr_xdg_toplevel *parent_xdg_toplevel; - struct wlr_xdg_popup *xdg_popup = data; - struct wlr_xdg_surface *parent; - CasildaCompositorPopup *popup; - - if(!(parent = wlr_xdg_surface_try_from_wlr_surface (xdg_popup->parent))) - return; - - popup = g_new0 (CasildaCompositorPopup, 1); - popup->priv = priv; - popup->xdg_popup = xdg_popup; - - /* Back Reference */ - popup->xdg_popup->base->data = popup; - - /* We do not know if parent wlr_xdg_surface is from a toplevel or popup */ - if ((parent_xdg_toplevel = wlr_xdg_toplevel_try_from_wlr_surface (parent->surface))) - { - CasildaCompositorToplevel *toplevel = parent_xdg_toplevel->base->data; - popup->toplevel = toplevel; - toplevel->popups = g_list_prepend (toplevel->popups, popup); - } - else { - struct wlr_xdg_popup *parent_xdg_popup = wlr_xdg_popup_try_from_wlr_surface(parent->surface); - - if (parent_xdg_popup) - { - CasildaCompositorPopup *parent_popup = parent_xdg_popup->base->data; - popup->parent = parent_popup; - parent_popup->popups = g_list_prepend (parent_popup->popups, popup); - } - } - - popup->commit.notify = xdg_popup_commit; - wl_signal_add (&xdg_popup->base->surface->events.commit, &popup->commit); - - popup->destroy.notify = xdg_popup_destroy; - wl_signal_add (&xdg_popup->events.destroy, &popup->destroy); - - compositor_subsurfaces_init (&popup->subsurfaces, xdg_popup->base->surface); - - casilda_compositor_queue_draw (popup->priv); -} - -static void -server_request_activate (struct wl_listener *listener, void *data) -{ - CasildaCompositorPrivate *priv = wl_container_of (listener, priv, request_activate); - struct wlr_xdg_activation_v1_request_activate_event *event = data; - struct wlr_xdg_toplevel *xdg_toplevel = - wlr_xdg_toplevel_try_from_wlr_surface (event->surface); - - if (!xdg_toplevel) - return; - - for (GList *l = priv->toplevels; l; l = g_list_next (l)) - { - CasildaCompositorToplevel *toplevel = l->data; - - if (toplevel->xdg_toplevel != xdg_toplevel) - continue; - - casilda_compositor_focus_toplevel (toplevel, xdg_toplevel->base->surface); - } -} - -#if ENABLE_GL_DEBUG -static void GLAPIENTRY -on_gl_message_callback (G_GNUC_UNUSED GLenum source, - GLenum type, - G_GNUC_UNUSED GLuint id, - GLenum severity, - G_GNUC_UNUSED GLsizei length, - const GLchar* message, - G_GNUC_UNUSED const void* userParam) -{ - if (type == GL_DEBUG_TYPE_ERROR) - g_warning ("GL: type = 0x%x, severity = 0x%x, message = %s\n", type, severity, message); - else - g_message ("GL: type = 0x%x, severity = 0x%x, message = %s\n", type, severity, message); -} -#endif - -static struct wlr_renderer * -create_gles_renderer (CasildaCompositorPrivate *priv) -{ - g_autoptr(GError) error = NULL; - EGLDisplay *egl_display = NULL; - GdkDisplay *g_display = gdk_display_get_default (); - -#ifdef GDK_WINDOWING_WAYLAND - if (GDK_IS_WAYLAND_DISPLAY (g_display)) - { - egl_display = gdk_wayland_display_get_egl_display (g_display); - - if (egl_display == NULL) - { - g_warning ("failed to get Wayland EGL display"); - return NULL; - } - } -#endif - -#if defined(GDK_WINDOWING_X11) && defined(HAVE_X11_XCB) - if (GDK_IS_X11_DISPLAY (g_display)) - { -G_GNUC_BEGIN_IGNORE_DEPRECATIONS - egl_display = eglGetDisplay ((EGLNativeDisplayType) gdk_x11_display_get_xdisplay (g_display)); -G_GNUC_END_IGNORE_DEPRECATIONS - if (egl_display == NULL) - { - g_warning ("failed to get X11 EGL display"); - return NULL; - } - } -#endif - - if (egl_display == NULL) - return NULL; - - priv->gl_context = gdk_display_create_gl_context (g_display, &error); - if (error != NULL) - { - g_warning ("Failed to create GL context: %s", error->message); - return NULL; - } - g_object_ref_sink(priv->gl_context); - - /* Add DMABUF capability */ - priv->backend.buffer_caps |= WLR_BUFFER_CAP_DMABUF; - - gdk_gl_context_set_allowed_apis (priv->gl_context, GDK_GL_API_GLES); - if (!gdk_gl_context_realize (priv->gl_context, &error)) - { - g_warning ("Failed to realize GL context"); - if (error != NULL) - g_warning ("GL context error: %s", error->message); - return NULL; - } - - gdk_gl_context_make_current (priv->gl_context); - EGLContext *egl_context = eglGetCurrentContext(); - if (egl_context == NULL) - { - g_warning ("Failed to get current EGL context"); - return NULL; - } - - struct wlr_egl *egl = wlr_egl_create_with_context (egl_display, egl_context); - if (egl == NULL) - { - g_warning ("Failed to create wlr_egl object"); - return NULL; - } - -#if ENABLE_GL_DEBUG - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(on_gl_message_callback, 0); -#endif - - return wlr_gles2_renderer_create (egl); -} - -static void -casilda_compositor_wlr_init (CasildaCompositorPrivate *priv) -{ - priv->wl_display = wl_display_create (); - - if (g_getenv("CASILDA_FORCE_SOFTWARE") == NULL) - priv->renderer = create_gles_renderer(priv); - - if (priv->renderer == NULL) - { - g_warning ("failed to create GLES renderer, using pixman"); - priv->renderer = wlr_pixman_renderer_create (); - } - - if (priv->renderer == NULL) - { - g_error ("failed to create pixman renderer"); - return; - } - - wlr_renderer_init_wl_display (priv->renderer, priv->wl_display); - - priv->allocator = wlr_allocator_autocreate (&priv->backend, priv->renderer); - if (priv->allocator == NULL) - { - g_warning ("failed to create wlr_allocator"); - return; - } - - wlr_compositor_create (priv->wl_display, 6, priv->renderer); - wlr_subcompositor_create (priv->wl_display); - wlr_data_device_manager_create (priv->wl_display); - - wlr_fractional_scale_manager_v1_create (priv->wl_display, 1); - - /* Set up xdg-shell version 3 */ - priv->xdg_shell = wlr_xdg_shell_create (priv->wl_display, 3); - priv->new_xdg_toplevel.notify = server_new_xdg_toplevel; - wl_signal_add (&priv->xdg_shell->events.new_toplevel, &priv->new_xdg_toplevel); - priv->new_xdg_popup.notify = server_new_xdg_popup; - wl_signal_add (&priv->xdg_shell->events.new_popup, &priv->new_xdg_popup); - - /* Set up xdg-activation */ - priv->xdg_activation = wlr_xdg_activation_v1_create (priv->wl_display); - priv->request_activate.notify = server_request_activate; - wl_signal_add (&priv->xdg_activation->events.request_activate, &priv->request_activate); - - /* Configure seat */ - priv->seat = wlr_seat_create (priv->wl_display, "seat0"); - priv->request_set_selection.notify = seat_request_set_selection; - wl_signal_add (&priv->seat->events.request_set_selection, &priv->request_set_selection); - - wlr_seat_set_capabilities (priv->seat, WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD); - - if (!priv->socket) - return; - - if (wl_display_add_socket (priv->wl_display, priv->socket)) - g_warning ("Error adding socket file %s", priv->socket); - else - g_info ("Listening on %s", priv->socket); -} - - -/* Public API */ - -/** - * casilda_compositor_new: - * @socket: the named socket to use or NULL - * - * Create a new `CasildaCompositor` widget using @socket as the name of the Wayland socket. - * Clients can connect to the compositor by setting WAYLAND_DISPLAY=@socket - * - * Returns: a new `CasildaCompositor` widget - */ -CasildaCompositor * -casilda_compositor_new (const gchar *socket) -{ - return g_object_new (CASILDA_COMPOSITOR_TYPE, "socket", socket, NULL); -} - - -/** - * casilda_compositor_get_client_socket_fd: - * @compositor: a `CasildaCompositor` - * - * Create a client socket file descriptor connected to this compositor ready to use by passing it to a client with - * WAYLAND_SOCKET environment variable. - * Once the returned FD is passed to the client it must be closed on the parent otherwise the client windows - * wont get destroyed if the client looses the connection to the server. - * - * Returns: a socket FD connected to the compositor - */ -int -casilda_compositor_get_client_socket_fd (CasildaCompositor *compositor) -{ - g_return_val_if_fail (CASILDA_IS_COMPOSITOR (compositor), -1); - - CasildaCompositorPrivate *priv = GET_PRIVATE (compositor); - gint fds[2] = {0, }; - - if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds)) - { - g_warning ("Could not create a UNIX socketpair"); - return -1; - } - - if (!wl_client_create (priv->wl_display, fds[0])) - { - g_warning ("Could not add socketpair to display"); - return -1; - } - - return fds[1]; -} - - -/** - * casilda_compositor_spawn_async: - * @compositor: a `CasildaCompositor` - * @working_directory: (type filename) (nullable): child's current working directory, or %NULL to inherit parent's - * @argv: (array zero-terminated=1) (element-type filename): child's argument vector - * @envp: (array zero-terminated=1) (element-type filename) (nullable): child's environment, or %NULL to inherit parent's - * @flags: flags from #GSpawnFlags - * @child_setup: (scope async) (closure user_data) (nullable): function to run in the child just before `exec()` - * @user_data: user data for @child_setup - * @child_pid: (out) (optional): return location for child process reference, or %NULL - * @error: return location for error - * - * Executes a child program asynchronously with the right environment to automatically connect to this compositor. - * - * See [func@GLib.spawn_async_with_pipes_and_fds] for a full description; this function simply calls - * [func@GLib.spawn_async_with_pipes_and_fds] without any pipes and with WAYLAND_DISPLAY set to `CasildaCompositor::socket` or - * a fd already connected to the compositor and set to WAYLAND_SOCKET if its NULL. - * - * Please note GDK_BACKEND, WAYLAND_DISPLAY and WAYLAND_SOCKET are set by this function they are ignored from %envp and - * DISPLAY is removed to avoid clients try to connect using X11 - * - * Returns: TRUE on success, FALSE if error is set. - */ -gboolean -casilda_compositor_spawn_async (CasildaCompositor *compositor, - const gchar *working_directory, - gchar **argv, - gchar **envp, - GSpawnFlags flags, - GSpawnChildSetupFunc child_setup, - gpointer user_data, - GPid *child_pid, - GError **error) -{ - g_return_val_if_fail (CASILDA_IS_COMPOSITOR (compositor), FALSE); - - CasildaCompositorPrivate *priv = GET_PRIVATE (compositor); - g_autoptr(GStrvBuilder) builder = g_strv_builder_new (); - g_autofree gchar *wayland_socket = NULL; - g_auto(GStrv) environ = NULL; - GStrv source_env = NULL; - gboolean retval; - gint fd = -1; - - if (envp) - source_env = envp; - else - source_env = environ = g_get_environ(); - - /* Build environment */ - for (gint i = 0; source_env[i]; i++) - { - if (g_str_has_prefix (source_env[i], "DISPLAY=")) - continue; - if (g_str_has_prefix (source_env[i], "GDK_BACKEND=")) - continue; - if (g_str_has_prefix (source_env[i], "WAYLAND_DISPLAY=")) - continue; - if (g_str_has_prefix (source_env[i], "WAYLAND_SOCKET=")) - continue; - - g_strv_builder_add (builder, source_env[i]); - } - - /* Force GTK apps to wayland backend */ - g_strv_builder_add (builder, "GDK_BACKEND=wayland"); - - if (priv->socket) - wayland_socket = g_strdup_printf("WAYLAND_DISPLAY=%s", priv->socket); - else - { - fd = casilda_compositor_get_client_socket_fd (compositor); - wayland_socket = g_strdup_printf("WAYLAND_SOCKET=%d", fd); - } - - /* Add wayland socket env var */ - g_strv_builder_add (builder, wayland_socket); - - g_auto(GStrv) env = g_strv_builder_end (builder); - - retval = g_spawn_async_with_pipes_and_fds (working_directory, - (const gchar* const* ) argv, - (const gchar* const* ) env, - flags, - child_setup, - user_data, - -1, -1, -1, - &fd, &fd, fd > 0 ? 1 : 0, - child_pid, - NULL, NULL, NULL, - error); - - /* Close file descriptor after its being passed to the client */ - if (fd > 0) - close (fd); - - return retval; -} - diff --git a/vendor/casilda/src/casilda-compositor.h b/vendor/casilda/src/casilda-compositor.h deleted file mode 100644 index bb6b364..0000000 --- a/vendor/casilda/src/casilda-compositor.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Casilda Wayland Compositor Widget - * - * Copyright (C) 2024 Juan Pablo Ugarte - * - * 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; - * version 2.1 of the License. - * - * 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. - * - * 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 - * - * Authors: - * Juan Pablo Ugarte - * - * SPDX-License-Identifier: LGPL-2.1-only - */ - -#pragma once - -#include - -#define CASILDA_COMPOSITOR_TYPE (casilda_compositor_get_type ()) -G_DECLARE_FINAL_TYPE (CasildaCompositor, casilda_compositor, CASILDA, COMPOSITOR, GtkWidget) - -CasildaCompositor *casilda_compositor_new (const gchar *socket); - -int casilda_compositor_get_client_socket_fd (CasildaCompositor *compositor); - -gboolean casilda_compositor_spawn_async (CasildaCompositor *compositor, - const gchar *working_directory, - gchar **argv, - gchar **envp, - GSpawnFlags flags, - GSpawnChildSetupFunc child_setup, - gpointer user_data, - GPid *child_pid, - GError **error); - -void casilda_compositor_set_scrollable (CasildaCompositor *compositor, - gboolean scrollable); - -void casilda_compositor_set_maximized (CasildaCompositor *compositor, - gboolean maximized); diff --git a/vendor/casilda/src/casilda-version.h.in b/vendor/casilda/src/casilda-version.h.in deleted file mode 100644 index 6b16782..0000000 --- a/vendor/casilda/src/casilda-version.h.in +++ /dev/null @@ -1,97 +0,0 @@ -/* casilda-version.h.in - * - * Copyright 2024 Juan Pablo Ugarte - * - * 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. - * - * 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. - * - * 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 - * - * SPDX-License-Identifier: LGPL-2.1-only - */ - -#pragma once - -#if !defined(CASILDA_INSIDE) && !defined(CASILDA_COMPILATION) -# error "Only can be included directly." -#endif - -/** - * SECTION:casildaversion - * @short_description: casilda version checking - * - * casilda provides macros to check the version of the library - * at compile-time - */ - -/** - * CASILDA_MAJOR_VERSION: - * - * casilda major version component (e.g. 1 if %CASILDA_VERSION is 1.2.3) - */ -#define CASILDA_MAJOR_VERSION (@MAJOR_VERSION@) - -/** - * CASILDA_MINOR_VERSION: - * - * casilda minor version component (e.g. 2 if %CASILDA_VERSION is 1.2.3) - */ -#define CASILDA_MINOR_VERSION (@MINOR_VERSION@) - -/** - * CASILDA_MICRO_VERSION: - * - * casilda micro version component (e.g. 3 if %CASILDA_VERSION is 1.2.3) - */ -#define CASILDA_MICRO_VERSION (@MICRO_VERSION@) - -/** - * CASILDA_VERSION - * - * casilda version. - */ -#define CASILDA_VERSION (@VERSION@) - -/** - * CASILDA_VERSION_S: - * - * casilda version, encoded as a string, useful for printing and - * concatenation. - */ -#define CASILDA_VERSION_S "@VERSION@" - -#define CASILDA_ENCODE_VERSION(major,minor,micro) \ - ((major) << 24 | (minor) << 16 | (micro) << 8) - -/** - * CASILDA_VERSION_HEX: - * - * casilda version, encoded as an hexadecimal number, useful for - * integer comparisons. - */ -#define CASILDA_VERSION_HEX \ - (CASILDA_ENCODE_VERSION (CASILDA_MAJOR_VERSION, CASILDA_MINOR_VERSION, CASILDA_MICRO_VERSION)) - -/** - * CASILDA_CHECK_VERSION: - * @major: required major version - * @minor: required minor version - * @micro: required micro version - * - * Compile-time version checking. Evaluates to %TRUE if the version - * of casilda is greater than the required one. - */ -#define CASILDA_CHECK_VERSION(major,minor,micro) \ - (CASILDA_MAJOR_VERSION > (major) || \ - (CASILDA_MAJOR_VERSION == (major) && CASILDA_MINOR_VERSION > (minor)) || \ - (CASILDA_MAJOR_VERSION == (major) && CASILDA_MINOR_VERSION == (minor) && \ - CASILDA_MICRO_VERSION >= (micro))) diff --git a/vendor/casilda/src/casilda-wayland-source.c b/vendor/casilda/src/casilda-wayland-source.c deleted file mode 100644 index d940b48..0000000 --- a/vendor/casilda/src/casilda-wayland-source.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * casilda_headers Wayland GLib Integration - * - * Copyright (C) 2024 Juan Pablo Ugarte - * - * 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; - * version 2.1 of the License. - * - * 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. - * - * 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 - * - * Authors: - * Juan Pablo Ugarte - * - * SPDX-License-Identifier: LGPL-2.1-only - */ - -#include "casilda-wayland-source.h" - -typedef struct -{ - GSource source; - struct wl_display *display; -} CasildaWaylandSource; - -#define CASILDA_WAYLAND_SOURCE(s) ((CasildaWaylandSource *) s) - -static gboolean -casilda_wayland_source_prepare (GSource *base, int *timeout) -{ - CasildaWaylandSource *source = CASILDA_WAYLAND_SOURCE (base); - - *timeout = -1; - - wl_display_flush_clients (source->display); - - return FALSE; -} - -static gboolean -casilda_wayland_source_check (GSource *base) -{ - CasildaWaylandSource *source = CASILDA_WAYLAND_SOURCE (base); - struct wl_event_loop *loop = wl_display_get_event_loop (source->display); - - /* Since there is no way to know if there are idle source, dispatch them! */ - wl_event_loop_dispatch_idle (loop); - - return FALSE; -} - - -static gboolean -casilda_wayland_source_dispatch (GSource *base, - G_GNUC_UNUSED GSourceFunc callback, - G_GNUC_UNUSED void *data) -{ - CasildaWaylandSource *source = CASILDA_WAYLAND_SOURCE (base); - struct wl_event_loop *loop = wl_display_get_event_loop (source->display); - - wl_event_loop_dispatch (loop, 0); - - return TRUE; -} - - -static GSourceFuncs casilda_wayland_source_funcs = { - .prepare = casilda_wayland_source_prepare, - .check = casilda_wayland_source_check, - .dispatch = casilda_wayland_source_dispatch, -}; - - -GSource * -casilda_wayland_source_new (struct wl_display *display) -{ - struct wl_event_loop *loop = wl_display_get_event_loop (display); - GSource *source = g_source_new (&casilda_wayland_source_funcs, - sizeof (CasildaWaylandSource)); - - CASILDA_WAYLAND_SOURCE (source)->display = display; - - g_source_add_unix_fd (source, - wl_event_loop_get_fd (loop), - G_IO_IN | G_IO_ERR); - - return source; -} diff --git a/vendor/casilda/src/casilda-wayland-source.h b/vendor/casilda/src/casilda-wayland-source.h deleted file mode 100644 index d633f19..0000000 --- a/vendor/casilda/src/casilda-wayland-source.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Casilda Wayland GLib Integration - * - * Copyright (C) 2024 Juan Pablo Ugarte - * - * 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; - * version 2.1 of the License. - * - * 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. - * - * 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 - * - * Authors: - * Juan Pablo Ugarte - * - * SPDX-License-Identifier: LGPL-2.1-only - */ - -#pragma once - -#include -#include - -GSource *casilda_wayland_source_new (struct wl_display *display); diff --git a/vendor/casilda/src/casilda.h b/vendor/casilda/src/casilda.h deleted file mode 100644 index f2125a1..0000000 --- a/vendor/casilda/src/casilda.h +++ /dev/null @@ -1,34 +0,0 @@ -/* casilda.h - * - * Copyright 2024 Juan Pablo Ugarte - * - * 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. - * - * 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. - * - * 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 - * - * SPDX-License-Identifier: LGPL-2.1-only - */ - -#pragma once - -#include - -G_BEGIN_DECLS - -#define CASILDA_INSIDE -# include "casilda-version.h" -#undef CASILDA_INSIDE - -#include "casilda-compositor.h" - -G_END_DECLS diff --git a/vendor/casilda/src/meson.build b/vendor/casilda/src/meson.build deleted file mode 100644 index 0b7a134..0000000 --- a/vendor/casilda/src/meson.build +++ /dev/null @@ -1,125 +0,0 @@ -api_version = '1.0' - -casilda_sources = [ - 'casilda-compositor.c', - 'casilda-wayland-source.c', -] - -casilda_headers = [ - 'casilda.h', - 'casilda-compositor.h', -] - -version_conf = configuration_data() -version_conf.set('VERSION', meson.project_version()) -version_conf.set('MAJOR_VERSION', version_split[0]) -version_conf.set('MINOR_VERSION', version_split[1]) -version_conf.set('MICRO_VERSION', version_split[2]) - -casilda_headers += configure_file( - input: 'casilda-version.h.in', - output: 'casilda-version.h', - configuration: version_conf, - install: true, - install_dir: get_option('includedir') / 'casilda', -) - -wayland_scanner = find_program( - wayland_scanner_dep.get_variable('wayland_scanner'), - native: true, -) - -casilda_deps = [ - gtk4_dep, - wlroots_dep, - xkbcommon, - wayland_server_dep, - epoxy_dep, - wayland_server_dep, - pixman_dep -] - -wl_protocols_dir = wayland_protocols_deps.get_variable('pkgdatadir') -wl_stable_protocols_dir = wl_protocols_dir / 'stable' / 'xdg-shell' - -generated_protocols = [ - 'xdg-shell', -] - -wayland_protocol_sources = [] - -foreach proto_name: generated_protocols - base_file = proto_name - xml_path = '@0@.xml'.format(proto_name) - - foreach output_type: [ 'private-code', 'server-header' ] - wayland_protocol_sources += custom_target( - '@0@_@1@'.format(base_file, output_type), - command: [ wayland_scanner, output_type, '@INPUT@', '@OUTPUT@' ], - input: wl_stable_protocols_dir / 'xdg-shell' + '.xml', - output: base_file + '-protocol.' + ('header' in output_type ? 'h' : 'c'), - ) - endforeach -endforeach - -lib_c_args = [] -if xkbcommon_x11_dep.found() and x11_xcb_dep.found() - casilda_deps += [xkbcommon_x11_dep, x11_xcb_dep] - lib_c_args += ['-DHAVE_X11_XCB=1'] -endif - -# Remove soversion once Meson is updated to support this automatically -# https://mesonbuild.com/Reference-manual_functions.html#shared_library_version -casilda_lib = shared_library('casilda-' + api_version, - sources: [ - casilda_sources, - wayland_protocol_sources, - ], - version: api_version, - soversion: api_version.split('.')[0], - dependencies: casilda_deps, - c_args: lib_c_args, - link_args : '-lm', - install: true, -) - -casilda_dep = declare_dependency( - include_directories: include_directories('.'), - link_with: casilda_lib, - dependencies: gtk4_dep, -) - -install_headers(casilda_headers, subdir: 'casilda') - -pkg.generate( - description: 'A simple Gtk wayland compositor widget', - libraries: casilda_lib, - name: 'casilda', - filebase: 'casilda-' + api_version, - version: meson.project_version(), - subdirs: 'casilda', - requires: [ gtk4_dep ], - requires_private: [ wlroots_dep ], - install_dir: get_option('libdir') / 'pkgconfig' -) - -casilda_gir = gnome.generate_gir(casilda_lib, - sources: [casilda_headers, casilda_sources], - nsversion: api_version, - namespace: 'Casilda', - symbol_prefix: 'casilda', - identifier_prefix: 'Casilda', - includes: [ 'Gtk-4.0' ], - install: true, - extra_args: [ '--c-include=casilda.h' ] -) - -if get_option('vapi') - casilda_vapi = gnome.generate_vapi('casilda-' + api_version, - sources: casilda_gir[0], - install: true, - packages: [ 'gtk4' ], - install_dir: get_option('datadir') / 'vala' / 'vapi', - metadata_dirs: [ meson.current_source_dir() ] - ) -endif