pax_global_header00006660000000000000000000000064142230425370014514gustar00rootroot0000000000000052 comment=2faa98d85f1142383ec8ad1487616c1a7ad1882f squeekboard-v1.17.1/000077500000000000000000000000001422304253700142765ustar00rootroot00000000000000squeekboard-v1.17.1/.dir-locals.el000066400000000000000000000001011422304253700167170ustar00rootroot00000000000000((c-mode . ((c-basic-offset . 4) (indent-tabs-mode . nil))))squeekboard-v1.17.1/.gitignore000066400000000000000000000001061422304253700162630ustar00rootroot00000000000000_build po/squeekboard.pot po/*.mo TAGS tags vgdump *.swp *~ \#*# .\#* squeekboard-v1.17.1/.gitlab-ci.yml000066400000000000000000000056111422304253700167350ustar00rootroot00000000000000image: pureos/byzantium stages: - build - test before_script: - apt-get -y update - apt-get -y install ca-certificates build_docs: stage: build artifacts: paths: - _build script: - apt-get -y install python3-pip python3-sphinx - pip3 install recommonmark - ./doc/build.sh _build except: variables: - $PKG_ONLY == "1" build_meson: stage: build artifacts: paths: - _build expire_in: 3h script: - apt-get -y build-dep . - meson . _build/ -Ddepdatadir=/usr/share --werror - ninja -C _build install except: variables: - $PKG_ONLY == "1" build_deb: stage: build artifacts: paths: - '*.deb' script: - rm -f ../*.deb - apt-get -y build-dep . - apt-get -y install devscripts - REV=$(git log -1 --format=%h) - VER=$(dpkg-parsechangelog -SVersion) - DEBFULLNAME="Librem5 CI" - EMAIL="librem5-builds@lists.community.puri.sm" - dch -v"$VER+librem5ci$CI_PIPELINE_ID.$REV" "$MSG" - debuild -i -us -uc -b - cp ../*.deb . build_deb:arm64: image: pureos/byzantium tags: - aarch64 stage: build artifacts: paths: - '*.deb' script: - rm -f ../*.deb - apt-get -y build-dep . - apt-get -y install devscripts - REV=$(git log -1 --format=%h) - VER=$(dpkg-parsechangelog -SVersion) - DEBFULLNAME="Librem5 CI" - EMAIL="librem5-builds@lists.community.puri.sm" - dch -v"$VER+librem5ci$CI_PIPELINE_ID.$REV" "$MSG" - debuild -i -us -uc -b - cp ../*.deb . build_deb:future: image: debian:sid allow_failure: true tags: - aarch64 stage: build artifacts: paths: - '*.deb' script: - rm -f ../*.deb - mv debian/control-newer debian/control - apt-get -y build-dep . - apt-get -y install devscripts - REV=$(git log -1 --format=%h) - VER=$(dpkg-parsechangelog -SVersion) - DEBFULLNAME="Librem5 CI" - EMAIL="librem5-builds@lists.community.puri.sm" - dch -v"$VER+librem5ci$CI_PIPELINE_ID.$REV" "$MSG" - debuild -i -us -uc -b - cp ../*.deb . test_lintian: stage: test needs: - job: build_deb artifacts: true script: - apt-get -y install lintian - lintian *.deb except: variables: - $PKG_ONLY == "1" test: stage: test needs: - job: build_meson artifacts: true script: - apt-get -y build-dep . - apt-get -y install clang-tidy - ninja -C _build test - tools/style-check_build _build except: variables: - $PKG_ONLY == "1" test_style: stage: test needs: [] script: - apt-get -y build-dep . - tools/style-check_source except: variables: - $PKG_ONLY == "1" check_release: stage: test needs: [] only: refs: - master script: - apt-get -y install git python3 - (head -n 1 ./debian/changelog && git tag) | ./debian/check_release.py except: variables: - $PKG_ONLY == "1" squeekboard-v1.17.1/AUTHORS000066400000000000000000000003171422304253700153470ustar00rootroot00000000000000squeekboard is written by Dorota Czaplejewicz on behlf of Purism, SPC. eekboard was written by Daiki Ueno For more details, see the debian/copyright file. squeekboard-v1.17.1/COPYING000066400000000000000000001045131422304253700153350ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state 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 program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . squeekboard-v1.17.1/Cargo.deps000066400000000000000000000010451422304253700162060ustar00rootroot00000000000000# Dependencies which change based on build flags bitflags = "1.2.*" clap = { version = "2.33.*", default-features = false } [dependencies.cairo-rs] version = "0.7.*" [dependencies.cairo-sys-rs] version = "0.9" [dependencies.gdk] version = "0.11.*" [dependencies.gio] version = "0.7.*" features = ["v2_44"] [dependencies.glib] version = "0.8.*" features = ["v2_44"] [dependencies.glib-sys] version = "*" features = ["v2_44"] [dependencies.gtk] version = "0.7.*" features = ["v3_22"] [dependencies.gtk-sys] version = "0.9" features = ["v3_22"]squeekboard-v1.17.1/Cargo.deps.newer000066400000000000000000000011331422304253700173230ustar00rootroot00000000000000# Dependencies which change based on build flags # For the newer-than-Byzantium config bitflags = "1.3.*" clap = { version = "2.33.*", default-features = false } [dependencies.cairo-rs] version = "0.14.*" [dependencies.cairo-sys-rs] version = "0.14.*" [dependencies.gdk] version = "0.14.*" [dependencies.gio] version = "0.14.*" features = ["v2_58"] [dependencies.glib] version = "0.14.*" features = ["v2_58"] [dependencies.glib-sys] version = "0.14.*" features = ["v2_58"] [dependencies.gtk] version = "0.14.*" features = ["v3_22"] [dependencies.gtk-sys] version = "0.14.*" features = ["v3_22"] squeekboard-v1.17.1/Cargo.deps.online000066400000000000000000000003361422304253700174730ustar00rootroot00000000000000# Dependencies which are only used with online, crates.io builds. [patch.crates-io] # Dependency was yanked, but gio 0.7 needs it. fragile = { git = "https://source.puri.sm/dorota.czaplejewicz/fragile.git", tag = "0.3.0" }squeekboard-v1.17.1/Cargo.lock000066400000000000000000000262041422304253700162070ustar00rootroot00000000000000# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "atk" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b7499272acf036bb5820c6e346bbfb5acc5dceb104bc2c4fd7e6e33dfcde6a" dependencies = [ "atk-sys", "bitflags", "glib", "glib-sys", "gobject-sys", "libc", ] [[package]] name = "atk-sys" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e552c1776737a4c80110d06b36d099f47c727335f9aaa5d942a72b6863a8ec6f" dependencies = [ "glib-sys", "gobject-sys", "libc", "pkg-config", ] [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "cairo-rs" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e05db47de3b0f09a222fa4bba2eab957d920d4243962a86b2d77ab401e4a359c" dependencies = [ "bitflags", "cairo-sys-rs", "glib", "glib-sys", "gobject-sys", "libc", ] [[package]] name = "cairo-sys-rs" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff65ba02cac715be836f63429ab00a767d48336efc5497c5637afb53b4f14d63" dependencies = [ "glib-sys", "libc", "pkg-config", ] [[package]] name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "clap" version = "2.33.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826bf7bc84f9435630275cb8e802a4a0ec792b615969934bd16d42ffed10f207" dependencies = [ "bitflags", "textwrap", "unicode-width", ] [[package]] name = "fragile" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9" [[package]] name = "gdk" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6243e995f41f3a61a31847e54cc719edce93dd9140c89dca3b9919be1cfe22d5" dependencies = [ "bitflags", "cairo-rs", "cairo-sys-rs", "gdk-pixbuf", "gdk-sys", "gio", "gio-sys", "glib", "glib-sys", "gobject-sys", "libc", "pango", ] [[package]] name = "gdk-pixbuf" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9726408ee1bbada83094326a99b9c68fea275f9dbb515de242a69e72051f4fcc" dependencies = [ "gdk-pixbuf-sys", "gio", "gio-sys", "glib", "glib-sys", "gobject-sys", "libc", ] [[package]] name = "gdk-pixbuf-sys" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8991b060a9e9161bafd09bf4a202e6fd404f5b4dd1a08d53a1e84256fb34ab0" dependencies = [ "gio-sys", "glib-sys", "gobject-sys", "libc", "pkg-config", ] [[package]] name = "gdk-sys" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6adf679e91d1bff0c06860287f80403e7db54c2d2424dce0a470023b56c88fbb" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", "gio-sys", "glib-sys", "gobject-sys", "libc", "pango-sys", "pkg-config", ] [[package]] name = "gio" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6261b5d34c30c2d59f879e643704cf54cb44731f3a2038000b68790c03e360e3" dependencies = [ "bitflags", "fragile", "gio-sys", "glib", "glib-sys", "gobject-sys", "lazy_static", "libc", ] [[package]] name = "gio-sys" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fad225242b9eae7ec8a063bb86974aca56885014672375e5775dc0ea3533911" dependencies = [ "glib-sys", "gobject-sys", "libc", "pkg-config", ] [[package]] name = "glib" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be27232841baa43e0fd5ae003f7941925735b2f733a336dc75f07b9eff415e7b" dependencies = [ "bitflags", "glib-sys", "gobject-sys", "lazy_static", "libc", ] [[package]] name = "glib-sys" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95856f3802f446c05feffa5e24859fe6a183a7cb849c8449afc35c86b1e316e2" dependencies = [ "libc", "pkg-config", ] [[package]] name = "gobject-sys" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31d1a804f62034eccf370006ccaef3708a71c31d561fee88564abe71177553d9" dependencies = [ "glib-sys", "libc", "pkg-config", ] [[package]] name = "gtk" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "709f1074259d4685b96133f92b75c7f35b504715b0fcdc96ec95de2607296a60" dependencies = [ "atk", "bitflags", "cairo-rs", "cairo-sys-rs", "cc", "gdk", "gdk-pixbuf", "gdk-pixbuf-sys", "gdk-sys", "gio", "gio-sys", "glib", "glib-sys", "gobject-sys", "gtk-sys", "lazy_static", "libc", "pango", "pango-sys", ] [[package]] name = "gtk-sys" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53def660c7b48b00b510c81ef2d2fbd3c570f1527081d8d7947f471513e1a4c1" dependencies = [ "atk-sys", "cairo-sys-rs", "gdk-pixbuf-sys", "gdk-sys", "gio-sys", "glib-sys", "gobject-sys", "libc", "pango-sys", "pkg-config", ] [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "indexmap" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", "hashbrown", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "linked-hash-map" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" dependencies = [ "libc", "winapi", ] [[package]] name = "pango" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "393fa071b144f8ffb83ede273758983cf414ca3c0b1d2a5a9ce325b3ba3dd786" dependencies = [ "bitflags", "glib", "glib-sys", "gobject-sys", "lazy_static", "libc", "pango-sys", ] [[package]] name = "pango-sys" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b93d84907b3cf0819bff8f13598ba72843bee579d5ebc2502e4b0367b4be7d" dependencies = [ "glib-sys", "gobject-sys", "libc", "pkg-config", ] [[package]] name = "pkg-config" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "proc-macro2" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "quote" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] [[package]] name = "rs" version = "0.1.0" dependencies = [ "bitflags", "cairo-rs", "cairo-sys-rs", "clap", "gdk", "gio", "glib", "glib-sys", "gtk", "gtk-sys", "maplit", "serde", "serde_yaml", "xkbcommon", ] [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "serde" version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_yaml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" dependencies = [ "indexmap", "ryu", "serde", "yaml-rust", ] [[package]] name = "syn" version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ "unicode-width", ] [[package]] name = "unicode-width" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "xkbcommon" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fda0ea5f7ddabd51deeeda7799bee06274112f577da7dd3d954b8eda731b2fce" dependencies = [ "libc", "memmap", ] [[package]] name = "yaml-rust" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] squeekboard-v1.17.1/Cargo.toml.in000066400000000000000000000011501422304253700166300ustar00rootroot00000000000000[package] name = "rs" version = "0.1.0" [lib] name = "rs" path = "@path@/src/lib.rs" crate-type = ["staticlib", "rlib"] # Cargo can't do autodiscovery if Cargo.toml is not in the root. [[bin]] name = "test_layout" path = "@path@/src/bin/test_layout.rs" [[example]] name = "test_layout" path = "@path@/examples/test_layout.rs" [features] glib_v0_14 = [] # Dependencies which don't change based on build flags [dependencies] maplit = "1.0.*" serde = { version = "1.0.*", features = ["derive"] } serde_yaml = "0.8.*" xkbcommon = { version = "0.4.*", features = ["wayland"] } # Here is inserted the Cargo.deps file squeekboard-v1.17.1/README.md000066400000000000000000000041361422304253700155610ustar00rootroot00000000000000*squeekboard* - a Wayland on-screen keyboard ======================================== *Squeekboard* is a keyboard-shaped input method supporting Wayland, built primarily for the *Librem 5* phone. It squeaks because some Rust got inside. Features -------- ### Present - GTK3 - Custom keyboard layouts defined in yaml - Input purpose dependent keyboard layouts - DBus interface to show and hide - Use Wayland input method protocol to submit text - Use Wayland virtual keyboard protocol ### TODO - Text prediction/correction - Use preedit - Submit actions like "next field" using a future Wayland protocol - Pick up DBus interface files from /usr/share Creating layouts ------------------- If you want to work on layouts, check out the [guide](doc/tutorial.md). Building -------- ### Dependencies See `.gitlab-ci.yml` or run `apt-get build-dep .` ### Build from git repo ```bash $ git clone https://gitlab.gnome.org/World/Phosh/squeekboard.git $ cd squeekboard $ mkdir _build $ meson _build/ $ cd _build $ ninja ``` To run tests use `ninja test`. To install squeekboard run `ninja install`. Running ------- ```bash $ phoc # if no compatible Wayland compositor is running yet $ cd ../build/ $ src/squeekboard ``` Squeekboard's panel will appear whenever a compatible application requests an input method. Click a text field in any GTK application, like `python3 ./tools/entry.py`. Squeekboard honors the gnome "screen-keyboard-enabled" setting. Either enable this through gnome-settings under accessibility or run: ```bash $ gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true ``` Alternatively, force panel visibility manually with: ```bash busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true ``` ### What the compositor has to support A compatible compositor has to support the protocols: - layer-shell - virtual-keyboard-v1 It's strongly recommended to support: - input-method-v2 Developing ---------- See [`doc/hacking.md`](doc/hacking.md) for this copy, or the [official documentation](https://developer.puri.sm/projects/squeekboard/) for the current release. squeekboard-v1.17.1/cargo.sh000077500000000000000000000007101422304253700157260ustar00rootroot00000000000000#!/bin/sh # This script manages Cargo operations # while keeping the artifact directory within the build tree # instead of the source tree set -e SCRIPT_PATH="$(realpath "$0")" SOURCE_DIR="$(dirname "$SCRIPT_PATH")" CARGO_TARGET_DIR="$(pwd)" export CARGO_TARGET_DIR cd "$SOURCE_DIR" # the 'run" command takes arguments at the end, # so --manifest-path must not be last CMD="$1" shift cargo "$CMD" --manifest-path "$CARGO_TARGET_DIR"/Cargo.toml "$@" squeekboard-v1.17.1/cargo_build.py000066400000000000000000000021321422304253700171200ustar00rootroot00000000000000#!/usr/bin/env python3 """This script manages Cargo builds while keeping the artifact directory within the build tree instead of the source tree. """ from pathlib import Path import shlex import subprocess import sys source_dir = Path(__file__).absolute().parent args = sys.argv[1:] binary_dir = "debug" if '--release' in args: binary_dir = "release" # The file produced by Cargo will have a special name try: i = args.index('--rename') except ValueError: filename = None else: args.pop(i) filename = args.pop(i) # The target destination of the produced file is a positional argument out_path = [arg for arg in args if not arg.startswith('--')] if out_path: out_path = out_path[0] i = args.index(out_path) args.pop(i) subprocess.run(['sh', "{}/cargo.sh".format(source_dir.as_posix()), 'build'] + args, check=True) if out_path: out_path = Path(out_path).absolute() out_basename = out_path.name filename = filename or out_basename subprocess.run(['cp', '-a', './{}/{}'.format(binary_dir, filename), out_path], check=True) squeekboard-v1.17.1/data/000077500000000000000000000000001422304253700152075ustar00rootroot00000000000000squeekboard-v1.17.1/data/common.css000066400000000000000000000006661422304253700172210ustar00rootroot00000000000000/* Theme independent styles */ sq_view { font-family: cantarell, sans-serif; font-size: 1.5em; } sq_button { border-radius: 4px; margin: 2px; } sq_view.wide sq_button { margin: 3px; } sq_button.latched, sq_button.locked { font-weight: bold; } sq_button.action { font-size: 0.75em; } sq_button.small { font-size: 0.5em; } sq_view.pin sq_button { border-radius: 0px; margin: 1px 1px 1px 1px; }squeekboard-v1.17.1/data/dbus/000077500000000000000000000000001422304253700161445ustar00rootroot00000000000000squeekboard-v1.17.1/data/dbus/sm.puri.OSK0.xml000066400000000000000000000013321422304253700207750ustar00rootroot00000000000000 Switch keyboard visibility Get keyboard visibility squeekboard-v1.17.1/data/icons/000077500000000000000000000000001422304253700163225ustar00rootroot00000000000000squeekboard-v1.17.1/data/icons/key-enter.svg000066400000000000000000000006041422304253700207460ustar00rootroot00000000000000 squeekboard-v1.17.1/data/icons/key-shift.svg000066400000000000000000000004271422304253700207510ustar00rootroot00000000000000 squeekboard-v1.17.1/data/icons/keyboard-mode-symbolic.svg000066400000000000000000000151741422304253700234140ustar00rootroot00000000000000 image/svg+xml squeekboard-v1.17.1/data/keyboards/000077500000000000000000000000001422304253700171725ustar00rootroot00000000000000squeekboard-v1.17.1/data/keyboards/am+phonetic.yaml000066400000000000000000000045741422304253700222720ustar00rootroot00000000000000# Armenian layout created by Norayr Chilingarian # Yerevan # Oct 2021 --- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 32, height: 32 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "՝ է թ փ ձ ջ ւ և ռ չ ճ ֊ ժ" - "ք ո ե ր տ ը ւ ի օ պ խ ծ շ" - "ա ս դ ֆ գ հ յ կ լ ․" - "Shift_L զ ղ ց վ բ ն մ ՛ BackSpace" - "show_numbers preferences space period Return" upper: - "՝ Է Թ Փ Ձ Ջ Ւ և Ռ Չ Ճ — Ժ" - "Ք Ո Ե Ր Տ Ը Ւ Ի Օ Պ Խ Ծ Շ" - "Ա Ս Դ Ֆ Գ Հ Յ Կ Լ ։" - "Shift_L Զ Ղ Ց Վ Բ Ն Մ ՞ BackSpace" - "show_numbers preferences space period Return" numbers: - "show_symbols , \" ' colon ; ! ? BackSpace" - "ﬓ ﬔ ﬕ ﬖ ﬗ ՟ և" - "1 2 3 4 5 6 7 8 9 0" - "show_letters preferences space period Return" symbols: - "show_numbers_from_symbols \\ % < > = [ ] BackSpace" - "* # $ / & - _ + ( )" - "© ® £ € ¥ ^ ° @ { }" - "~ ` | · √ π τ ÷ × ¶" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ԱԲԳ" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/am.yaml000066400000000000000000000046161422304253700204620ustar00rootroot00000000000000# Armenian layout created by Norayr Chilingarian # Yerevan # Oct 2021 --- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 32, height: 32 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "՝ ֆ ձ ֊ , ։ ՞ ․ ՛ ) օ է ղ" - "ճ փ բ ս մ ո ւ կ ը թ ծ ց »" - "ջ վ գ ե ա ն ի տ հ պ ր" - "Shift_L ժ դ չ յ զ լ ք խ շ ռ BackSpace" - "show_numbers preferences space period Return" upper: - "՜ Ֆ Ձ — $ … ՟ և ՚ ( Օ Է Ղ" - "Ճ Փ Բ Ս Մ Ո Ւ Կ Ը Թ Ծ Ց «" - "Ջ Վ Գ Ե Ա Ն Ի Տ Հ Պ Պ Ր" - "Shift_L Ժ Դ Չ Յ Զ Լ Ք Խ Շ Ռ BackSpace" - "show_numbers preferences space period Return" numbers: - "show_symbols , \" ' colon ; ! ? BackSpace" - "ﬓ ﬔ ﬕ ﬖ ﬗ ՟ և" - "1 2 3 4 5 6 7 8 9 0" - "show_letters preferences space period Return" symbols: - "show_numbers_from_symbols \\ % < > = [ ] BackSpace" - "* # $ / & - _ + ( )" - "© ® £ € ¥ ^ ° @ { }" - "~ ` | · √ π τ ÷ × ¶" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ԱԲԳ" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/ara.yaml000066400000000000000000000040051422304253700206200ustar00rootroot00000000000000# Maintained by: Khaled Eldoheiri --- outlines: default: { width: 32.66, height: 52 } altline: { width: 48.99, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 195.96, height: 52 } special: { width: 35.66, height: 52 } views: base: - "ذ ض ص ث ق ف غ ع خ ح ج" - "ش س ي ب ل ا ت ن م ك ط" - "Shift_L ء ؤ ر ة و ز ظ د BackSpace" - "show_numbers preferences space . Return" extra: - "ذ ض ص ث ق لإ إ ع خ ح ج" - "ش س ى ب لأ أ ت ن م ك ط" - "Shift_L ئ لآ لا ه آ ز ظ د BackSpace" - "show_numbers preferences space . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols ، \" ' : ؛ ! ؟ BackSpace" - "show_letters preferences space . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers \\ / < > = [ ] BackSpace" - "show_letters preferences space . Return" buttons: Shift_L: action: locking: lock_view: "extra" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "ض" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" space: outline: "spaceline" label: " " text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" squeekboard-v1.17.1/data/keyboards/ara_wide.yaml000066400000000000000000000037741422304253700216440ustar00rootroot00000000000000# Maintained by: Khaled Eldoheiri --- outlines: default: { width: 49, height: 42 } altline: { width: 73.5, height: 42 } wide: { width: 108, height: 42 } spaceline: { width: 324, height: 42 } special: { width: 49, height: 42 } views: base: - "ذ ض ص ث ق ف غ ع خ ح ج" - "ش س ي ب ل ا ت ن م ك ط" - "Shift_L ء ؤ ر ة و ز ظ د BackSpace" - "show_numbers preferences space . Return" extra: - "ذ ض ص ث ق لإ إ ع خ ح ج" - "ش س ى ب لأ أ ت ن م ك ط" - "Shift_L ئ لآ لا ه آ ز ظ د BackSpace" - "show_numbers preferences space . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols ، \" ' : ؛ ! ؟ BackSpace" - "show_letters preferences space . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers \\ / < > = [ ] BackSpace" - "show_letters preferences space . Return" buttons: Shift_L: action: locking: lock_view: "extra" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "ض" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" space: outline: "spaceline" label: " " text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" squeekboard-v1.17.1/data/keyboards/be.yaml000066400000000000000000000050241422304253700204450ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 59, height: 52 } spaceline: { width: 140, height: 52 } special: { width: 44, height: 52 } views: base: - "a z e r t y u i o p" - "q s d f g h j k l m" - "Shift_L w x c v b n . BackSpace" - "show_numbers preferences space show_eschars Return" upper: - "A Z E R T Y U I O P" - "Q S D F G H J K L M" - "Shift_L W X C V B N , BackSpace" - "show_numbers preferences space show_eschars Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space show_eschars Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space show_eschars Return" eschars: - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace" - "show_letters preferences space show_eschars Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/be_wide.yaml000066400000000000000000000050121422304253700214520ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 100, height: 42 } spaceline: { width: 205, height: 42 } special: { width: 54, height: 42 } views: base: - "a z e r t y u i o p" - "q s d f g h j k l m" - "Shift_L w x c v b n . BackSpace" - "show_numbers preferences space show_eschars Return" upper: - "A Z E R T Y U I O P" - "Q S D F G H J K L M" - "Shift_L W X C V B N , BackSpace" - "show_numbers preferences space show_eschars Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space show_eschars Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space show_eschars Return" eschars: - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace" - "show_letters preferences space show_eschars Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/bg+phonetic.yaml000066400000000000000000000041501422304253700222530ustar00rootroot00000000000000--- outlines: default: { width: 32.72, height: 52 } altline: { width: 47, height: 52 } wide: { width: 49.09, height: 52 } spaceline: { width: 185, height: 52 } special: { width: 44, height: 52 } views: base: - "я в е р т ъ у и о п ю" - "а с д ф г х й к л ш щ" - "Shift_L з ь ц ж б н м ч BackSpace" - "show_numbers preferences space . Return" upper: - "Я В Е Р Т Ъ У И О П Ю" - "А С Д Ф Г Х Й К Л Ш Щ" - "Shift_L З Ь Ц Ж Б Н М Ч BackSpace" - "show_numbers preferences space , Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/bg.yaml000066400000000000000000000041501422304253700204460ustar00rootroot00000000000000--- outlines: default: { width: 32.72, height: 52 } altline: { width: 47, height: 52 } wide: { width: 49.09, height: 52 } spaceline: { width: 185, height: 52 } special: { width: 44, height: 52 } views: base: - "у е и ш щ к с д з ц б" - "ь я а о ж г т н в м ч" - "Shift_L ю й ъ ф х п р л BackSpace" - "show_numbers preferences space . Return" upper: - "У Е И Ш Щ К С Д З Ц Б" - "Ь Я А О Ж Г Т Н В М Ч" - "Shift_L Ю Й Ъ Ф Х П Р Л BackSpace" - "show_numbers preferences space , Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? ѝ BackSpace" - "show_letters preferences space Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/br.yaml000066400000000000000000000041061422304253700204620ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l ç" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space , Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L Ç" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "à À á Á ã à â  é É" - "show_symbols ê Ê í Í ó Ó ô Ô" - "show_letters õ Õ ú Ú ü Ü period BackSpace" symbols: - "@ # $ % - + ÷ × = ≠" - "( ) § & < > / * { }" - "show_numbers_from_symbols º \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "1ã" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "1ã" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/ch+de.yaml000066400000000000000000000040431422304253700210350ustar00rootroot00000000000000# Maintained by Patrick Jörg . No Copyright, enjoy! --- outlines: default: { width: 35.33, height: 52 } altline: { width: 48, height: 52 } wide: { width: 59, height: 52 } spaceline: { width: 70, height: 52 } special: { width: 28, height: 52 } views: base: - "q w e r t z u i o p ü" - "a s d f g h j k l ö ä" - "Shift_L y x c v b n m BackSpace" - "show_numbers ? ! preferences ' space , . Return" upper: - "Q W E R T Z U I O P Ü" - "A S D F G H J K L Ö Ä" - "Shift_L Y X C V B N M BackSpace" - "show_numbers - _ preferences \" space , . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ * + - = ( ) ~ < >" - "show_symbols # & / \\ √ ; : BackSpace" - "show_letters ? ! preferences _ space , . Return" symbols: - "€ $ £ ¥ % | § µ [ ]" - "© ® § ` ^ { } · ¡ ¿" - "show_numbers « » ÷ × “ ” „ BackSpace" - "show_letters preferences - space , . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" space: outline: "spaceline" label: " " text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/ch+fr.yaml000066400000000000000000000052241422304253700210560ustar00rootroot00000000000000# Maintained by: Jordi Bossy . No Copyright, enjoy! --- outlines: default: { width: 35.33, height: 52 } altline: { width: 48, height: 52 } wide: { width: 59, height: 52 } spaceline: { width: 70, height: 52 } special: { width: 28, height: 52 } views: base: - "q w e r t z u i o p" - "a s d f g h j k l ?" - "Shift_L y x c v b n m BackSpace" - "show_numbers show_eschars preferences ' space , . Return" upper: - "Q W E R T Z U I O P" - "A S D F G H J K L !" - "Shift_L Y X C V B N M BackSpace" - "show_numbers show_eschars preferences \" space , . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ * + - = ( ) ~ < >" - "show_symbols # & / \\ √ ; : BackSpace" - "show_letters show_eschars preferences _ space , . Return" symbols: - "€ $ £ ¥ % | § µ [ ]" - "© ® § ` ^ { } · ¡ ¿" - "show_numbers « » ÷ × “ ” „ BackSpace" - "show_letters show_eschars preferences - space , . Return" eschars: - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers æ œ ä ë ï ö ü BackSpace" - "show_letters_from_accents preferences ñ Ñ space ° ß Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" show_letters_from_accents: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" label: " " text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/ch.yaml000066400000000000000000000053211422304253700204510ustar00rootroot00000000000000# Maintained by: Jordy Bossy # and Patrick Jörg . No Copyright, enjoy! --- outlines: default: { width: 35.33, height: 52 } altline: { width: 48, height: 52 } wide: { width: 59, height: 52 } spaceline: { width: 70, height: 52 } special: { width: 28, height: 52 } views: base: - "q w e r t z u i o p ü" - "a s d f g h j k l ö ä" - "Shift_L y x c v b n m BackSpace" - "show_numbers show_eschars preferences ' space , . Return" upper: - "Q W E R T Z U I O P Ü" - "A S D F G H J K L Ö Ä" - "Shift_L Y X C V B N M BackSpace" - "show_numbers show_eschars preferences \" space , . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ * + - = ( ) ~ < > ? !" - "show_symbols # & / \\ √ ; : BackSpace" - "show_letters show_eschars preferences _ space , . Return" symbols: - "€ $ £ ¥ % | § µ [ ]" - "© ® § ` ^ { } · ¡ ¿" - "show_numbers « » ÷ × “ ” „ BackSpace" - "show_letters show_eschars preferences - space , . Return" eschars: - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers æ œ ä ë ï ö ü BackSpace" - "show_letters_from_accents preferences ñ Ñ space ° ß Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" show_letters_from_accents: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" label: " " text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/ch_wide.yaml000066400000000000000000000052731422304253700214670ustar00rootroot00000000000000# Maintained by: Jordy Bossy # and Patrick Jörg . No Copyright, enjoy! --- outlines: default: { width: 48, height: 42 } altline: { width: 81, height: 42 } wide: { width: 108, height: 42 } spaceline: { width: 216, height: 42 } special: { width: 48, height: 42 } views: base: - "q w e r t z u i o p ü" - "a s d f g h j k l ö ä" - "Shift_L y x c v b n m BackSpace" - "show_numbers show_eschars preferences ' space , . Return" upper: - "Q W E R T Z U I O P Ü" - "A S D F G H J K L Ö Ä" - "Shift_L Y X C V B N M BackSpace" - "show_numbers show_eschars preferences \" space , . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ * + - = ( ) ~ < > ? !" - "show_symbols # & / \\ √ ; : BackSpace" - "show_letters show_eschars preferences _ space , . Return" symbols: - "€ $ £ ¥ % | § µ [ ]" - "© ® § ` ^ { } · ¡ ¿" - "show_numbers « » ÷ × “ ” „ BackSpace" - "show_letters show_eschars preferences - space , . Return" eschars: - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers æ œ ä ë ï ö ü BackSpace" - "show_letters_from_accents preferences ñ Ñ space ° ß Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "äÄ" show_letters_from_accents: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" label: " " text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/cz+qwerty.yaml000066400000000000000000000060671422304253700220320ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 52.67, height: 52 } spaceline: { width: 106, height: 52 } special: { width: 35.33, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences show_accents space , . Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences show_upper_accents space ! ? Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences show_accents space , . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences show_accents space , . Return" accents: - "ä ě é ř ť ý ů í ó ö" - "á š ď ë ŕ ú ü ô ľ" - "accents_Shift_L ž ß č ç ñ ň ĺ BackSpace" - "show_letters preferences show_accents space , . Return" upper_accents: - "Ä Ě É Ř Ť Ý Ů Í Ó Ö" - "Á Š Ď Ë Ŕ Ú Ü Ô Ľ" - "accents_Shift_L Ž ẞ Č Ç Ñ Ň Ĺ BackSpace" - "show_letters preferences show_upper_accents space , . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" accents_Shift_L: action: locking: lock_view: "upper_accents" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_accents: action: locking: lock_view: "accents" unlock_view: "base" outline: "special" label: "á" show_upper_accents: action: locking: lock_view: "upper_accents" unlock_view: "base" outline: "special" label: "Á" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/cz+qwerty_wide.yaml000066400000000000000000000060531422304253700230350ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 81, height: 42 } spaceline: { width: 162, height: 42 } special: { width: 54, height: 42 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences show_accents space , . Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences show_upper_accents space ! ? Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences show_accents space , . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences show_accents space , . Return" accents: - "ä ě é ř ť ý ů í ó ö" - "á š ď ë ŕ ú ü ô ľ" - "accents_Shift_L ž ß č ç ñ ň ĺ BackSpace" - "show_letters preferences show_accents space , . Return" upper_accents: - "Ä Ě É Ř Ť Ý Ů Í Ó Ö" - "Á Š Ď Ë Ŕ Ú Ü Ô Ľ" - "accents_Shift_L Ž ẞ Č Ç Ñ Ň Ĺ BackSpace" - "show_letters preferences show_upper_accents space , . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" accents_Shift_L: action: locking: lock_view: "upper_accents" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_accents: action: locking: lock_view: "accents" unlock_view: "base" outline: "special" label: "á" show_upper_accents: action: locking: lock_view: "upper_accents" unlock_view: "base" outline: "special" label: "Á" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/cz.yaml000066400000000000000000000060671422304253700205030ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 52.67, height: 52 } spaceline: { width: 106, height: 52 } special: { width: 35.33, height: 52 } views: base: - "q w e r t z u i o p" - "a s d f g h j k l" - "Shift_L y x c v b n m BackSpace" - "show_numbers preferences show_accents space , . Return" upper: - "Q W E R T Z U I O P" - "A S D F G H J K L" - "Shift_L Y X C V B N M BackSpace" - "show_numbers preferences show_upper_accents space ! ? Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences show_accents space , . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences show_accents space , . Return" accents: - "ä ě é ř ť ž ů í ó ö" - "á š ď ë ŕ ú ü ô ľ" - "accents_Shift_L ý ß č ç ñ ň ĺ BackSpace" - "show_letters preferences show_accents space , . Return" upper_accents: - "Ä Ě É Ř Ť Ž Ů Í Ó Ö" - "Á Š Ď Ë Ŕ Ú Ü Ô Ľ" - "accents_Shift_L Ý ẞ Č Ç Ñ Ň Ĺ BackSpace" - "show_letters preferences show_upper_accents space , . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" accents_Shift_L: action: locking: lock_view: "upper_accents" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_accents: action: locking: lock_view: "accents" unlock_view: "base" outline: "special" label: "á" show_upper_accents: action: locking: lock_view: "upper_accents" unlock_view: "base" outline: "special" label: "Á" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/cz_wide.yaml000066400000000000000000000060531422304253700215060ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 81, height: 42 } spaceline: { width: 162, height: 42 } special: { width: 54, height: 42 } views: base: - "q w e r t z u i o p" - "a s d f g h j k l" - "Shift_L y x c v b n m BackSpace" - "show_numbers preferences show_accents space , . Return" upper: - "Q W E R T Z U I O P" - "A S D F G H J K L" - "Shift_L Y X C V B N M BackSpace" - "show_numbers preferences show_upper_accents space ! ? Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences show_accents space , . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences show_accents space , . Return" accents: - "ä ě é ř ť ž ů í ó ö" - "á š ď ë ŕ ú ü ô ľ" - "accents_Shift_L ý ß č ç ñ ň ĺ BackSpace" - "show_letters preferences show_accents space , . Return" upper_accents: - "Ä Ě É Ř Ť Ž Ů Í Ó Ö" - "Á Š Ď Ë Ŕ Ú Ü Ô Ľ" - "accents_Shift_L Ý ẞ Č Ç Ñ Ň Ĺ BackSpace" - "show_letters preferences show_upper_accents space , . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" accents_Shift_L: action: locking: lock_view: "upper_accents" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_accents: action: locking: lock_view: "accents" unlock_view: "base" outline: "special" label: "á" show_upper_accents: action: locking: lock_view: "upper_accents" unlock_view: "base" outline: "special" label: "Á" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/de.yaml000066400000000000000000000046231422304253700204530ustar00rootroot00000000000000# Maintained by: Mark Müller --- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 99.67, height: 52 } special: { width: 35.33, height: 52 } views: base: - "q w e r t z u i o p" - "a s d f g h j k l" - "Shift_L y x c v b n m BackSpace" - "show_numbers show_eschars preferences space , . Return" upper: - "Q W E R T Z U I O P" - "A S D F G H J K L" - "Shift_L Y X C V B N M BackSpace" - "show_numbers show_eschars preferences space ! ? Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols ; \" ' : = < > BackSpace" - "show_letters show_eschars preferences space , . Return" symbols: - "~ ` ´ | · √ µ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers \\ / § π τ [ ] BackSpace" - "show_letters show_eschars preferences space , . Return" eschars: - "ä è é ö ü Ä È É Ö Ü" - "à â ê î ô À Â È Î Ô" - "show_numbers « » ç Ç æ œ ß BackSpace" - "show_letters show_eschars preferences space „ “ Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "äÄ" space: outline: "spaceline" label: " " text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" squeekboard-v1.17.1/data/keyboards/de_wide.yaml000066400000000000000000000045041422304253700214610ustar00rootroot00000000000000# Maintained by: Mark Müller --- outlines: default: { width: 48, height: 42 } altline: { width: 81, height: 42 } wide: { width: 108, height: 42 } spaceline: { width: 216, height: 42 } special: { width: 48, height: 42 } views: base: - "q w e r t z u i o p ü" - "a s d f g h j k l ö ä" - "Shift_L y x c v b n m BackSpace" - "show_numbers preferences space , . Return" upper: - "Q W E R T Z U I O P Ü" - "A S D F G H J K L Ö Ä" - "Shift_L Y X C V B N M BackSpace" - "show_numbers preferences space ! ? Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # % & - _ + ( ) ß" - "show_symbols ; \" ' : = < > BackSpace" - "show_letters preferences space , . Return" symbols: - "~ ` ´ · © ® ÷ × ¶" - "€ £ $ ¥ ^ ° * { } |" - "show_numbers \\ / § π τ [ ] BackSpace" - "show_letters preferences space , . Return" eschars: - "ä è é ö ü Ä È É Ö Ü" - "à â ê î ô À Â È Î Ô" - "show_numbers « » ç Ç æ œ ß BackSpace" - "show_letters preferences space „ “ Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "äÄ" space: outline: "spaceline" text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" squeekboard-v1.17.1/data/keyboards/dk.yaml000066400000000000000000000046751422304253700204700ustar00rootroot00000000000000--- outlines: default: { width: 32, height: 52 } altline: { width: 48.39024, height: 52 } wide: { width: 62, height: 52 } outline7: { width: 88.97561, height: 52 } spaceline: { width: 150.5853, height: 52 } views: base: - "q w e r t y u i o p å" - "a s d f g h j k l ø æ" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space . Return" upper: - "Q W E R T Y U I O P Å" - "A S D F G H J K L Ø Æ" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' : ; ! ? BackSpace" - "show_letters preferences space . Return" symbols: - "~ ` | U00B7 squareroot Greek_pi Greek_tau division multiply paragraph" - "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree * { }" - "show_numbers \\ / < > = [ ] BackSpace" - "show_letters preferences space . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "altline" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" ".": outline: altline space: outline: spaceline text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" U00B7: text: "·" squareroot: text: "√" Greek_pi: text: "π" division: text: "÷" multiply: text: "×" paragraph: text: "¶" Greek_tau: text: "τ" copyright: text: "©" U00AE: text: "®" U00A3: text: "£" EuroSign: text: "€" U00A5: text: "¥" asciicircum: text: "^" degree: text: "°" squeekboard-v1.17.1/data/keyboards/email/000077500000000000000000000000001422304253700202615ustar00rootroot00000000000000squeekboard-v1.17.1/data/keyboards/email/us.yaml000066400000000000000000000042231422304253700215750ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 106.67, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space at period Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space at period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space at period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space at period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase at: outline: "special" text: "@" preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/emoji/000077500000000000000000000000001422304253700202755ustar00rootroot00000000000000squeekboard-v1.17.1/data/keyboards/emoji/us.yaml000066400000000000000000000043651422304253700216200ustar00rootroot00000000000000--- outlines: default: { width: 52, height: 52 } altline: { width: 40, height: 52 } narrow: { width: 22, height: 52 } views: base: - "😀 😁 😅 😂 😊 😇 🙃" - "😍 😘 😋 😜 😎 🥳 😔" - "😢 😭 😡 😱 🤔 😬 🙄" - "preferences blank 1 2 3 4 5 6 blank BackSpace" two: - "🤩 🤨 🤓 😴 🤢 🤮 😈" - "💩 🙌 👏 👍 👎 👌 👋" - "💪 🖕 🙏 💋 🤦‍♀️ 🤷‍♀️ 💃" - "preferences blank 1 2 3 4 5 6 blank BackSpace" three: - "🐶 🐱 🐯 🙈 🐴 🦄 🌳" - "🍀 🌹 💫 ⭐️ ✨ 💥 🔥" - "🌈 ☀️ 🌤 🌧 ⛄️ ☂️ 🌊" - "preferences blank 1 2 3 4 5 6 blank BackSpace" four: - "🍎 🍓 🍑 🍍 🍆 🥑 🥦" - "🍕 🎂 🍫 🍿 🍻 🍾 🍽" - "⚽️ 🏀 🏓 🏆 🎹 🎸 🎯" - "preferences blank 1 2 3 4 5 6 blank BackSpace" five: - "🚗 🚌 🚲 🚄 🚂 ✈️ 🛰" - "🚀 🛸 🚁 🚦 🏝 🏔 ⛺️" - "🏠 🏢 🏥 🏛 🛤 🌅 🎇" - "preferences blank 1 2 3 4 5 6 blank BackSpace" six: - "⌚️ 📱 💻 🖥 🖨 🕹 ✉️" - "📞 ☎️ ⏰ ⏳ 📈 📉 📌" - "🎁 ❤️ 💕 💯 ✅ ❎ 📢" - "preferences blank 1 2 3 4 5 6 blank BackSpace" buttons: 1: action: set_view: "base" outline: "altline" label: "1" 2: action: set_view: "two" outline: "altline" label: "2" 3: action: set_view: "three" outline: "altline" label: "3" 4: action: set_view: "four" outline: "altline" label: "4" 5: action: set_view: "five" outline: "altline" label: "5" 6: action: set_view: "six" outline: "altline" label: "6" preferences: action: "show_prefs" outline: "altline" icon: "keyboard-mode-symbolic" BackSpace: outline: "altline" icon: "edit-clear-symbolic" keysym: BackSpace blank: outline: "narrow" text: "" squeekboard-v1.17.1/data/keyboards/epo.yaml000066400000000000000000000044611422304253700206460ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 99.67, height: 52 } special: { width: 35.33, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers show_eschars preferences space , . Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers show_eschars preferences space ! ? Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' : ; ! ? BackSpace" - "show_letters preferences space . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space . Return" eschars: - "ĉ ĝ ĥ ĵ ŝ ŭ ?" - "Ĉ Ĝ Ĥ Ĵ Ŝ Ŭ !" - "show_numbers ' - 🐊 💚 🌐 . BackSpace" - "show_letters show_eschars preferences space „ “ Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "ŭŜ" space: outline: "spaceline" label: " " text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" squeekboard-v1.17.1/data/keyboards/es+cat.yaml000066400000000000000000000046651422304253700212430ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 99.67, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l ç" - "Shift_L z x c v b n m BackSpace" - "show_numbers show_eschars preferences space ? period Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L Ç" - "Shift_L Z X C V B N M BackSpace" - "show_numbers show_eschars preferences space ¿ period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! = BackSpace" - "show_letters show_eschars preferences space ? period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers \\ / < > = [ ] BackSpace" - "show_letters show_eschars preferences space ? period Return" eschars: - "á é í ó ú Á É Í Ó Ú" - "à è ì ò ù À È Ì Ò Ù" - "show_numbers ü ç ï Ü Ç Ï ¡ BackSpace" - "show_letters show_eschars preferences space « » Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "default" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "àÀ" period: outline: "default" text: "." space: outline: "spaceline" text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/es.yaml000066400000000000000000000046651422304253700205000ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 99.67, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l ñ" - "Shift_L z x c v b n m BackSpace" - "show_numbers show_eschars preferences space ? period Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L Ñ" - "Shift_L Z X C V B N M BackSpace" - "show_numbers show_eschars preferences space ¿ period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! = BackSpace" - "show_letters show_eschars preferences space ? period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers \\ / < > = [ ] BackSpace" - "show_letters show_eschars preferences space ? period Return" eschars: - "á é í ó ú Á É Í Ó Ú" - "à è ì ò ù À È Ì Ò Ù" - "show_numbers ü ç ï Ü Ç Ï ¡ BackSpace" - "show_letters show_eschars preferences space « » Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "default" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "áÁ" period: outline: "default" text: "." space: outline: "spaceline" text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/fi.yaml000066400000000000000000000073441422304253700204640ustar00rootroot00000000000000--- outlines: default: { width: 32, height: 52 } altline: { width: 48.39024, height: 52 } wide: { width: 62, height: 52 } outline7: { width: 88.97561, height: 52 } spaceline: { width: 150.5853, height: 52 } views: base: - "q w e r t y u i o p å" - "a s d f g h j k l ö ä" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space . Return" upper: - "Q W E R T Y U I O P Å" - "A S D F G H J K L Ö Ä" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "at numbersign dollar percent ampersand minus underscore plus parenleft parenright" - "show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace" - "show_letters preferences space . Return" symbols: - "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph" - "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright" - "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace" - "show_letters preferences space . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "altline" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" ".": outline: altline space: outline: spaceline text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" aring: text: "å" Aring: text: "Å" ouml: text: "ö" Ouml: text: "Ö" auml: text: "ä" Auml: text: "Ä" asterisk: text: "*" asciitilde: text: "~" quoteleft: text: "`" bar: text: "|" U00B7: text: "·" squareroot: text: "√" Greek_pi: text: "π" division: text: "÷" multiply: text: "×" paragraph: text: "¶" Greek_tau: text: "τ" copyright: text: "©" numbersign: text: "#" U00AE: text: "®" at: text: "@" dollar: text: "$" U00A3: text: "£" percent: text: "%" EuroSign: text: "€" ampersand: text: "&" U00A5: text: "¥" minus: text: "-" asciicircum: text: "^" underscore: text: "_" degree: text: "°" plus: text: "+" equal: text: "=" parenleft: text: "(" parenright: text: ")" braceleft: text: "{" braceright: text: "}" comma: text: "," backslash: text: "\\" slash: text: "/" quotedbl: text: "\"" quoteright: text: "'" less: text: "<" greater: text: ">" colon: text: ":" semicolon: text: ";" exclam: text: "!" question: text: "?" bracketleft: text: "[" bracketright: text: "]" squeekboard-v1.17.1/data/keyboards/fr.yaml000066400000000000000000000050241422304253700204660ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 59, height: 52 } spaceline: { width: 140, height: 52 } special: { width: 44, height: 52 } views: base: - "a z e r t y u i o p" - "q s d f g h j k l m" - "Shift_L w x c v b n . BackSpace" - "show_numbers preferences space show_eschars Return" upper: - "A Z E R T Y U I O P" - "Q S D F G H J K L M" - "Shift_L W X C V B N , BackSpace" - "show_numbers preferences space show_eschars Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space show_eschars Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space show_eschars Return" eschars: - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace" - "show_letters preferences space show_eschars Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/fr_wide.yaml000066400000000000000000000050121422304253700214730ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 100, height: 42 } spaceline: { width: 205, height: 42 } special: { width: 54, height: 42 } views: base: - "a z e r t y u i o p" - "q s d f g h j k l m" - "Shift_L w x c v b n . BackSpace" - "show_numbers preferences space show_eschars Return" upper: - "A Z E R T Y U I O P" - "Q S D F G H J K L M" - "Shift_L W X C V B N , BackSpace" - "show_numbers preferences space show_eschars Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space show_eschars Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space show_eschars Return" eschars: - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace" - "show_letters preferences space show_eschars Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/gr.yaml000066400000000000000000000106101422304253700204640ustar00rootroot00000000000000# Greek layout created by Antonis Tsolomitis # University of the Aegean, Department of Mathematics, atsol@aegean.gr # Sep 2019 --- outlines: default: { width: 32, height: 52 } altline: { width: 48.39024, height: 52 } wide: { width: 62, height: 52 } outline7: { width: 88.97561, height: 52 } spaceline: { width: 150.5853, height: 52 } views: base: - "; ς ε ρ τ υ θ ι ο π !" - "α σ δ φ γ η ξ κ λ show_accented" - "Shift_L ζ χ ψ ω β ν μ , BackSpace" - "show_numbers preferences space period Return" upper: - ": EuroSign Ε Ρ Τ Υ Θ Ι Ο Π" - "Α Σ Δ Φ Γ Η Ξ Κ Λ show_accented" - "Shift_L Ζ Χ Ψ Ω Β Ν Μ · BackSpace" - "show_numbers preferences space « » Return" accented: - "ά έ ή ί ό ύ ώ ϊ ϋ ΐ" - "ΰ Ά Έ Ή Ί Ό Ύ Ώ Ϊ show_base" - "Ϋ Ϗ ϐ ϑ ϕ ϖ ϗ – — BackSpace" - "show_numbers preferences space quoteleft quoteright Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "at numbersign dollar percent ampersand minus underscore plus parenleft parenright" - "show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace" - "show_letters preferences space period Return" symbols: - "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph" - "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright" - "show_numbers backslash slash less greater equal bracketleft bracketright BackSpace" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "altline" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "ΑΒΓ" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_accented: action: locking: lock_view: "accented" unlock_view: "base" outline: "altline" label: "άΐ" show_base: action: set_view: "base" outline: "altline" label: "αι" period: outline: "altline" text: "." space: outline: spaceline text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" aring: text: "å" Aring: text: "Å" oslash: text: "ø" Oslash: text: "Ø" ae: text: "æ" AE: text: "Æ" asterisk: text: "*" asciitilde: text: "~" quoteleft: text: "`" bar: text: "|" U00B7: text: "·" squareroot: text: "√" Greek_pi: text: "π" division: text: "÷" multiply: text: "×" paragraph: text: "¶" Greek_tau: text: "τ" copyright: text: "©" numbersign: text: "#" U00AE: text: "®" at: text: "@" dollar: text: "$" U00A3: text: "£" percent: text: "%" EuroSign: text: "€" ampersand: text: "&" U00A5: text: "¥" minus: text: "-" asciicircum: text: "^" underscore: text: "_" degree: text: "°" plus: text: "+" equal: text: "=" parenleft: text: "(" parenright: text: ")" braceleft: text: "{" braceright: text: "}" comma: text: "," backslash: text: "\\" slash: text: "/" quotedbl: text: "\"" quoteright: text: "'" less: text: "<" greater: text: ">" colon: text: ":" semicolon: text: ";" exclam: text: "!" question: text: "?" bracketleft: text: "[" bracketright: text: "]" squeekboard-v1.17.1/data/keyboards/il.yaml000066400000000000000000000034741422304253700204720ustar00rootroot00000000000000--- outlines: default: { width: 40, height: 60 } altline: { width: 56, height: 60 } wide: { width: 62, height: 60 } spaceline: { width: 142, height: 60 } special: { width: 44, height: 60 } views: base: - "' - ק ר א ט ו ן ם פ" - "ש ד ג כ ע י ח ל ך ף" - "ז ס ב ה נ מ צ ת ץ BackSpace" - "show_numbers comma preferences space period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # ₪ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € $ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space period Return" buttons: BackSpace: outline: "default" icon: "edit-clear-symbolic" action: erase comma: outline: "special" text: "," preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/ir.yaml000066400000000000000000000042351422304253700204740ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "ض ص ق ف غ ع ه خ ح ج" - "ش س ی ب ل ا ت ن م ک" - "Shift_L ظ ط ز ر ذ د و BackSpace" - "show_numbers preferences space period Return" upper: - "پ { } [ ] ّ َ ِ ُ چ" - "ؤ‌ ئ ي‌ إ أ آ ة‌ » « گ" - "Shift_L ك ٓ ژ ء > < ؟ BackSpace" - "show_numbers preferences space period Return" numbers: - "۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۰" - "@ # ﷼ % & - _ + ( )" - "show_symbols , \" ' colon ؛ ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/ir_wide.yaml000066400000000000000000000042311422304253700215000ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 108, height: 42 } spaceline: { width: 216, height: 42 } special: { width: 54, height: 42 } views: base: - "ض ص ق ف غ ع ه خ ح ج" - "ش س ی ب ل ا ت ن م ک" - "Shift_L ظ ط ز ر ذ د و BackSpace" - "show_numbers preferences space period Return" upper: - "پ { } [ ] ّ َ ِ ُ چ" - "ؤ‌ ئ ي‌ إ أ آ ة‌ » « گ" - "Shift_L ك ٓ ژ ء > < ؟ BackSpace" - "show_numbers preferences space period Return" numbers: - "۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۰" - "@ # ﷼ % & - _ + ( )" - "show_symbols , \" ' colon ؛ ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" ".": outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/it+fur.yaml000066400000000000000000000050301422304253700212600ustar00rootroot00000000000000# Friulian layout created by Fabio Tomat # 14 october 2020 --- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 99.67, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers show_eschars preferences space , . Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers show_eschars preferences space “ ” Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' : ; ! = BackSpace" - "show_letters show_eschars preferences space ? . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers \\ / < > = [ ] BackSpace" - "show_letters show_eschars preferences space ? . Return" eschars: - "â ê î ô û Â Ê Î Ô Û" - "à è ì ò ù À È Ì Ò Ù" - "show_numbers ç Ç ᶜ ᵐ ⁿ ᵉ ᵗ BackSpace" - "show_letters show_eschars preferences space ᶠ . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "àê" space: outline: "spaceline" label: " " text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" squeekboard-v1.17.1/data/keyboards/it.yaml000066400000000000000000000047141422304253700205000ustar00rootroot00000000000000# Italian layout created by Antonio Pandolfo # 03 october 2019 --- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 99.67, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers show_eschars preferences space , . Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers show_eschars preferences space ? . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' : ; ! ? BackSpace" - "show_letters show_eschars preferences space ? . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers \\ / < > = [ ] BackSpace" - "show_letters show_eschars preferences space ? . Return" eschars: - "á é í ó ú Á É Í Ó Ú" - "à è ì ò « » ù ! { }" - "show_numbers \\ / < > = [ ] BackSpace" - "show_letters show_eschars preferences space « » Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "default" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "altline" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: set_view: "eschars" outline: "altline" label: "àè" space: outline: "spaceline" label: " " text: " " Return: outline: "altline" icon: "key-enter" keysym: "Return" squeekboard-v1.17.1/data/keyboards/jp+kana.yaml000066400000000000000000000345061422304253700214050ustar00rootroot00000000000000# Maintained by: Mark Müller --- outlines: default: { width: 62, height: 52 } default-wide: { width: 62, height: 52 } altline: { width: 62, height: 52 } wide: { width: 62, height: 52 } special: { width: 62, height: 52 } views: base: # hiragana - "preferences _a ka sa BackSpace" - "Left ta na ha Right" - "カタカナ ma ya ra space" - "switch2roman symbols wa punct Return" _a: - "preferences dummykey _a dummykey BackSpace" - "あ い う え お" - "ぁ ぃ ぅ ぇ ぉ" # 2 code points each - "dummykey dummykey ゔ dummykey dummykey" ka: - "preferences dummykey ka dummykey BackSpace" - "か き く け こ" - "が ぎ ぐ げ ご" - "ゕ dummykey dummykey ゖ dummykey" sa: - "preferences dummykey sa dummykey BackSpace" - "さ し す せ そ" - "ざ じ ず ぜ ぞ" ta: - "preferences dummykey ta dummykey BackSpace" - "た ち つ て と" - "だ ぢ づ で ど" - "dummykey dummykey っ dummykey dummykey" na: - "preferences dummykey na dummykey BackSpace" - "な に ぬ ね の" ha: - "preferences dummykey ha dummykey BackSpace" - "は ひ ふ へ ほ" - "ば び ぶ べ ぼ" - "ぱ ぴ ぷ ぺ ぽ" ma: - "preferences dummykey ma dummykey BackSpace" - "ま み む め も" ya: - "preferences dummykey ya dummykey BackSpace" - "や dummykey ゆ dummykey よ" - "ゃ dummykey ゅ dummykey ょ" ra: - "preferences dummykey ra dummykey BackSpace" - "ら り る れ ろ" wa: - "preferences dummykey wa dummykey BackSpace" - "わ ゐ dummykey ゑ を" - "ゎ dummykey ん dummykey dummykey" symbols: - "preferences dummykey symbols dummykey BackSpace" - "「 」 ( ) §" - "【 】 < > =" - "+ * & % $ " punct: - "preferences dummykey punct dummykey BackSpace" - "。 、 ? ! ー" - ": ; ・ 〜 …" - "♪ ” ’ ゙ ゚" #a あア かカ さサ たタ なナ はハ まマ やヤ らラ わワ #i いイ きキ しシ ちチ にニ ひヒ みミ ※ りリ ゐヰ #u うウ くク すス つツ ぬヌ ふフ むム ゆユ るル ※ #e えエ けケ せセ てテ ねネ へヘ めメ ※ れレ ゑヱ #o おオ こコ そソ とト のノ ほホ もモ よヨ ろロ をヲ # g z d b p n #a が ガ ざ ザ だ ダ ば バ ぱ パ ん ン #i ぎ ギ じ ジ ぢ ヂ び ビ ぴ ピ #u ぐ グ ず ズ づ ヅ ぶ ブ ぷ プ #e げ ゲ ぜ ゼ で デ べ ベ ぺ ペ #o ご ゴ ぞ ゾ ど ド ぼ ボ ぽ ポ カタカナ: # katakana - "preferences _A KA SA BackSpace" - "Left TA NA HA Right" - "ひらがな MA YA RA space" - "switch2roman SYMBOLS WA PUNCT Return" _A: - "preferences DUMMYKEY _A DUMMYKEY BackSpace" - "ア イ ウ エ オ" - "ァ ィ ゥ ェ ォ" - "DUMMYKEY DUMMYKEY ヴ DUMMYKEY DUMMYKEY" KA: - "preferences DUMMYKEY KA DUMMYKEY BackSpace" - "カ キ ク ケ コ" - "ガ ギ グ ゲ ゴ" - "ヵ DUMMYKEY ㇰ ヶ DUMMYKEY" SA: - "preferences DUMMYKEY SA DUMMYKEY BackSpace" - "サ シ ス セ ソ" - "ザ ジ ズ ゼ ゾ" - "DUMMYKEY ㇱ ㇲ DUMMYKEY DUMMYKEY" TA: - "preferences DUMMYKEY TA DUMMYKEY BackSpace" - "タ チ ツ テ ト" - "ダ ヂ ヅ デ ド" - "DUMMYKEY DUMMYKEY ッ DUMMYKEY ㇳ" NA: - "preferences DUMMYKEY NA DUMMYKEY BackSpace" - "ナ ニ ヌ ネ ノ" - "DUMMYKEY DUMMYKEY ㇴ DUMMYKEY DUMMYKEY" HA: - "preferences DUMMYKEY HA DUMMYKEY BackSpace" - "ハ ヒ フ ヘ ホ" - "バ ビ ブ ベ ボ" - "パ ピ プ ペ ポ" MA: - "preferences DUMMYKEY MA DUMMYKEY BackSpace" - "マ ミ ム メ モ" - "DUMMYKEY DUMMYKEY ㇺ DUMMYKEY DUMMYKEY" YA: - "preferences DUMMYKEY YA DUMMYKEY BackSpace" - "ヤ DUMMYKEY ユ DUMMYKEY ヨ" - "ャ DUMMYKEY ュ DUMMYKEY ョ" RA: - "preferences DUMMYKEY RA DUMMYKEY BackSpace" - "ラ リ ル レ ロ" - "ㇻ ㇼ ㇽ ㇾ ㇿ" WA: - "preferences DUMMYKEY WA DUMMYKEY BackSpace" - "ワ ヰ DUMMYKEY ヱ ヲ" - "ヮ ヸ ン ヹ ヺ" # numbers view numbers: - "preferences 1 2 3 BackSpace" - "Left 4 5 6 Right" - "roman 7 8 9 space" - "switch2kana * 0 # Return" # Roman alphabet view roman: - "preferences RSYM1 ABC DEF BackSpace" - "Left GHI JKL MNO Right" - "ひらがな PQRS TUV WXYZ space" - "switch2num RSYM2 RSYM3 RSYM4 Return" RSYM1: - "preferences dummykey RSYM1 dummykey BackSpace" - "@ # $ § :" - "| € ¥ £ 1" ABC: - "preferences dummykey ABC dummykey BackSpace" - "A B C Ä ç" - "a b c ä 2" DEF: - "preferences dummykey DEF dummykey BackSpace" - "D E F dummykey" - "d e f 3" GHI: - "preferences dummykey GHI dummykey BackSpace" - "G H I dummykey" - "g h i 4" JKL: - "preferences dummykey JKL dummykey BackSpace" - "J K L dummykey" - "j k l 5" MNO: - "preferences dummykey MNO dummykey BackSpace" - "M N O Ö dummykey" - "m n o ö 6" PQRS: - "preferences dummykey PQRS dummykey BackSpace" - "P Q R S ß" - "p q r s 7" TUV: - "preferences dummykey TUV dummykey BackSpace" - "T U V Ü dummykey" - "t u v ü 8" WXYZ: - "preferences dummykey WXYZ dummykey BackSpace" - "W X Y Z dummykey" - "w x y z 9" RSYM2: - "preferences dummykey RSYM2 dummykey BackSpace" - "( ) ' \" ~" - "[ ] { } _" RSYM3: - "preferences dummykey RSYM3 dummykey BackSpace" - "+ - * / =" - "< > ^ ° 0" RSYM4: - "preferences dummykey RSYM4 dummykey BackSpace" - ", . ? ! ;" - "\\ ´ ` · ¶" buttons: # following 4 buttons use the corresponding xkb name as keysym BackSpace: outline: "wide" icon: "edit-clear-symbolic" action: erase Return: outline: "wide" icon: "key-enter" keysym: "Return" Left: outline: "wide" label: "←" keysym: "Left" Right: outline: "wide" label: "→" keysym: "Right" # special button "preferences" is handled in the code preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" # space button using text tag for ideographic space space: outline: "default-wide" label: "␣" text: " " # switch to number view numbers: action: set_view: "numbers" outline: "wide" label: "123" # switch to latin characters roman: action: set_view: "roman" outline: "wide" label: "ᴀʙᴄ" # toggle button with 3 different states switch2roman: # switch from kana to latin characters view action: set_view: "roman" outline: "wide" label: "あᴀ₁" switch2num: # switch from latin characters to numbers view action: set_view: "numbers" outline: "wide" label: "ぁA₁" switch2kana: # switch from numbers to hiragana view action: set_view: "base" outline: "wide" label: "ぁᴀ1" # Buttons for katakana and symbols ひらがな: action: set_view: "base" outline: "wide" label: "あさ" _a: action: locking: lock_view: "_a" unlock_view: "base" outline: "altline" label: "あ" ka: action: locking: lock_view: "ka" unlock_view: "base" outline: "altline" label: "か" sa: action: locking: lock_view: "sa" unlock_view: "base" outline: "altline" label: "さ" ta: action: locking: lock_view: "ta" unlock_view: "base" outline: "altline" label: "た" na: action: locking: lock_view: "na" unlock_view: "base" outline: "altline" label: "な" ha: action: locking: lock_view: "ha" unlock_view: "base" outline: "altline" label: "は" ma: action: locking: lock_view: "ma" unlock_view: "base" outline: "altline" label: "ま" ya: action: locking: lock_view: "ya" unlock_view: "base" outline: "altline" label: "や" ra: action: locking: lock_view: "ra" unlock_view: "base" outline: "altline" label: "ら" wa: action: locking: lock_view: "wa" unlock_view: "base" outline: "altline" label: "わ" dummykey: action: set_view: "base" outline: "altline" label: "" # buttons available on different views like symbols and punct should go # back to their corresponding view symbols: action: locking: lock_view: "symbols" unlock_view: "base" outline: "altline" label: "()" punct: action: locking: lock_view: "punct" unlock_view: "base" outline: "altline" label: "。" # Buttons for katakana and symbols カタカナ: action: set_view: "カタカナ" outline: "wide" label: "アサ" _A: action: locking: lock_view: "_A" unlock_view: "カタカナ" outline: "altline" label: "ア" KA: action: locking: lock_view: "KA" unlock_view: "カタカナ" outline: "altline" label: "カ" SA: action: locking: lock_view: "SA" unlock_view: "カタカナ" outline: "altline" label: "サ" TA: action: locking: lock_view: "TA" unlock_view: "カタカナ" outline: "altline" label: "タ" NA: action: locking: lock_view: "NA" unlock_view: "カタカナ" outline: "altline" label: "ナ" HA: action: locking: lock_view: "HA" unlock_view: "カタカナ" outline: "altline" label: "ハ" MA: action: locking: lock_view: "MA" unlock_view: "カタカナ" outline: "altline" label: "マ" YA: action: locking: lock_view: "YA" unlock_view: "カタカナ" outline: "altline" label: "ヤ" RA: action: locking: lock_view: "RA" unlock_view: "カタカナ" outline: "altline" label: "ラ" WA: action: locking: lock_view: "WA" unlock_view: "カタカナ" outline: "altline" label: "ワ" DUMMYKEY: action: set_view: "カタカナ" outline: "altline" label: "" SYMBOLS: action: locking: lock_view: "symbols" unlock_view: "カタカナ" outline: "altline" label: "()" PUNCT: action: locking: lock_view: "punct" unlock_view: "カタカナ" outline: "altline" label: "。" # Buttons for Latin characters RSYM1: action: locking: lock_view: "RSYM1" unlock_view: "roman" outline: "altline" label: "@#" ABC: action: locking: lock_view: "ABC" unlock_view: "roman" outline: "altline" label: "ᴀʙᴄ" DEF: action: locking: lock_view: "DEF" unlock_view: "roman" outline: "altline" label: "ᴅᴇꜰ" GHI: action: locking: lock_view: "GHI" unlock_view: "roman" outline: "altline" label: "ɢʜɪ" JKL: action: locking: lock_view: "JKL" unlock_view: "roman" outline: "altline" label: "ᴊᴋʟ" MNO: action: locking: lock_view: "MNO" unlock_view: "roman" outline: "altline" label: "ᴍɴᴏ" PQRS: action: locking: lock_view: "PQRS" unlock_view: "roman" outline: "altline" label: "ᴘǫʀs" TUV: action: locking: lock_view: "TUV" unlock_view: "roman" outline: "altline" label: "ᴛᴜᴠ" WXYZ: action: locking: lock_view: "WXYZ" unlock_view: "roman" outline: "altline" label: "ᴡxʏᴢ" RSYM2: action: locking: lock_view: "RSYM2" unlock_view: "roman" outline: "altline" label: "()" RSYM3: action: locking: lock_view: "RSYM3" unlock_view: "roman" outline: "altline" label: "+-" RSYM4: action: locking: lock_view: "RSYM4" unlock_view: "roman" outline: "altline" label: ",.?" squeekboard-v1.17.1/data/keyboards/jp+kana_wide.yaml000066400000000000000000000345061422304253700224150ustar00rootroot00000000000000# Maintained by: Mark Müller --- outlines: default: { width: 62, height: 42 } default-wide: { width: 62, height: 42 } altline: { width: 62, height: 42 } wide: { width: 62, height: 42 } special: { width: 62, height: 42 } views: base: # hiragana - "preferences _a ka sa BackSpace" - "Left ta na ha Right" - "カタカナ ma ya ra space" - "switch2roman symbols wa punct Return" _a: - "preferences dummykey _a dummykey BackSpace" - "あ い う え お" - "ぁ ぃ ぅ ぇ ぉ" # 2 code points each - "dummykey dummykey ゔ dummykey dummykey" ka: - "preferences dummykey ka dummykey BackSpace" - "か き く け こ" - "が ぎ ぐ げ ご" - "ゕ dummykey dummykey ゖ dummykey" sa: - "preferences dummykey sa dummykey BackSpace" - "さ し す せ そ" - "ざ じ ず ぜ ぞ" ta: - "preferences dummykey ta dummykey BackSpace" - "た ち つ て と" - "だ ぢ づ で ど" - "dummykey dummykey っ dummykey dummykey" na: - "preferences dummykey na dummykey BackSpace" - "な に ぬ ね の" ha: - "preferences dummykey ha dummykey BackSpace" - "は ひ ふ へ ほ" - "ば び ぶ べ ぼ" - "ぱ ぴ ぷ ぺ ぽ" ma: - "preferences dummykey ma dummykey BackSpace" - "ま み む め も" ya: - "preferences dummykey ya dummykey BackSpace" - "や dummykey ゆ dummykey よ" - "ゃ dummykey ゅ dummykey ょ" ra: - "preferences dummykey ra dummykey BackSpace" - "ら り る れ ろ" wa: - "preferences dummykey wa dummykey BackSpace" - "わ ゐ dummykey ゑ を" - "ゎ dummykey ん dummykey dummykey" symbols: - "preferences dummykey symbols dummykey BackSpace" - "「 」 ( ) §" - "【 】 < > =" - "+ * & % $ " punct: - "preferences dummykey punct dummykey BackSpace" - "。 、 ? ! ー" - ": ; ・ 〜 …" - "♪ ” ’ ゙ ゚" #a あア かカ さサ たタ なナ はハ まマ やヤ らラ わワ #i いイ きキ しシ ちチ にニ ひヒ みミ ※ りリ ゐヰ #u うウ くク すス つツ ぬヌ ふフ むム ゆユ るル ※ #e えエ けケ せセ てテ ねネ へヘ めメ ※ れレ ゑヱ #o おオ こコ そソ とト のノ ほホ もモ よヨ ろロ をヲ # g z d b p n #a が ガ ざ ザ だ ダ ば バ ぱ パ ん ン #i ぎ ギ じ ジ ぢ ヂ び ビ ぴ ピ #u ぐ グ ず ズ づ ヅ ぶ ブ ぷ プ #e げ ゲ ぜ ゼ で デ べ ベ ぺ ペ #o ご ゴ ぞ ゾ ど ド ぼ ボ ぽ ポ カタカナ: # katakana - "preferences _A KA SA BackSpace" - "Left TA NA HA Right" - "ひらがな MA YA RA space" - "switch2roman SYMBOLS WA PUNCT Return" _A: - "preferences DUMMYKEY _A DUMMYKEY BackSpace" - "ア イ ウ エ オ" - "ァ ィ ゥ ェ ォ" - "DUMMYKEY DUMMYKEY ヴ DUMMYKEY DUMMYKEY" KA: - "preferences DUMMYKEY KA DUMMYKEY BackSpace" - "カ キ ク ケ コ" - "ガ ギ グ ゲ ゴ" - "ヵ DUMMYKEY ㇰ ヶ DUMMYKEY" SA: - "preferences DUMMYKEY SA DUMMYKEY BackSpace" - "サ シ ス セ ソ" - "ザ ジ ズ ゼ ゾ" - "DUMMYKEY ㇱ ㇲ DUMMYKEY DUMMYKEY" TA: - "preferences DUMMYKEY TA DUMMYKEY BackSpace" - "タ チ ツ テ ト" - "ダ ヂ ヅ デ ド" - "DUMMYKEY DUMMYKEY ッ DUMMYKEY ㇳ" NA: - "preferences DUMMYKEY NA DUMMYKEY BackSpace" - "ナ ニ ヌ ネ ノ" - "DUMMYKEY DUMMYKEY ㇴ DUMMYKEY DUMMYKEY" HA: - "preferences DUMMYKEY HA DUMMYKEY BackSpace" - "ハ ヒ フ ヘ ホ" - "バ ビ ブ ベ ボ" - "パ ピ プ ペ ポ" MA: - "preferences DUMMYKEY MA DUMMYKEY BackSpace" - "マ ミ ム メ モ" - "DUMMYKEY DUMMYKEY ㇺ DUMMYKEY DUMMYKEY" YA: - "preferences DUMMYKEY YA DUMMYKEY BackSpace" - "ヤ DUMMYKEY ユ DUMMYKEY ヨ" - "ャ DUMMYKEY ュ DUMMYKEY ョ" RA: - "preferences DUMMYKEY RA DUMMYKEY BackSpace" - "ラ リ ル レ ロ" - "ㇻ ㇼ ㇽ ㇾ ㇿ" WA: - "preferences DUMMYKEY WA DUMMYKEY BackSpace" - "ワ ヰ DUMMYKEY ヱ ヲ" - "ヮ ヸ ン ヹ ヺ" # numbers view numbers: - "preferences 1 2 3 BackSpace" - "Left 4 5 6 Right" - "roman 7 8 9 space" - "switch2kana * 0 # Return" # Roman alphabet view roman: - "preferences RSYM1 ABC DEF BackSpace" - "Left GHI JKL MNO Right" - "ひらがな PQRS TUV WXYZ space" - "switch2num RSYM2 RSYM3 RSYM4 Return" RSYM1: - "preferences dummykey RSYM1 dummykey BackSpace" - "@ # $ § :" - "| € ¥ £ 1" ABC: - "preferences dummykey ABC dummykey BackSpace" - "A B C Ä ç" - "a b c ä 2" DEF: - "preferences dummykey DEF dummykey BackSpace" - "D E F dummykey" - "d e f 3" GHI: - "preferences dummykey GHI dummykey BackSpace" - "G H I dummykey" - "g h i 4" JKL: - "preferences dummykey JKL dummykey BackSpace" - "J K L dummykey" - "j k l 5" MNO: - "preferences dummykey MNO dummykey BackSpace" - "M N O Ö dummykey" - "m n o ö 6" PQRS: - "preferences dummykey PQRS dummykey BackSpace" - "P Q R S ß" - "p q r s 7" TUV: - "preferences dummykey TUV dummykey BackSpace" - "T U V Ü dummykey" - "t u v ü 8" WXYZ: - "preferences dummykey WXYZ dummykey BackSpace" - "W X Y Z dummykey" - "w x y z 9" RSYM2: - "preferences dummykey RSYM2 dummykey BackSpace" - "( ) ' \" ~" - "[ ] { } _" RSYM3: - "preferences dummykey RSYM3 dummykey BackSpace" - "+ - * / =" - "< > ^ ° 0" RSYM4: - "preferences dummykey RSYM4 dummykey BackSpace" - ", . ? ! ;" - "\\ ´ ` · ¶" buttons: # following 4 buttons use the corresponding xkb name as keysym BackSpace: outline: "wide" icon: "edit-clear-symbolic" action: erase Return: outline: "wide" icon: "key-enter" keysym: "Return" Left: outline: "wide" label: "←" keysym: "Left" Right: outline: "wide" label: "→" keysym: "Right" # special button "preferences" is handled in the code preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" # space button using text tag for ideographic space space: outline: "default-wide" label: "␣" text: " " # switch to number view numbers: action: set_view: "numbers" outline: "wide" label: "123" # switch to latin characters roman: action: set_view: "roman" outline: "wide" label: "ᴀʙᴄ" # toggle button with 3 different states switch2roman: # switch from kana to latin characters view action: set_view: "roman" outline: "wide" label: "あᴀ₁" switch2num: # switch from latin characters to numbers view action: set_view: "numbers" outline: "wide" label: "ぁA₁" switch2kana: # switch from numbers to hiragana view action: set_view: "base" outline: "wide" label: "ぁᴀ1" # Buttons for katakana and symbols ひらがな: action: set_view: "base" outline: "wide" label: "あさ" _a: action: locking: lock_view: "_a" unlock_view: "base" outline: "altline" label: "あ" ka: action: locking: lock_view: "ka" unlock_view: "base" outline: "altline" label: "か" sa: action: locking: lock_view: "sa" unlock_view: "base" outline: "altline" label: "さ" ta: action: locking: lock_view: "ta" unlock_view: "base" outline: "altline" label: "た" na: action: locking: lock_view: "na" unlock_view: "base" outline: "altline" label: "な" ha: action: locking: lock_view: "ha" unlock_view: "base" outline: "altline" label: "は" ma: action: locking: lock_view: "ma" unlock_view: "base" outline: "altline" label: "ま" ya: action: locking: lock_view: "ya" unlock_view: "base" outline: "altline" label: "や" ra: action: locking: lock_view: "ra" unlock_view: "base" outline: "altline" label: "ら" wa: action: locking: lock_view: "wa" unlock_view: "base" outline: "altline" label: "わ" dummykey: action: set_view: "base" outline: "altline" label: "" # buttons available on different views like symbols and punct should go # back to their corresponding view symbols: action: locking: lock_view: "symbols" unlock_view: "base" outline: "altline" label: "()" punct: action: locking: lock_view: "punct" unlock_view: "base" outline: "altline" label: "。" # Buttons for katakana and symbols カタカナ: action: set_view: "カタカナ" outline: "wide" label: "アサ" _A: action: locking: lock_view: "_A" unlock_view: "カタカナ" outline: "altline" label: "ア" KA: action: locking: lock_view: "KA" unlock_view: "カタカナ" outline: "altline" label: "カ" SA: action: locking: lock_view: "SA" unlock_view: "カタカナ" outline: "altline" label: "サ" TA: action: locking: lock_view: "TA" unlock_view: "カタカナ" outline: "altline" label: "タ" NA: action: locking: lock_view: "NA" unlock_view: "カタカナ" outline: "altline" label: "ナ" HA: action: locking: lock_view: "HA" unlock_view: "カタカナ" outline: "altline" label: "ハ" MA: action: locking: lock_view: "MA" unlock_view: "カタカナ" outline: "altline" label: "マ" YA: action: locking: lock_view: "YA" unlock_view: "カタカナ" outline: "altline" label: "ヤ" RA: action: locking: lock_view: "RA" unlock_view: "カタカナ" outline: "altline" label: "ラ" WA: action: locking: lock_view: "WA" unlock_view: "カタカナ" outline: "altline" label: "ワ" DUMMYKEY: action: set_view: "カタカナ" outline: "altline" label: "" SYMBOLS: action: locking: lock_view: "symbols" unlock_view: "カタカナ" outline: "altline" label: "()" PUNCT: action: locking: lock_view: "punct" unlock_view: "カタカナ" outline: "altline" label: "。" # Buttons for Latin characters RSYM1: action: locking: lock_view: "RSYM1" unlock_view: "roman" outline: "altline" label: "@#" ABC: action: locking: lock_view: "ABC" unlock_view: "roman" outline: "altline" label: "ᴀʙᴄ" DEF: action: locking: lock_view: "DEF" unlock_view: "roman" outline: "altline" label: "ᴅᴇꜰ" GHI: action: locking: lock_view: "GHI" unlock_view: "roman" outline: "altline" label: "ɢʜɪ" JKL: action: locking: lock_view: "JKL" unlock_view: "roman" outline: "altline" label: "ᴊᴋʟ" MNO: action: locking: lock_view: "MNO" unlock_view: "roman" outline: "altline" label: "ᴍɴᴏ" PQRS: action: locking: lock_view: "PQRS" unlock_view: "roman" outline: "altline" label: "ᴘǫʀs" TUV: action: locking: lock_view: "TUV" unlock_view: "roman" outline: "altline" label: "ᴛᴜᴠ" WXYZ: action: locking: lock_view: "WXYZ" unlock_view: "roman" outline: "altline" label: "ᴡxʏᴢ" RSYM2: action: locking: lock_view: "RSYM2" unlock_view: "roman" outline: "altline" label: "()" RSYM3: action: locking: lock_view: "RSYM3" unlock_view: "roman" outline: "altline" label: "+-" RSYM4: action: locking: lock_view: "RSYM4" unlock_view: "roman" outline: "altline" label: ",.?" squeekboard-v1.17.1/data/keyboards/no.yaml000066400000000000000000000050701422304253700204740ustar00rootroot00000000000000--- outlines: default: { width: 32, height: 52 } altline: { width: 48.39024, height: 52 } wide: { width: 64, height: 52 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p å" - "a s d f g h j k l ø æ" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space . Return" upper: - "Q W E R T Y U I O P Å" - "A S D F G H J K L Ø Æ" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' : ; ! ? BackSpace" - "show_letters preferences space . Return" symbols: - "~ ` | U00B7 squareroot Greek_pi Greek_tau division multiply paragraph" - "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: altline label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" ".": outline: "special" space: outline: spaceline text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" U00B7: text: "·" squareroot: text: "√" Greek_pi: text: "π" division: text: "÷" multiply: text: "×" paragraph: text: "¶" Greek_tau: text: "τ" copyright: text: "©" U00AE: text: "®" U00A3: text: "£" EuroSign: text: "€" U00A5: text: "¥" asciicircum: text: "^" degree: text: "°" squeekboard-v1.17.1/data/keyboards/number/000077500000000000000000000000001422304253700204625ustar00rootroot00000000000000squeekboard-v1.17.1/data/keyboards/number/us.yaml000066400000000000000000000014441422304253700220000ustar00rootroot00000000000000--- outlines: default: { width: 37.46341, height: 52 } altline: { width: 48.39024, height: 52 } outline7: { width: 88.97561, height: 52 } spaceline: { width: 120.5853, height: 52 } views: base: - "1 2 3 parenleft parenright" - "4 5 6 numbersign asterisk" - "7 8 9 plus minus" - "BackSpace 0 space Return" buttons: BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase space: outline: spaceline text: " " Return: outline: outline7 icon: "key-enter" keysym: "Return" asterisk: text: "*" numbersign: text: "#" minus: text: "-" plus: text: "+" parenleft: text: "(" parenright: text: ")" squeekboard-v1.17.1/data/keyboards/pin/000077500000000000000000000000001422304253700177605ustar00rootroot00000000000000squeekboard-v1.17.1/data/keyboards/pin/us.yaml000066400000000000000000000005301422304253700212710ustar00rootroot00000000000000--- margins: { top: 4, side: 0, bottom: 4 } outlines: default: { width: 120, height: 52 } views: base: - "1 2 3" - "4 5 6" - "7 8 9" - "BackSpace 0 Return" buttons: BackSpace: icon: "edit-clear-symbolic" action: erase Return: icon: "key-enter" keysym: "Return" squeekboard-v1.17.1/data/keyboards/pl.yaml000066400000000000000000000063451422304253700205010ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 59, height: 52 } spaceline: { width: 140, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space show_accents Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space show_upper_accents Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space period Return" accents: - "q w ę r t y u i ó p" - "ą ś d f g h j k ł" - "accents_show_upper ż ź ć v b ń m BackSpace" - "show_numbers preferences space show_accents Return" upper_accents: - "Q W Ę R T Y U I Ó P" - "Ą Ś D F G H J K Ł" - "accents_show_upper Ż Ź Ć V B Ń M BackSpace" - "show_numbers preferences space show_upper_accents Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" accents_show_upper: action: locking: lock_view: "upper_accents" unlock_view: "accents" looks_locked_from: - "upper" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" keysym: "BackSpace" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_accents: action: locking: lock_view: "accents" unlock_view: "base" outline: "altline" label: "ąę" show_upper_accents: action: locking: lock_view: "upper_accents" unlock_view: "upper" looks_locked_from: - "accents" outline: "altline" label: "ĄĘ" period: outline: "altline" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/pl_wide.yaml000066400000000000000000000056011422304253700215030ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 100, height: 42 } spaceline: { width: 206, height: 42 } special: { width: 54, height: 42 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space show_accents Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space show_upper_accents Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space period Return" accents: - "q w ę r t y u i ó p" - "ą ś d f g h j k ł" - "Shift_L ż ź ć v b ń m BackSpace" - "show_numbers preferences space show_accents Return" upper_accents: - "Q W Ę R T Y U I Ó P" - "Ą Ś D F G H J K Ł" - "Shift_L Ż Ź Ć V B Ń M BackSpace" - "show_numbers preferences space show_upper_accents Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" keysym: "BackSpace" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_accents: action: locking: lock_view: "accents" unlock_view: "base" outline: "altline" label: "ąę" show_upper_accents: action: locking: lock_view: "upper_accents" unlock_view: "upper" outline: "altline" label: "ĄĘ" period: outline: "altline" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/ro.yaml000066400000000000000000000050141422304253700204760ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 99.67, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers show_eschars preferences space . Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers show_eschars preferences space , Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters show_eschars preferences space . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters show_eschars preferences space , Return" eschars: - "ă â î ș ț á é í ó ü" - "Ă Â Î Ș Ț Á É Í Ó Ü" - "show_numbers_from_symbols „ ” « » ― { } BackSpace" - "show_letters show_eschars preferences space . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "ăĂ" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/ro_wide.yaml000066400000000000000000000050051422304253700215060ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 108, height: 42 } spaceline: { width: 153, height: 42 } special: { width: 54, height: 42 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers show_eschars preferences space . Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers show_eschars preferences space , Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters show_eschars preferences space . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters show_eschars preferences space , Return" eschars: - "ă â î ș ț á é í ó ü" - "Ă Â Î Ș Ț Á É Í Ó Ü" - "show_numbers_from_symbols „ ” « » ― { } BackSpace" - "show_letters show_eschars preferences space . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "altline" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "ăĂ" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/ru.yaml000066400000000000000000000047251422304253700205140ustar00rootroot00000000000000--- outlines: default: { width: 32, height: 52 } altline: { width: 32, height: 52 } wide: { width: 57, height: 52 } narrow: { width: 26, height: 52 } spaceline: { width: 107, height: 52 } fill: { width: 159, height: 52 } special: { width: 42, height: 52 } views: base: - "й ц у к е н г ш щ з х" - "ф ы в а п р о л д ж э" - "Shift_L я ч с м и т ь б ю BackSpace" - "show_numbers preferences ё space ъ period Return" upper: - "Й Ц У К Е Н Г Ш Щ З Х" - "Ф Ы В А П Р О Л Д Ж Э" - "Shift_L Я Ч С М И Т Ь Б Ю BackSpace" - "show_numbers preferences Ё space Ъ comma Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space_fill period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space_fill period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "wide" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "АБВ" show_symbols: action: set_view: "symbols" outline: "wide" label: "*/=" period: outline: "special" text: "." comma: outline: "special" text: "," space: outline: "spaceline" text: " " space_fill: outline: "fill" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" ё: outline: "narrow" Ё: outline: "narrow" ъ: outline: "narrow" Ъ: outline: "narrow" squeekboard-v1.17.1/data/keyboards/se.yaml000066400000000000000000000072541422304253700204750ustar00rootroot00000000000000--- outlines: default: { width: 32, height: 52 } altline: { width: 48.39024, height: 52 } wide: { width: 64, height: 52 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p å" - "a s d f g h j k l ö ä" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space . Return" upper: - "Q W E R T Y U I O P Å" - "A S D F G H J K L Ö Ä" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "at numbersign dollar percent ampersand minus underscore plus parenleft parenright" - "show_symbols comma quotedbl quoteright colon semicolon exclam question BackSpace" - "show_letters preferences space . Return" symbols: - "asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph" - "copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright" - "show_numbers_from_symbols backslash slash less greater equal bracketleft bracketright BackSpace" - "show_letters preferences space . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: altline icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: outline: "wide" action: set_view: "numbers" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: altline label: "123" show_letters: outline: "wide" action: set_view: "base" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" ".": outline: "special" space: outline: spaceline text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" asterisk: text: "*" asciitilde: text: "~" quoteleft: text: "`" bar: text: "|" U00B7: text: "·" squareroot: text: "√" Greek_pi: text: "π" division: text: "÷" multiply: text: "×" paragraph: text: "¶" Greek_tau: text: "τ" copyright: text: "©" numbersign: text: "#" U00AE: text: "®" at: text: "@" dollar: text: "$" U00A3: text: "£" percent: text: "%" EuroSign: text: "€" ampersand: text: "&" U00A5: text: "¥" minus: text: "-" asciicircum: text: "^" underscore: text: "_" degree: text: "°" plus: text: "+" equal: text: "=" parenleft: text: "(" parenright: text: ")" braceleft: text: "{" braceright: text: "}" comma: text: "," backslash: text: "\\" slash: text: "/" quotedbl: text: "\"" quoteright: text: "'" less: text: "<" greater: text: ">" colon: text: ":" semicolon: text: ";" exclam: text: "!" question: text: "?" bracketleft: text: "[" bracketright: text: "]" squeekboard-v1.17.1/data/keyboards/terminal/000077500000000000000000000000001422304253700210055ustar00rootroot00000000000000squeekboard-v1.17.1/data/keyboards/terminal/fr.yaml000066400000000000000000000125531422304253700223060ustar00rootroot00000000000000--- outlines: action: { width: 59, height: 46 } small: { width: 50, height: 22 } default: { width: 35.33, height: 46 } altline: { width: 48, height: 46 } wide: { width: 50, height: 46 } spaceline: { width: 110, height: 46 } special: { width: 44, height: 46 } views: base: - "Ctrl Alt Tabsmall ↑ ↓ ← →" - "a z e r t y u i o p" - "q s d f g h j k l m" - "Shift_L w x c v b n period BackSpace" - "show_numbers preferences space show_eschars show_actions Return" upper: - "Ctrl Alt Tabsmall PgUp PgDn Home End" - "A Z E R T Y U I O P" - "Q S D F G H J K L M" - "Shift_L W X C V B N , BackSpace" - "show_numbers preferences space show_eschars show_actions Return" numbers: - "Ctrl Alt Tabsmall ↑ ↓ ← →" - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space show_eschars show_actions Return" symbols: - "Ctrl Alt Tabsmall ↑ ↓ ← →" - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space show_eschars show_actions Return" eschars: - "Ctrl Alt Tabsmall ↑ ↓ ← →" - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace" - "show_letters preferences space show_eschars show_actions Return" actions: - "Ctrl Alt PgUp PgDn Home End" - "F1 F2 F3 F4 F5 F6" - "F7 F8 F9 F10 F11 F12" - "Esc Tab Pause Insert Up Del" - "show_letters Menu Break Left Down Right" buttons: F1: outline: "action" keysym: "F1" F2: outline: "action" keysym: "F2" F3: outline: "action" keysym: "F3" F4: outline: "action" keysym: "F4" F5: outline: "action" keysym: "F5" F6: outline: "action" keysym: "F6" F7: outline: "action" keysym: "F7" F8: outline: "action" keysym: "F8" F9: outline: "action" keysym: "F9" F10: outline: "action" keysym: "F10" F11: outline: "action" keysym: "F11" F12: outline: "action" keysym: "F12" Esc: outline: "action" keysym: "Escape" Tab: outline: "action" keysym: "Tab" Tabsmall: outline: "small" keysym: "Tab" label: "Tab" Del: outline: "action" keysym: "Delete" Insert: outline: "action" keysym: "Insert" Menu: outline: "action" keysym: "Menu" Pause: outline: "action" keysym: "Pause" Break: outline: "action" keysym: "Break" Home: outline: "small" keysym: "Home" End: outline: "small" keysym: "End" PgUp: outline: "small" keysym: "Page_Up" PgDn: outline: "small" keysym: "Page_Down" "↑": outline: "small" keysym: "Up" "↓": outline: "small" keysym: "Down" "←": outline: "small" keysym: "Left" "→": outline: "small" keysym: "Right" Up: label: "↑" outline: "action" keysym: "Up" Left: label: "←" outline: "action" keysym: "Left" Down: label: "↓" outline: "action" keysym: "Down" Right: label: "→" outline: "action" keysym: "Right" Ctrl: modifier: "Control" outline: "small" label: "Ctrl" Alt: modifier: "Alt" outline: "small" label: "Alt" period: outline: "special" text: "." show_actions: action: set_view: "actions" outline: "special" label: ">_" Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/terminal/fr_wide.yaml000066400000000000000000000127621422304253700233200ustar00rootroot00000000000000--- outlines: action: { width: 90, height: 37 } small: { width: 67.4, height: 22 } default: { width: 54, height: 37 } altline: { width: 81, height: 37 } wide: { width: 100, height: 37 } spaceline: { width: 110, height: 37 } special: { width: 54, height: 37 } views: base: - "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →" - "a z e r t y u i o p" - "q s d f g h j k l m" - "Shift_L w x c v b n period BackSpace" - "show_numbers preferences space show_eschars show_actions Return" upper: - "EscSmall TabSmall Ctrl Alt PgUp PgDn Home End" - "A Z E R T Y U I O P" - "Q S D F G H J K L M" - "Shift_L W X C V B N , BackSpace" - "show_numbers preferences space show_eschars show_actions Return" numbers: - "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →" - "1 2 3 4 5 6 7 8 9 0" - "@ # € % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space show_eschars show_actions Return" symbols: - "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →" - "~ ` | · √ π τ ÷ × ¶" - "© ® £ $ ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space show_eschars show_actions Return" eschars: - "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →" - "à â ç é è ê î ô ù û" - "À Â Ç É È Ê Î Ô Ù Û" - "show_numbers_from_symbols æ œ ä ë ï ö ü BackSpace" - "show_letters preferences space show_eschars show_actions Return" actions: - "EscSmall TabSmall Ctrl Alt PgUp PgDn Home End" - "F1 F2 F3 F4 F5 F6" - "F7 F8 F9 F10 F11 F12" - "Esc Tab Pause Insert Up Del" - "show_letters Menu Break Left Down Right" buttons: F1: outline: "action" keysym: "F1" F2: outline: "action" keysym: "F2" F3: outline: "action" keysym: "F3" F4: outline: "action" keysym: "F4" F5: outline: "action" keysym: "F5" F6: outline: "action" keysym: "F6" F7: outline: "action" keysym: "F7" F8: outline: "action" keysym: "F8" F9: outline: "action" keysym: "F9" F10: outline: "action" keysym: "F10" F11: outline: "action" keysym: "F11" F12: outline: "action" keysym: "F12" Esc: outline: "action" keysym: "Escape" EscSmall: outline: "small" keysym: "Escape" label: "Esc" Tab: outline: "action" keysym: "Tab" TabSmall: outline: "small" keysym: "Tab" label: "Tab" Del: outline: "action" keysym: "Delete" Insert: outline: "action" keysym: "Insert" Menu: outline: "action" keysym: "Menu" Pause: outline: "action" keysym: "Pause" Break: outline: "action" keysym: "Break" Home: outline: "small" keysym: "Home" End: outline: "small" keysym: "End" PgUp: outline: "small" keysym: "Page_Up" PgDn: outline: "small" keysym: "Page_Down" "↑": outline: "small" keysym: "Up" "↓": outline: "small" keysym: "Down" "←": outline: "small" keysym: "Left" "→": outline: "small" keysym: "Right" Up: label: "↑" outline: "action" keysym: "Up" Left: label: "←" outline: "action" keysym: "Left" Down: label: "↓" outline: "action" keysym: "Down" Right: label: "→" outline: "action" keysym: "Right" Ctrl: modifier: "Control" outline: "small" label: "Ctrl" Alt: modifier: "Alt" outline: "small" label: "Alt" period: outline: "special" text: "." show_actions: action: set_view: "actions" outline: "special" label: ">_" Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "abc" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" show_eschars: action: locking: lock_view: "eschars" unlock_view: "base" outline: "altline" label: "âÂ" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" "\"": keysym: "quotedbl" squeekboard-v1.17.1/data/keyboards/terminal/us.yaml000066400000000000000000000112021422304253700223140ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 46 } action: { width: 59, height: 46 } altline: { width: 52.67, height: 46 } wide: { width: 59, height: 46 } spaceline: { width: 140, height: 46 } special: { width: 44, height: 46 } small: { width: 59, height: 22 } views: base: - "Ctrl Alt ↑ ↓ ← →" - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space show_actions Return" upper: - "Ctrl Alt PgUp PgDn Home End" - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space show_actions Return" numbers: - "Ctrl Alt ↑ ↓ ← →" - "1 2 3 4 5 6 7 8 9 0" - "* # $ / & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "Ctrl Alt ↑ ↓ ← →" - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° @ { }" - "show_numbers_from_symbols \\ % < > = [ ] BackSpace" - "show_letters preferences space period Return" actions: - "Ctrl Alt PgUp PgDn Home End" - "F1 F2 F3 F4 F5 F6" - "F7 F8 F9 F10 F11 F12" - "Esc Tab Pause Insert Up Del" - "show_letters Menu Break Left Down Right" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "τ=\\" show_actions: action: set_view: "actions" outline: "altline" label: ">_" period: outline: "altline" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" F1: outline: "action" keysym: "F1" F2: outline: "action" keysym: "F2" F3: outline: "action" keysym: "F3" F4: outline: "action" keysym: "F4" F5: outline: "action" keysym: "F5" F6: outline: "action" keysym: "F6" F7: outline: "action" keysym: "F7" F8: outline: "action" keysym: "F8" F9: outline: "action" keysym: "F9" F10: outline: "action" keysym: "F10" F11: outline: "action" keysym: "F11" F12: outline: "action" keysym: "F12" Esc: outline: "action" keysym: "Escape" Tab: outline: "action" keysym: "Tab" Del: outline: "action" keysym: "Delete" Insert: outline: "action" keysym: "Insert" Menu: outline: "action" keysym: "Menu" Pause: outline: "action" keysym: "Pause" Break: outline: "action" keysym: "Break" Home: outline: "small" keysym: "Home" End: outline: "small" keysym: "End" PgUp: outline: "small" keysym: "Page_Up" PgDn: outline: "small" keysym: "Page_Down" "↑": outline: "small" keysym: "Up" "↓": outline: "small" keysym: "Down" "←": outline: "small" keysym: "Left" "→": outline: "small" keysym: "Right" Up: label: "↑" outline: "action" keysym: "Up" Left: label: "←" outline: "action" keysym: "Left" Down: label: "↓" outline: "action" keysym: "Down" Right: label: "→" outline: "action" keysym: "Right" Ctrl: modifier: "Control" outline: "small" label: "Ctrl" Alt: modifier: "Alt" outline: "small" label: "Alt" squeekboard-v1.17.1/data/keyboards/terminal/us_wide.yaml000066400000000000000000000116271422304253700233370ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 37 } action: { width: 90, height: 37 } altline: { width: 81, height: 37 } wide: { width: 90, height: 37 } spaceline: { width: 225, height: 37 } special: { width: 54, height: 37 } small: { width: 67.4, height: 22 } views: base: - "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →" - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space show_actions Return" upper: - "EscSmall TabSmall Ctrl Alt PgUp PgDn Home End" - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space show_actions Return" numbers: - "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →" - "1 2 3 4 5 6 7 8 9 0" - "* # $ / & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "EscSmall TabSmall Ctrl Alt ↑ ↓ ← →" - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° @ { }" - "show_numbers_from_symbols \\ % < > = [ ] BackSpace" - "show_letters preferences space period Return" actions: - "EscSmall TabSmall Ctrl Alt PgUp PgDn Home End" - "F1 F2 F3 F4 F5 F6" - "F7 F8 F9 F10 F11 F12" - "Esc Tab Pause Insert Up Del" - "show_letters Menu Break Left Down Right" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "τ=\\" show_actions: action: set_view: "actions" outline: "altline" label: ">_" period: outline: "altline" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" F1: outline: "action" keysym: "F1" F2: outline: "action" keysym: "F2" F3: outline: "action" keysym: "F3" F4: outline: "action" keysym: "F4" F5: outline: "action" keysym: "F5" F6: outline: "action" keysym: "F6" F7: outline: "action" keysym: "F7" F8: outline: "action" keysym: "F8" F9: outline: "action" keysym: "F9" F10: outline: "action" keysym: "F10" F11: outline: "action" keysym: "F11" F12: outline: "action" keysym: "F12" Esc: outline: "action" keysym: "Escape" EscSmall: outline: "small" keysym: "Escape" label: "Esc" Tab: outline: "action" keysym: "Tab" TabSmall: outline: "small" keysym: "Tab" label: "Tab" Del: outline: "action" keysym: "Delete" Insert: outline: "action" keysym: "Insert" Menu: outline: "action" keysym: "Menu" Pause: outline: "action" keysym: "Pause" Break: outline: "action" keysym: "Break" Home: outline: "small" keysym: "Home" End: outline: "small" keysym: "End" PgUp: outline: "small" keysym: "Page_Up" PgDn: outline: "small" keysym: "Page_Down" "↑": outline: "small" keysym: "Up" "↓": outline: "small" keysym: "Down" "←": outline: "small" keysym: "Left" "→": outline: "small" keysym: "Right" Up: label: "↑" outline: "action" keysym: "Up" Left: label: "←" outline: "action" keysym: "Left" Down: label: "↓" outline: "action" keysym: "Down" Right: label: "→" outline: "action" keysym: "Right" Ctrl: modifier: "Control" outline: "small" label: "Ctrl" Alt: modifier: "Alt" outline: "small" label: "Alt"squeekboard-v1.17.1/data/keyboards/th.yaml000066400000000000000000000045451422304253700205010ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "ๅ / _ ภ ถ ุ ึ ค ต จ ข ช" - "ๆ ไ ำ พ ะ ั ี ร น ย บ ล" - "ฟ ห ก ด เ ้ ่ า ส ว ง ฃ" - "Shift_L ผ ป แ อ ิ ื ท ม ใ ฝ BackSpace" - "show_numbers preferences space period Return" upper: - "+ ๑ ๒ ๓ ๔ ู ฿ ๕ ๖ ๗ ๘ ๙" - "๐ \" ฎ ฑ ธ ํ ๊ ณ ฯ ญ ฐ ," - "ฤ ฆ ฏ โ ฌ ็ ๋ ษ ศ ซ . ฅ" - "Shift_L ( ) ฉ ฮ ฺ ์ ? ฒ ฬ ฦ BackSpace" - "show_numbers preferences space period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "กขค" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/th_wide.yaml000066400000000000000000000047421422304253700215100ustar00rootroot00000000000000--- outlines: default: { width: 75, height: 56 } altline: { width: 75, height: 56 } wide: { width: 135, height: 56 } spaceline: { width: 450, height: 56 } spacelinesymbol: { width: 300, height: 56 } special: { width: 90, height: 56 } views: base: - "ๅ / _ ภ ถ ุ ึ ค ต จ ข ช" - "ๆ ไ ำ พ ะ ั ี ร น ย บ ล" - "ฟ ห ก ด เ ้ ่ า ส ว ง ฃ" - "Shift_L ผ ป แ อ ิ ื ท ม ใ ฝ BackSpace" - "show_numbers preferences space period Return" upper: - "+ ๑ ๒ ๓ ๔ ู ฿ ๕ ๖ ๗ ๘ ๙" - "๐ \" ฎ ฑ ธ ํ ๊ ณ ฯ ญ ฐ ," - "ฤ ฆ ฏ โ ฌ ็ ๋ ษ ศ ซ . ฅ" - "Shift_L ( ) ฉ ฮ ฺ ์ ? ฒ ฬ ฦ BackSpace" - "show_numbers preferences space period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences spacesymbol period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences spacesymbol period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "กขค" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " spacesymbol: outline: "spacelinesymbol" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/ua.yaml000066400000000000000000000047251422304253700204730ustar00rootroot00000000000000--- outlines: default: { width: 32, height: 52 } altline: { width: 32, height: 52 } wide: { width: 57, height: 52 } narrow: { width: 26, height: 52 } spaceline: { width: 107, height: 52 } fill: { width: 159, height: 52 } special: { width: 42, height: 52 } views: base: - "й ц у к е н г ш щ з х" - "ф і в а п р о л д ж є" - "Shift_L я ч с м и т ь б ю BackSpace" - "show_numbers preferences ґ space ї period Return" upper: - "Й Ц У К Е Н Г Ш Щ З Х" - "Ф І В А П Р О Л Д Ж Є" - "Shift_L Я Ч С М И Т Ь Б Ю BackSpace" - "show_numbers preferences Ґ space Ї comma Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space_fill period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space_fill period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "wide" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "АБВ" show_symbols: action: set_view: "symbols" outline: "wide" label: "*/=" period: outline: "special" text: "." comma: outline: "special" text: "," space: outline: "spaceline" text: " " space_fill: outline: "fill" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" ґ: outline: "narrow" Ґ: outline: "narrow" ї: outline: "narrow" Ї: outline: "narrow" squeekboard-v1.17.1/data/keyboards/url/000077500000000000000000000000001422304253700177745ustar00rootroot00000000000000squeekboard-v1.17.1/data/keyboards/url/us.yaml000066400000000000000000000042421422304253700213110ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 106.67, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space slash period Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space slash period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space slash period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space slash period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." slash: outline: "special" text: "/" space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/us+colemak.yaml000066400000000000000000000041171422304253700221170ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "q w f p g j l u y" - "a r s t d h n e i o" - "Shift_L z x c v b k m BackSpace" - "show_numbers preferences space period Return" upper: - "Q W F P G J L U Y" - "A R S T D H N E I O" - "Shift_L Z X C V B K M BackSpace" - "show_numbers preferences space period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/us+colemak_wide.yaml000066400000000000000000000040671422304253700231330ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 108, height: 42 } spaceline: { width: 216, height: 42 } special: { width: 54, height: 42 } views: base: - "q w f p g j l u y" - "a r s t d h n e i o" - "Shift_L z x c v b k m BackSpace" - "show_numbers preferences space . Return" upper: - "Q W F P G J L U Y" - "A R S T D H N E I O" - "Shift_L Z X C V B K M BackSpace" - "show_numbers preferences space . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" ".": outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/us+dvorak.yaml000066400000000000000000000053511422304253700217730ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "Shift_L p y f g c r l BackSpace" - "a o e u i d h t n s" - ", q j k x b m w v z" - "show_numbers preferences space period Return" upper: - "Shift_L P Y F G C R L BackSpace" - "A O E U I D H T N S" - ", Q J K X B M W V Z" - "show_numbers preferences space period Return" numbers: - "show_symbols , \" ' colon ; ! ? BackSpace" - "* # $ / & - _ + ( )" - "1 2 3 4 5 6 7 8 9 0" - "show_letters preferences space period Return" symbols: - "show_numbers_from_symbols \\ % < > = [ ] BackSpace" - "© ® £ € ¥ ^ ° @ { }" - "~ ` | · √ π τ ÷ × ¶" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" # The US QWERTY layout has fewer letters on the third row, and so has # the shift & backspace keys placed there. In contrast, the US DVORAK # layout has fewer letters on the first row, which makes it a good # choice for the shift & backspace keys. That leads to what may be, # for many people, an unexpected layout in numbers mode: the numerals # are on the third row (not the first) so that the backspace key # remains in a consistent location regardless of mode, without # sacrificing key width. (Once could argue that in numbers mode, the # numerals should be closer to the enter key.) As with any keyboard # layout, familiarity comes with repeated use. squeekboard-v1.17.1/data/keyboards/us+dvorak_wide.yaml000066400000000000000000000053441422304253700230050ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 108, height: 42 } spaceline: { width: 216, height: 42 } special: { width: 54, height: 42 } views: base: - "Shift_L p y f g c r l BackSpace" - "a o e u i d h t n s" - ", q j k x b m w v z" - "show_numbers preferences space period Return" upper: - "Shift_L P Y F G C R L BackSpace" - "A O E U I D H T N S" - ", Q J K X B M W V Z" - "show_numbers preferences space period Return" numbers: - "show_symbols , \" ' colon ; ! ? BackSpace" - "* # $ / & - _ + ( )" - "1 2 3 4 5 6 7 8 9 0" - "show_letters preferences space period Return" symbols: - "show_numbers_from_symbols \\ % < > = [ ] BackSpace" - "© ® £ € ¥ ^ ° @ { }" - "~ ` | · √ π τ ÷ × ¶" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" # The US QWERTY layout has fewer letters on the third row, and so has # the shift & backspace keys placed there. In contrast, the US DVORAK # layout has fewer letters on the first row, which makes it a good # choice for the shift & backspace keys. That leads to what may be, # for many people, an unexpected layout in numbers mode: the numerals # are on the third row (not the first) so that the backspace key # remains in a consistent location regardless of mode, without # sacrificing key width. (Once could argue that in numbers mode, the # numerals should be closer to the enter key.) As with any keyboard # layout, familiarity comes with repeated use. squeekboard-v1.17.1/data/keyboards/us.yaml000066400000000000000000000041171422304253700205100ustar00rootroot00000000000000--- outlines: default: { width: 35.33, height: 52 } altline: { width: 52.67, height: 52 } wide: { width: 62, height: 52 } spaceline: { width: 142, height: 52 } special: { width: 44, height: 52 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space period Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space period Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space period Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space period Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: erase preferences: action: show_prefs outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" period: outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/keyboards/us_wide.yaml000066400000000000000000000040671422304253700215240ustar00rootroot00000000000000--- outlines: default: { width: 54, height: 42 } altline: { width: 81, height: 42 } wide: { width: 108, height: 42 } spaceline: { width: 216, height: 42 } special: { width: 54, height: 42 } views: base: - "q w e r t y u i o p" - "a s d f g h j k l" - "Shift_L z x c v b n m BackSpace" - "show_numbers preferences space . Return" upper: - "Q W E R T Y U I O P" - "A S D F G H J K L" - "Shift_L Z X C V B N M BackSpace" - "show_numbers preferences space . Return" numbers: - "1 2 3 4 5 6 7 8 9 0" - "@ # $ % & - _ + ( )" - "show_symbols , \" ' colon ; ! ? BackSpace" - "show_letters preferences space . Return" symbols: - "~ ` | · √ π τ ÷ × ¶" - "© ® £ € ¥ ^ ° * { }" - "show_numbers_from_symbols \\ / < > = [ ] BackSpace" - "show_letters preferences space . Return" buttons: Shift_L: action: locking: lock_view: "upper" unlock_view: "base" outline: "altline" icon: "key-shift" BackSpace: outline: "altline" icon: "edit-clear-symbolic" action: "erase" preferences: action: "show_prefs" outline: "special" icon: "keyboard-mode-symbolic" show_numbers: action: set_view: "numbers" outline: "wide" label: "123" show_numbers_from_symbols: action: set_view: "numbers" outline: "altline" label: "123" show_letters: action: set_view: "base" outline: "wide" label: "ABC" show_symbols: action: set_view: "symbols" outline: "altline" label: "*/=" ".": outline: "special" text: "." space: outline: "spaceline" text: " " Return: outline: "wide" icon: "key-enter" keysym: "Return" colon: text: ":" squeekboard-v1.17.1/data/meson.build000066400000000000000000000010541422304253700173510ustar00rootroot00000000000000gnome = import('gnome') squeekboard_resources = gnome.compile_resources( 'squeekboard-resources', 'squeekboard.gresources.xml', c_name: 'squeekboard', ) desktopconf = configuration_data() desktopconf.set('bindir', bindir) desktop_file = 'sm.puri.Squeekboard.desktop' i18n.merge_file( input: configure_file( input: desktop_file + '.in.in', output: desktop_file + '.in', configuration: desktopconf ), output: desktop_file, po_dir: '../po', install: true, install_dir: desktopdir, type: 'desktop' ) squeekboard-v1.17.1/data/popover.ui000066400000000000000000000014341422304253700172420ustar00rootroot00000000000000 Emoji layout emoji Terminal layout terminal
Keyboard Settings settings
squeekboard-v1.17.1/data/sm.puri.Squeekboard.desktop.in.in000066400000000000000000000003071422304253700234550ustar00rootroot00000000000000[Desktop Entry] Name=Squeekboard GenericName=On Screen Keyboard Comment=An on screen virtual keyboard Exec=@bindir@/squeekboard Terminal=false Type=Application NoDisplay=true Categories=GTK;Utility; squeekboard-v1.17.1/data/squeekboard.gresources.xml000066400000000000000000000007221422304253700224170ustar00rootroot00000000000000 common.css style.css style-Adwaita:dark.css popover.ui icons/key-enter.svg icons/key-shift.svg icons/keyboard-mode-symbolic.svg squeekboard-v1.17.1/data/style-Adwaita:dark.css000066400000000000000000000011101422304253700213560ustar00rootroot00000000000000/* Adwaita-dark style keyboard */ sq_view { background-color: rgba(0, 0, 0, 255); color: #ffffff; } sq_view sq_button { color: #deddda; background: #464448; } sq_button:active { background: #747077; } sq_button.altline, sq_button.special, sq_button.wide { background: #2b292f; } sq_button.latched { background: #ffffff; color: #2b292f; } sq_button.locked { background: #ffffff; color: #1c71d8; } #Return { background: #1c71d8; } #Return:active { background: #1c71d8; } @import url("resource:///sm/puri/squeekboard/common.css"); squeekboard-v1.17.1/data/style.css000066400000000000000000000020361422304253700170620ustar00rootroot00000000000000/* Keyboard style */ sq_view { background-color: mix(@theme_base_color, @theme_fg_color, 0.1); box-shadow:inset 0 1px 0 0 mix(@borders, @theme_base_color, 0.8); } sq_button { color: @theme_fg_color; background: alpha(@theme_fg_color, 0.07); box-shadow: 0 1px 0 0 rgba(0,0,0,0.2); } sq_button:active { background: alpha(@theme_fg_color, 0.11); } sq_button.altline, sq_button.special { background: alpha(@theme_fg_color, 0.15); } sq_button.altline:active, sq_button.special:active { background: alpha(@theme_fg_color, 0.2); } sq_button.latched { background: alpha(@theme_fg_color, 0.2); color: alpha(@theme_fg_color, 0.8); } sq_button.locked { background: alpha(@theme_fg_color, 0.5); color: @theme_base_color; } #Return { background: @theme_selected_bg_color; color: @theme_selected_fg_color; } #Return:active { background: mix(@theme_selected_bg_color, black, 0.2); color: mix(@theme_selected_fg_color, black, 0.2); } @import url("resource:///sm/puri/squeekboard/common.css"); squeekboard-v1.17.1/dco.txt000066400000000000000000000026171422304253700156120ustar00rootroot00000000000000Developer Certificate of Origin Version 1.1 Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 1 Letterman Drive Suite D4700 San Francisco, CA, 94129 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. squeekboard-v1.17.1/debian/000077500000000000000000000000001422304253700155205ustar00rootroot00000000000000squeekboard-v1.17.1/debian/cargo/000077500000000000000000000000001422304253700166135ustar00rootroot00000000000000squeekboard-v1.17.1/debian/cargo/config000066400000000000000000000006141422304253700200040ustar00rootroot00000000000000# When modifying this file, consider instead # to take advantage of the method that Cargo packagers use # to set up all the necessary stuff automatically: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=907629#30 [source.crates-io] registry = 'https://github.com/rust-lang/crates.io-index' replace-with = 'vendored-sources' [source.vendored-sources] directory = '/usr/share/cargo/registry' squeekboard-v1.17.1/debian/changelog000066400000000000000000000671061422304253700174040ustar00rootroot00000000000000squeekboard (1.17.1-1) experimental; urgency=medium [ Dorota Czaplejewicz ] * build: Replace missing crates.io dependency with Purism-hosted one * ci: Allow failure on sid * panel: Use scaling to set height [ William Wold ] * Do not reset pending state on zwp_input_method_v2.done [ Arnaud Ferraris ] * state: fix "wide mode" detection in portrait orientation -- Dorota Czaplejewicz Tue, 05 Apr 2022 13:32:53 +0000 squeekboard (1.17.0-1) experimental; urgency=medium [ Dorota Czaplejewicz ] * docs: Detail the release process better * cleanup: Remove unused header lines * docstrings: Clarify the purpose of Receiver * wayland: Move initialization to the Rust side * ffi: Remove unnecessary pointers to InputMethod * outputs: Clean up for more Rust usage * outputs: Notify the state manager about changes * outputs: Handle removal * Save outputs state * Store preferred output * deps: Vendor assert_matches * Carry output information on visible command all the way to C * Don't reach for globals to choose output * visibility: Forward panel height information to window creation * outputs: Remove ui manager * output: Use new source of panel height information * panel: Apply a hard limit of 1/2 height * cargo: Update lockfile [ Cosmin Humeniuc ] * Add Romanian layout [ Sam Hewitt ] * data: Update stylesheet with upstream design [ Tor ] * Make compatible with latest cargo deps [ Luís Fernando Stürmer da Rosa ] * Update Brazilian Portuguese translation [ Fran Dieguez ] * Add Galician translation [ William Wold ] * Check if dbus handler is null before using [ Yosef Or Boczko ] * Add Hebrew translation -- Dorota Czaplejewicz Tue, 25 Jan 2022 11:24:04 +0000 squeekboard (1.16.0-1) experimental; urgency=medium [ Dorota Czaplejewicz ] * build: Remove regex crate * ci: Use bookworm image * build: Pin transitive dependencies * cargo: Update Cargo.lock with pinned dependencies * CI: Use byzantium as the base * cargo: Bump dependencies [ Guido Günther ] * po: Fix ui file name * entry: Mark as executable * entry: Only activate purpose timer when focused * entry: Add another input hint * Add entry test using GTK4 [ Rafael Fontenelle ] * Add Brazilian Portuguese translation [ Yuri Chornoivan ] * Add Ukrainian translation [ Luna Jernberg ] * Add Swedish Translation * Update sv.po * Update LINGUAS [ Fabio Tomat ] * Add Friulian translation [ Daniel Șerbănescu ] * Add Romanian translation [ Matej Urbančič ] * Add Slovenian translation [ Nathan Follens ] * Add Dutch translation [ Jiri Grönroos ] * Add Finnish translation [ Danial Behzadi ] * Add Persian translation [ Jordi Mas i Hernandez ] * Add Catalan translation -- Dorota Czaplejewicz Tue, 25 Jan 2022 11:24:04 +0000 squeekboard (1.15.0-1) experimental; urgency=medium [ Khaled Eldoheiri ] * Introduce Arabic keyboard layout [ Dorota Czaplejewicz ] * Docs: Release procedure * build: Fix "any" dependency versioning * readme: Mention the layout guide * dbus: Hint that maybe squeekboard is running * readme: Change self-reference to repo to gnome * docs: Move env vars section to debugging * readme: Clarify basic running steps * readme: Put emphasis on being an input method * readme: Update features * ci: Use cached artifacts in the test * ci: Move release test to the start * ci: Start lintian test right after deb build * ci: Add git revision and CI pipeline number to .deb artifacts * ci: Use bookworm image * ci: Reformat yaml file * ci: Include pre-build style check * popover: Fix reentrancy problem * submission: Wrap the structure in a safe wrapper * util: Add ArcWrapped * animation: Prototype a way of handling state and applying it separately * state: Connect the animation state machine to the rest * event_loop: Separate and use for physical keyboard presence * Revert "util: Add ArcWrapped" * Revert "ci: Use bookworm image" * ci: Fix formatting * ci: Make indentation close to original again * cargo: version bump [ Jordi ] * Introduce Swiss French keyboard layout * improve accents layout behavior and code cleaning [ Plamen Stoev ] * Rename bg to bg+phonetic * Add 'bg' layout * Translate more layout names in Bulgarian [ William Wold ] * Show error when Layer Shell is not supported * Update entry.py file path in readme * Update zwp_text_input_v3 (comment changes only) * Update zwp_input_method_v2 [ Patrick Jörg ] * Introduce Swiss German keyboard layout * Introducing ch+de layout and modified ch.yaml fallback * Added ch_wide [ ZenWalker ] * layersurface: avoid duplicate assignment [ T. Zack Crawford ] * Update tutorial.md to clarify steps in creating a custom layout [ Guido Günther ] * gitlab-ci: Adjust CI tags * gitlab-ci: Drop build for outdated distributions * data: Fix build with meson 0.60.0 * main: Remove trailing whitespace * main: Honor --help and -h * eek-renderer: Add log domain * eek-renderer: Fix indentation * eek-renderer: Honor theme changes (Closes: #296) * main: Drop broken support G_BUS_TYPE_SYSTEM * main: Avoid two error variables in the same function * main: Use dark theme when run in a Phosh session (Closes: #242) * gtk-keyboard: Don't set variable to NULL twice in a row * renderer: Use `g_debug ()` * main: Add debug flag to always show squeekboard on start * renderer: Disconnect theme change signal handler * main: Add debug flag to show GTK inspector * README: Document SQUEEKBOARD_DEBUG environment variable * Move style-check to separate script * Honor input-purpose PIN * entry: Use a scrolled window * entry: Set a margin on the grids * entry: Add a random text entry field * imservice: Invoke eekboard_context_service_set_hint_purpose unconditionally (Closes: #311) * langs: Don't use empty translation file (Closes: #313) * Initialize gettext * Reuse the unused popover ui file for i18n (Closes: #315) * po: Add German translation * gresources: Drop popup.ui * Revert "gresources: Drop popup.ui" * gitlab-ci: Add PKG_ONLY * layout: Drop trailing whitespace * Use special pin keyboard * layout: Keep content purpose around * renderer: Set style class based on input purpose * pin: Use less margin * debian: Install translations * debian: Switch to dh 13 * debian: Install desktop file * eekboard-context-service: Don't translate property names * server-context-servide: Don't translate application name * data: Make generic name truly generic * po: Add desktop file to translatable files * Add URL and EMail keyboard variants for us (Closes: #65) * gitignore: Drop zanata dir * gitignore: Ignore generated po files * popover: Move Emoji and Terminal to ui file * popover: Add translator notes * popover: Make the ui file match the code file name * Remove emoji and terminal from translations * popover: Don't complain about missing translations * Drop custom translation handling * Drop locale_config * Remove custom translations [ PhilProg ] * Add documentation about compositors [ Norayr Chilingarian ] * armenian typewriter and phonetic keyboards. * armenian layout also added to meson.build etc. [ Arnaud Ferraris ] * resources: add wide FR terminal keyboard [ Sebastian Krzyszkowiak ] * renderer: Take context scale into account when drawing icons (Closes: #139) -- Dorota Czaplejewicz Sun, 19 Dec 2021 14:11:06 +0000 squeekboard (1.14.0pureos0~amber0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * data: Split into loading and parsing * layout: Remove unused code * build: Fix unnecessary shell quotes * popover: Allow spanning outside panel area * cargo: Update dependencies before release [ undef ] * Fix typos jp keyboard comments [ anteater ] * use the correct GtkStyleProviderPriority to indicate that the styles are provided by the application * remove some unnecessary unsafe code -- Dorota Czaplejewicz Sat, 15 May 2021 12:45:20 +0000 squeekboard (1.13.0pureos0~amber0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * layout: Latch keys when clicked twice * layout: Add stateless view switching * layout: Plug in stateless view switching * layout: Remove the little abomination of view change promise * view: Ąto-unlatching when multiple latching buttons pressed * renderer: Bring button drawing closer to Rust * ffi: Eliminate squeek_button and squeek_row * imservice: Increment serials on receiving done, not sending commit * input-method: Fix commit/done mixup in protocol text * CI: fix xheck_tag to be compatible with Amber * italian: Fix colon * popover: Fix prematurely deallocated CString * Rust: Remove unnecessary no_mangle statements to silence warnings * renderer: Reduce reliance on knowing the transform * renderer: Split mutable geometry and place it directly in GtkKeyboard * Revert "moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations." * layout: Make it possible to opt out of latching per-key * renderer: Mark latched buttons differently than locked * appearance: Colour latched/locked according to design * docs: Describe view switching * language-terminal: Place keyboards in a sub-path * layout selection: Fix emoji and number * rust: Fix compiler warnings * layout: Take into account text purpose again * layouts: Make selection testable * layouts: Stop assuming that layout name always changes on switch * Cargo: Version bump [ J.D. Laub ] * Add US Dvorak layout (and Colemak wide) * Add US Dvorak layout (and Colemak wide) [ Jordi Masip ] * Catalan keyboard layout [ Myth ] * Added hebrew keyboard layout [ David96 ] * Add Mod4 (Windows) key [ Panawat Wong-klaew ] * Add wide Thai keyboard layout [ Guido Günther ] * server-main: Add quit() * server-main: Properly register to gnome-session (Closes: #274) [ Kozova1 ] * Added Hebrew translations for most layouts. * moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations. * Fixed Hebrew layout. * moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations. [ M33 ] * Revert "Update tests/meson.build" -- Dorota Czaplejewicz Mon, 12 Apr 2021 10:40:32 +0000 squeekboard (1.12.0pureos0~amber0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * docs: Correct Cargo update instructions * visibility: Centralize keyboard panel visibility policy and handling * build: Fix release * tests: Prefer the env var for finding test layouts * tests: Explicitly pass source directory to tests * debian: Build reproducibly * tests: Allow legacy mode to have much longer tests. * build: Enable unused warnings in C * build: Enable wformat to remove warnings about missing wformat * build: Fail on any C warnings when strict * data: Made data flow in fallback clearer * data: Flattened layout fallback function * layouts: Use base as fallback for alternative layouts * layouts: Simplify the main flow of source list * tests: Add some description to the list of tested layouts * layout_names: Unmess the list of builtin layouts * dbus: Reset hints if text input missing * visibility: Stop calling GTK functions from the visibility manager [ Wannaphong Phatthiyaphaibun ] * Add thai keyboard * Update resources.rs * Update meson.build * escape " on thai keyboard [ clonex10100 ] * Added US Colemak Keyboard Layout [ Henry-Nicolas Tourneur ] * d/rules: fix an FTBFS on mips64el with GOT > 64kb * d/rules: export RUSTFLAGS only on architecture that needs it * d/rules: export RUSTFLAGS only on architecture that needs it [ Jiří Stránský ] * Add Czech keyboard layouts [ Stefan Grotz ] * Esperanto keyboard [ Vladimir ] * Bulgarian language keyboard layout [ Vladimir Stoilov ] * bulgarian add translation and to needed lists * Fix bulgarian layout size [ Andreas Rönnquist ] * no: Use wide button switching between numbers, symbols and base [ jranaraki ] * Farsi/Persian keyboard layout * Farsi/Persian keyboard layout * Added requirements to resources.rs and meson.build * Updated the layout to provide more convenient and faster typing experience -- Dorota Czaplejewicz Sun, 10 Jan 2021 09:43:42 +0000 squeekboard (1.11.1) amber-phone; urgency=medium [ Mark Müller ] * keyboard: Fix semicolon in German layout * keyboard: Move semicolon in German layout to numbers view replacing redundant comma key [ Dorota Czaplejewicz ] * imservice: Set up UI according to current needs when it shows up * UI: Keep visibility factors in a central place * cargo: Update deps -- Dorota Czaplejewicz Sat, 21 Nov 2020 11:08:06 +0000 squeekboard (1.11.0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * UI: Delay hiding only when leaving a text field * ui: Cancel hiding delay when activity requested again * Update dependencies [ Fabio Tomat ] * Update fur-IT.txt fix typo for Spanish -- Dorota Czaplejewicz Sat, 14 Nov 2020 06:46:28 +0000 squeekboard (1.10.0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * virtual_keyboard: Fix desynced modifiers state * rust: Fix deprecation warnings * docs: Tutorial syntax cleanups * docs: Reorganize tutorial * build: Error on repeating declarations * keymap: Generate from symbol map, not layout * data: Restore testability of action->keysym conversion * syntax: Let older rustc understand symbolmap's lifetime * debian: Insert a "breaks" for librem5-base < 24 * keymap: Keep keymap fd management in one place * vkeyboard: Use a generic slice instead of a vector * tests: Check for missing return in builtin layouts except emoji * keymap: Concentrate special handling of BackSpace, which is implicit in Erase action * keymaps: Use multiple key maps, each within the limit of what Xorg can accept. * build: Avoid MaybeUninit on older Debian * tests: Fix bad field access * cargo: Update dependencies [ Guido Günther ] * eekboard-context-service: Return early if schema is unavailable * treewide: Use new style function definitions * build: Enable '-Wold-style-definition' '-Wstrict-prototypes' * build: Enable '-Wunused-function' * eekboard-context-service: Drop EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE * keyboard: Fix warning * layout: Fix warning * gitlab-ci: Enable --Werror * eek-keyboard: Don't ignore return value * build: Enable -Winit-self * build: Enable -Wformat-security * build: Enable -Wmaybe-uninitialized * treewide: Drop redundant declarations * build: Enable -Wredundant-declarations * ServerContextService: Drop GObject boilerplate * build: Enable '-Wformat-nonliteral' * eekboad-context-service: Drop signal class handler * eekboard-context-service: Drop docstrings for inexistent functions * eekboard-context-service: Drop the GObject boilerplate * eekboard-context-service: Drop private struct * server-context-service: Consistenty name self argument 'self' * server-context-service: swap signal arguments * server-context-service: Don't show keyboard when disabled (Closes: #222) [ Nazarii Kretovych ] * Add Ukrainian keyboard layout. [ Benjamin Schaaf ] * Fix spelling mistakes in doc/hacking.md * Expand the development documentation in the readme * Expand key press detection to the edges of the view's bounding box * Sort layouts by type before sorting by name * Fix leak in level_keyboard_new * Fix leak endlessly adding a resource path to the default theme * Add settings option to popover [ Al ] * proposal for belgian layout (copy of fr) * alphabetical order for src/resources.rs tests/meson.build [ Arnaud Ferraris ] * eek-gtk-keyboard: use virtual resolution to check arrangement kind * server-context-service: optimize height calculation * keyboards: add wide French layout * keyboards: add wide Belgian layout * keyboards: add wide terminal layout [ Fabio Tomat ] * Revert "Add friulian keyboard" -- Dorota Czaplejewicz Mon, 19 Oct 2020 14:07:01 +0000 squeekboard (1.9.3) amber-phone; urgency=medium [ Björn Tantau ] * Show more useful keys at the same time. * Add Ctrl and Alt modifier keys. * Add missing Ê key. * Make f-keys slightly wider. * Add Menu key. [ Guido Günther ] * d/rules: Only remove Cargo.lock if it exists * eek: Drop libcanberra usage * debian: Build-depend on libfeedback * eek-gtk-keyboard: Trigger event feedback on button press (Closes: #166) [ Dorota Czaplejewicz ] * build: Add missing gio-unix dependency * build: Make compatible with Debian Bullseye * debian: Add amber to legacy distro list * ci: Add amber job * debian: Require lsb-release * size: Hardcode size to work around screen rotation * ci: Re-add x64 Buster build * italian: Fix space and period [ Sebastian Krzyszkowiak ] * Revert "Merge branch 'btantau-master-patch-76686' into 'master'" * Terminal layout: another approach [ Luís Fernando Stürmer da Rosa ] * Brazilian Portuguese Keyboard Layout. -- Sebastian Krzyszkowiak Wed, 05 Aug 2020 16:16:08 +0200 squeekboard (1.9.2) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * keyboard: Remove unused code * gsettings: Don't crash when unavailable * dbus: Don't crash if can't make a connection * gsettings: Don't crash on switching when unavailable * layout: Split out choice to a struct on its own * renderer: Simplify by dropping gobjectness * levelkeyboard: Rearrange to make future conversion easier * layout: Minor generalizations * Remove unused code * sizing: Create a standalone UI shape manager * sizing: Ignore scaling factor for layout selection * CI: Fix typo * Update rust deps for release [ Andreas Rönnquist ] * Swedish keyboard, wide button switching between numbers, symbols and base * More fixes of button sizes * Folder is doc, not docs [ uzanto ] * Add new file * Replace duplicated show_symbols by show_eschars and removed "Delete" button that it's doing nothing [ Arnaud Ferraris ] * keyboards: fr: fix keyboard layout * keyboards: fr: make sure the layout fits the screen * resources: include French keyboard layout * keyboards: fr: improve consistency with other layouts * keyboards: fr: improve diacritics layout * tests: add french layout [ Vlad ] * Fresh Russian layout [ Jordi Masip ] * Removed unused dependency 'libcroco' [ Florian Klink ] * sm.puri.Squeekboard.desktop: make path to Exec= absolute [ Ole Guldberg ] * Danish keyboard layout * Danish keyboard layout * add test for danish layout -- Dorota Czaplejewicz Mon, 01 Jun 2020 09:39:12 +0000 squeekboard (1.9.1) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * layout: Improve press handling * settings: Handle empty settings * Variant: Use proper pointer conversion between C and Rust * meta: Add doap file * modifiers: Support Control and Alt * CI: Test that any bump to changelog has a corresponding tag * docs: Add the guiding principle * hacking: Move into docs/ [ &t ] * Fix minor comment typos [ Dorota Czaplejewicz ] * cargo: Bump package versions before release -- Dorota Czaplejewicz Sun, 08 Mar 2020 10:04:29 +0000 squeekboard (1.9.0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * imservice: Add commit_string method * submission: Handle submitting strings * input_method: Use for erasing * logging: Use in merged functions * translations: Remove redundant ones * translations: Translate builtin layouts * greek: Rename to gr which is used by gnome settings [ Sebastian Krzyszkowiak ] * layouts: Add Polish layouts [ Dorota Czaplejewicz ] * locks: Draw based on current view * locking: Lock keys statelessly * layouts: Better accented uppercase in PL * emoji: Add more choices * row: Eliminate angle * layout: Center views relative to each other and the layout bounds * drawing: Generalized foreach_visible_button * variant: Fix double-free * variant: Fix leak * keyboard_layout: Fix leak * layout: Improve scoping of locked variable * terminal: Make */ easier to reach [ Sebastian Krzyszkowiak ] * layouts: terminal: Use altline outline for dot key [ Dorota Czaplejewicz ] * text input: Disable erasing * cargo: Update deps -- Dorota Czaplejewicz Wed, 19 Feb 2020 14:32:39 +0000 squeekboard (1.8.1) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * action: Rename Level to View * keyboard: Introduce a KeyCode type wrapping u32 * layout: Centralize handling key releases * layout: Make handling presses uniform * UI: Drop indirection for show/hide functions * managers: Move visible flag to UI manager * dbus_service: Remove unused function * dbus: Remove unneeded gobjectness * dbus: Rename handler from eekboard_service * context: Moved keymap setting together with its generation * key-emitter: Remove unused * eekboard_context_service: Drop unused enable property * services: Split out layout management from EekboardContextService * submission: Move away from virtual-keyboard * submission: Create a new wrapper over imservice * imservice: Limited scope of unsafe * EekGtkKeyboard: Use a direct reference to EekboardContext * submission: Take over virtual_keyboard handling * keyboard: Cleanups of unused code * levelkeyboard: Drop unused manager references * keyboard: Gather up keymap handling, drop layout * submission: Remove wildcard reexport * imservice: Rename commit_state to done to match protocol * ci: Clean up `..` before it's searched for artifacts * dbus: Log error on dbus exit * logging: Try to improve common operations * imservice: Return something more resembling an Error on failure * logging: Unified to remove random eprint calls * press_key: Use proper logging * number: Fix keysym for Return * build: Strip clap of optional features * layouts: Fix segfault on switching to wide * font: Use font from style context * font: Only pass relevant data to label renderer [ Sebastian Krzyszkowiak ] * layout: terminal: Swap positions of preferences and actions button * layout: terminal: Show actions button on all views * layout: terminal: Replace actions button with period on symbols view [ Dorota Czaplejewicz ] * setup: Connect ui to the state manager * debian: Add missing commas [ David Boddie ] * Tidy build file and docs * Use pip to install recommonmark -- Dorota Czaplejewicz Fri, 31 Jan 2020 09:59:12 +0000 squeekboard (1.8.0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * translations: Use gnome-desktop's xkb info database for layout names * translations: Make the code cleaner * overlay: Add terminal * eek-layout: Remove unused * pre-release: Update deps -- Dorota Czaplejewicz Tue, 14 Jan 2020 13:55:00 +0000 squeekboard (1.7.0) amber-phone; urgency=medium * New terminal layout appearing on terminal input hint -- Dorota Czaplejewicz Wed, 08 Jan 2020 11:53:07 +0000 squeekboard (1.7.0) amber-phone; urgency=medium * New terminal layout appearing on terminal input hint -- Dorota Czaplejewicz Wed, 08 Jan 2020 11:53:07 +0000 squeekboard (1.6.0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * tools: Move entry.py * build: Move building of squeekboard-test-layout to tools * packaging: Install entty.py as squeekboard-entry * Remove unused build dependencies * Remove unused header generator * logging: Move all facilities to one file * logging: Described the design * logging: Add described log levels * popover: Install emoji layout * popover: Show overlays as selected * Fix old Rust woes * emoji: Add a passable layout * Fix g_ and stdlib allocation/free mismatches -- Dorota Czaplejewicz Thu, 02 Jan 2020 12:02:50 +0000 squeekboard (1.5.0) amber-phone; urgency=medium [ Dorota Czaplejewicz ] * keycodes: Sort to eliminate runtime indeterminism * switcher: Switch layout on menu item click * Drop squeek_key * renderer: Remove some unneeded vars * renderer: Simplified outline rendering * renderer: Drop row from button rendering * renderer: Drop unused params * renderer: Simplify surface rendering * rendering: Simplify Cairo context usage, remove unneeded calls. * rendering: Remove unneeded redraw after button release * renderer: Remove unused locked key render function * renderer: Simply cut off when painting outside bounds * renderer: Render whole keyboard the same way as pressed buttons [ Mark Müller ] * layout: add German wide layout [ Dorota Czaplejewicz ] * renderer: Remove unused functions * cleanup: Remove references to squeek_view * cleanup: Unbox View and Row * cleanup: Remove unused single frame draw * positioning: Calculate sizes instead of storing, move position out of widgets * positioning: Clean up unused code * Fix old Rust woes [ Mark Müller ] * layout: add Japanese Kana wide layout [ Dorota Czaplejewicz ] * Entry test: Add Terminal input purpose * readme: Add note about Cargo dependencies * Create a library/UI module separation * hacking: Add DCO and licensing requirement * Fix internal .md link [ Mark Müller ] * squeekboard-test-layout: add argument parsing and some more output [ Dorota Czaplejewicz ] * Use clap in the lockfile * parsing: Remove bounds which weren't used anyway * layout: Respect margins * CI: Build arm64 .deb -- Dorota Czaplejewicz Mon, 23 Dec 2019 11:58:57 +0000 squeekboard (1.4.0) amber-phone; urgency=medium * "text" property in layouts * Adjusts to user's color scheme -- Dorota Czaplejewicz Mon, 02 Dec 2019 19:37:01 +0000 squeekboard (1.3.2) amber-phone; urgency=medium * Make sure all key presses get accepted by the compositor -- Dorota Czaplejewicz Tue, 26 Nov 2019 15:36:27 +0000 squeekboard (1.3.1) amber-phone; urgency=medium * Update and fix layouts and languages * Make tests less likely to fail -- Dorota Czaplejewicz Wed, 20 Nov 2019 22:10:48 +0000 squeekboard (1.3.0) amber-phone; urgency=medium * Language selection popup * Swedish and Finnish layouts -- Dorota Czaplejewicz Sat, 16 Nov 2019 15:38:14 +0000 squeekboard (1.2.2) amber-phone; urgency=medium * Landscape mode -- Dorota Czaplejewicz Wed, 30 Oct 2019 12:38:39 +0000 squeekboard (1.2.1) amber-phone; urgency=medium * Use different distribution -- Dorota Czaplejewicz Tue, 08 Oct 2019 10:56:10 +0000 squeekboard (1.2.0) unstable; urgency=medium * Use Cargo-based dependencies -- Dorota Czaplejewicz Tue, 24 Sep 2019 10:42:15 +0000 squeekboard (1.1.0) unstable; urgency=medium * Use new keyboard layout format -- Dorota Czaplejewicz Mon, 02 Sep 2019 10:12:02 +0000 squeekboard (1.0.10) unstable; urgency=medium * Use a shared DBus definition -- Dorota Czaplejewicz Tue, 02 Jul 2019 20:12:02 +0000 squeekboard (1.0.9) unstable; urgency=medium * Initial release. -- David Boddie Tue, 25 Jun 2019 19:33:00 +0200 squeekboard-v1.17.1/debian/check_release.py000077500000000000000000000006051422304253700206530ustar00rootroot00000000000000#!/usr/bin/env python3 """Checks tag before release. Feed it the first changelog line, and then all available tags. """ import re, sys version = re.findall("\\((.*)\\)", input())[0] tag = 'v' + re.findall("([0-9]+\\.[0-9]+\\.[0-9]+).*", version)[0] if tag not in map(str.strip, sys.stdin.readlines()): raise Exception("Changelog's current version doesn't have a tag. Push the tag!") squeekboard-v1.17.1/debian/control000066400000000000000000000026011422304253700171220ustar00rootroot00000000000000Source: squeekboard Section: x11 Priority: optional Maintainer: Dorota Czaplejewicz Build-Depends: cargo, debhelper-compat (= 13), meson (>=0.51.0), ninja-build, pkg-config, libglib2.0-dev, libgnome-desktop-3-dev, libgtk-3-dev, libfeedback-dev, librust-bitflags-1-dev (>= 1.0), librust-clap-2+default-dev (>= 2.32), librust-gio+v2-44-dev, librust-glib+v2-44-dev, librust-glib-sys-dev, librust-gtk+v3-22-dev (>= 0.5), librust-gtk-sys-dev, librust-maplit-1-dev (>= 1.0), librust-serde-derive-1-dev (>= 1.0), librust-serde-yaml-0.8-dev (>= 0.8), librust-xkbcommon-0.4+wayland-dev (>= 0.4), libwayland-dev (>= 1.16), lsb-release, python3, python3-ruamel.yaml, rustc, wayland-protocols (>= 1.14), Standards-Version: 4.1.3 Homepage: https://source.puri.sm/Librem5/squeekboard Package: squeekboard Architecture: linux-any Depends: # for the Adwaita-dark theme gnome-themes-extra-data, ${shlibs:Depends}, ${misc:Depends}, Breaks: librem5-base (<< 24), Description: On-screen keyboard for Wayland Virtual keyboard supporting Wayland, built primarily for the Librem 5 phone. Package: squeekboard-devel Architecture: linux-any Depends: python3, python3-gi, ${shlibs:Depends}, ${misc:Depends}, Description: Resources for making Squeekboard layouts Tools for creating and testing Squeekboard layouts: . * squeekboard-entry * squeekboard-test-layout squeekboard-v1.17.1/debian/control-newer000066400000000000000000000025651422304253700202510ustar00rootroot00000000000000Source: squeekboard Section: x11 Priority: optional Maintainer: Dorota Czaplejewicz Build-Depends: cargo, debhelper-compat (= 13), meson (>=0.51.0), ninja-build, pkg-config, libglib2.0-dev, libgnome-desktop-3-dev, libgtk-3-dev, libfeedback-dev, librust-bitflags-dev (>= 1.0), librust-clap-dev (>= 2.32), librust-gio+v2-58-dev, librust-glib+v2-58-dev, librust-glib-sys-dev, librust-gtk+v3-22-dev (>= 0.5), librust-gtk-sys-dev, librust-maplit-1-dev (>= 1.0), librust-serde-derive-1-dev (>= 1.0), librust-serde-yaml-0.8-dev (>= 0.8), librust-xkbcommon-0.4+wayland-dev (>= 0.4), libwayland-dev (>= 1.16), lsb-release, python3, python3-ruamel.yaml, rustc, wayland-protocols (>= 1.14), Standards-Version: 4.1.3 Homepage: https://source.puri.sm/Librem5/squeekboard Package: squeekboard Architecture: linux-any Depends: # for the Adwaita-dark theme gnome-themes-extra-data, ${shlibs:Depends}, ${misc:Depends}, Breaks: librem5-base (<< 24), Description: On-screen keyboard for Wayland Virtual keyboard supporting Wayland, built primarily for the Librem 5 phone. Package: squeekboard-devel Architecture: linux-any Depends: python3, python3-gi, ${shlibs:Depends}, ${misc:Depends}, Description: Resources for making Squeekboard layouts Tools for creating and testing Squeekboard layouts: . * squeekboard-entry * squeekboard-test-layout squeekboard-v1.17.1/debian/copyright000066400000000000000000000144311422304253700174560ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: squeekboard Source: https://source.puri.sm/Librem5/squeekboard Files: * Copyright: 2010-2011 Daiki Ueno 2010-2011 Red Hat, Inc. 2019 Purism SPC License: GPL-3+ Files: cargo.sh Copyright: 2019 Bart Ribbers 2019 Purism SPC License: GPL-3+ Files: data/style.css data/squeekboard.gresources.xml data/meson.build src/meson.build src/imservice.c Copyright: 2019 Purism SPC 2019 Squeekboard Contributors License: GPL-3+ Files: data/keyboards/de.yaml Copyright: 2019 Mark Müller License: GPL-3+ Files: data/keyboards/el.yaml Copyright: 2019 Antonis Tsolomitis 2019 Purism SPC License: GPL-3+ Files: data/keyboards/es.yaml Copyright: 2019 Purism SPC 2019 uzanto License: GPL-3+ Files: data/keyboards/fi.yaml Copyright: 2019 uzanto License: GPL-3+ Files: data/keyboards/it.yaml Copyright: 2019 Antonio Pandolfo 2019 Purism SPC License: GPL-3+ Files: data/keyboards/ja+kana.yaml Copyright: 2019 Mark Müller License: GPL-3+ Files: data/keyboards/se.yaml Copyright: 2019 Andreas Rönnquist 2019 Purism SPC License: GPL-3+ Files: eek/eek-layout.h eek/eek-layout.c eek/eek-element.c eek/eek-gtk-keyboard.c eek/eek-gtk-keyboard.h eek/eek.c eek/eek-xml-layout.h eek/eek-xml-layout.c eek/eek-renderer.h eek/eek-element.h eek/eek-renderer.c eekboard/eekboard-service.c eekboard/eekboard-service.h Copyright: 2010-2011 Daiki Ueno 2010-2011 Red Hat, Inc. 2018-2019 Purism SPC 2019 Squeekboard Contributors License: GPL-3+ Files: eek/eek-keyboard.c eek/eek-types.h eek/eek-types.c eek/eek-keyboard.h eek/eek.h src/server-main.c src/server-context-service.h Copyright: 2010-2011 Daiki Ueno 2010-2011 Red Hat, Inc. 2019 Purism SPC License: LGPL-2+ Files: eek/layersurface.c src/wayland.c src/key-emitter.c meson.build src/meson.build po/meson.build Copyright: 2018-2019 Purism SPC License: GPL-3+ Files: eekboard/keymap.c Copyright: 2000 Red Hat, Inc. 2019 Purism, SPC License: LGPL-2+ Files: eekboard/eekboard-context-service.c Copyright: 2010-2011 Daiki Ueno 2010-2011 Red Hat, Inc. 2019 Purism, SPC 2019 David Heidelberg 2019 Piotr Tworek 2019 Squeekboard Contributors License: GPL-3+ Files: eekboard/eekboard-context-service.h Copyright: 2010-2011 Daiki Ueno 2010-2011 Red Hat, Inc. License: GPL-3+ Files: po/POTFILES.skip po/LINGUAS po/ja.po po/POTFILES.in Copyright: 2010-2011 Daiki Ueno License: LGPL-2+ Comment: Only the po/ja.po file contains a license, but these are all grouped together. Files: protocols/wlr-layer-shell-unstable-v1.xml Copyright: 2017 Drew DeVault License: X11 Files: src/resources.rs Copyright: 2019 Andreas Rönnquist 2019 Mark Müller 2019 Purism SPC License: GPL-3+ Files: src/server-context-service.c Copyright: 2010-2011 Daiki Ueno 2010-2011 Red Hat, Inc. 2019 Purism SPC 2019 Squeekboard Contributors License: GPL-3+ Files: tests/meson.build Copyright: 2019 Purism SPC 2019 Mark Müller License: GPL-3+ License: GPL-3+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. . This package 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 General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . On Debian systems, the complete text of the GNU General Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". License: LGPL-2+ 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 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, see . License: X11 Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the copyright holders not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. The copyright holders make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. . THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. squeekboard-v1.17.1/debian/rules000077500000000000000000000024071422304253700166030ustar00rootroot00000000000000#!/usr/bin/make -f export CARGO_HOME = $(CURDIR)/debian/cargo export DEB_BUILD_MAINT_OPTIONS = hardening=+all # the below avoids an FTBFS on mips64el with a GOT > 64kb DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) ifeq ($(DEB_HOST_ARCH),mips64el) export RUSTFLAGS = -Ctarget-feature=+xgot endif # the below avoids an FTBFS on mips64el with a GOT > 64kb DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) ifeq ($(DEB_HOST_ARCH),mips64el) xgot = -Ctarget-feature=+xgot else xgot = endif # Don't use paths that may change between builds. # No need to care about $HOME # because Cargo will not place any source in ~/.cargo. # The build directory is a subdirectory of the source directory, # so it doesn't need to be explicitly taken care of. export RUSTFLAGS = --remap-path-prefix=$(CURDIR)=/remap-pwd $(xgot) distrel := $(shell lsb_release --codename --short) ifneq (,$(filter $(distrel),sid)) newer = true else newer = false endif %: dh $@ --builddirectory=_build --buildsystem=meson # The Debian version of linked-hash-map doesn't provide any hash, # causing Cargo to refuse to build with a crates.io copy override_dh_auto_configure: [ ! -f Cargo.lock ] || rm Cargo.lock dh_auto_configure -- -Dnewer=$(newer) -Donline=false override_dh_autoreconf: squeekboard-v1.17.1/debian/source/000077500000000000000000000000001422304253700170205ustar00rootroot00000000000000squeekboard-v1.17.1/debian/source/format000066400000000000000000000000151422304253700202270ustar00rootroot000000000000003.0 (native) squeekboard-v1.17.1/debian/squeekboard-devel.install000066400000000000000000000001141422304253700225060ustar00rootroot00000000000000usr/bin/squeekboard-test-layout /usr/bin usr/bin/squeekboard-entry /usr/bin squeekboard-v1.17.1/debian/squeekboard.install000066400000000000000000000001521422304253700214130ustar00rootroot00000000000000tools/squeekboard-restyled usr/bin usr/bin/squeekboard /usr/bin usr/share/applications/ usr/share/locale/ squeekboard-v1.17.1/debian/squeekboard.lintian-overrides000066400000000000000000000002711422304253700234050ustar00rootroot00000000000000# yaml-rust 0.4.3 shares some roots with libyaml, including the string which lintian checks, creating a false positive squeekboard binary: embedded-library usr/bin/squeekboard: libyaml squeekboard-v1.17.1/doc/000077500000000000000000000000001422304253700150435ustar00rootroot00000000000000squeekboard-v1.17.1/doc/build.sh000077500000000000000000000006231422304253700165020ustar00rootroot00000000000000#!/bin/sh # Builds the documentation and places in the selected directory, # or the working directory. set -e SCRIPT_PATH="$(realpath "$0")" DOCS_DIR="$(dirname "$SCRIPT_PATH")" TARGET_DIR="${1:-./}" SPHINX=sphinx-build if [ ! -d $DOCS_DIR/_static ]; then mkdir -p $DOCS_DIR/_static fi if ! which sphinx-build ; then SPHINX=sphinx-build-3 fi $SPHINX -b html "${DOCS_DIR}" "${TARGET_DIR}" squeekboard-v1.17.1/doc/conf.py000066400000000000000000000116221422304253700163440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Configuration file for the Sphinx documentation builder. # # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) # -- Project information ----------------------------------------------------- project = 'squeekboard' copyright = 'Squeekboard contributors' author = 'Dorota Czaplejewicz' # The short X.Y version version = '' # The full version, including alpha/beta/rc tags release = '' # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'recommonmark' ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.md' # The master toctree document. master_doc = 'index' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path . exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'alabaster' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. # # The default sidebars (for documents that don't match any pattern) are # defined by theme itself. Builtin themes are using these templates by # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', # 'searchbox.html']``. # # html_sidebars = {} # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = 'squeekboarddoc' # -- Options for LaTeX output ------------------------------------------------ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'squeekboard.tex', 'squeekboard Documentation', 'Dorota Czaplejewicz', 'manual'), ] # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'squeekboard', 'squeekboard Documentation', [author], 1) ] # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'squeekboard', 'squeekboard Documentation', author, 'squeekboard', 'One line description of project.', 'Miscellaneous'), ] from recommonmark.transform import AutoStructify def setup(app): app.add_config_value('recommonmark_config', { 'enable_auto_toc_tree': True, 'auto_toc_tree_section': 'Contents', }, True) app.add_transform(AutoStructify) squeekboard-v1.17.1/doc/hacking.md000066400000000000000000000226121422304253700167740ustar00rootroot00000000000000Hacking ======= This document describes the standards for modifying and maintaining the *squeekboard* project. Principles ---------- The project was built upon some guiding principles, which should be respected primarily by the maintainers, but also by contributors to avoid needlessly rejected changes. The overarching principle of *squeekboard* is to empower users. Software is primarily meant to solve problems of its users. Often in the quest to make software better, a hard distinction is made between the developer, who becomes the creator, and the user, who takes the role of the consumer, without direct influence on the software they use. This project aims to give users the power to make the software work for them by blurring the lines between users and developers. Notwithstanding its current state, *squeekboard* must be structured in a way that provides users a gradual way to gain more experience and power to adjust it. It must be easy, in order of importance: - to use the software, - to modify its resources, - to change its behavior, - to contribute upstream. To give an idea of what it means in practice, those are some examples of what has been important for *squeekboard* so far: - being quick and usable, - allowing local overrides of resources and config, - storing resources and config as editable, standard files, - having complete, up to date documentation of interfaces, - having an easy process of sending contributions, - adapting to to user's settings and constrains without overriding them, - avoiding compiling whenever possible, - making it easy to build, - having code that is [simple and obvious](https://www.python.org/dev/peps/pep-0020/), - having an easy process of testing and accepting contributions. You may notice that they are ordered roughly from "user-focused" to "maintainer-focused". While good properties are desired, sometimes they conflict, and maintainers should give additional weight to those benefiting the user compared to those benefiting regular contributors. Sending patches --------------- By submitting a change to this project, you agree to license it under the [GPL license version 3](https://source.puri.sm/Librem5/squeekboard/blob/master/COPYING), or any later version. You also certify that your contribution fulfills the [Developer's Certificate of Origin 1.1](https://source.puri.sm/Librem5/squeekboard/blob/master/dco.txt). Development environment ----------------------- *Squeekboard* is regularly built and tested on [the development environment](https://developer.puri.sm/Librem5/Development_Environment.html). Recent Fedora releases are likely to be tested as well. ### Dependencies On a Debian based system run ```sh sudo apt-get -y install build-essential sudo apt-get -y build-dep . ``` For an explicit list of dependencies check the `Build-Depends` entry in the [`debian/control`](https://source.puri.sm/Librem5/squeekboard/blob/master/debian/control) file. Testing ------- Most common testing is done in CI. Occasionally, and for each release, do perform manual tests to make sure that - the application draws correctly - it shows when relevant - it changes layouts - it changes views Testing with an application: ``` python3 tools/entry.py ``` Testing visibility: ``` $ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true $ busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b false ``` Testing layouts: Layouts can be selected using the GNOME Settings application. ``` # define all available layouts. First one is currently selected. $ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us'), ('xkb', 'de')]" ``` ### Environment Variables Besides the environment variables supported by GTK and [GLib](https://docs.gtk.org/glib/running.html) applications squeekboard honors the `SQUEEKBOARD_DEBUG` environment variable which can contain a comma separated list of: - `force-show` : Show squeekboard on startup independent of any gsettings or compositor requests - `gtk-inspector`: Spawn [gtk-inspector](https://wiki.gnome.org/Projects/GTK/Inspector) Coding ------ ### Project structure Rust modules should be split into 2 categories: libraries, and user interface. They differ in the way they do error handling. Libraries should: - not panic due to external surprises, only due to internal inconsistencies - pass errors and surprises they can't handle to the callers instead - not silence errors and surprises User interface modules should: - try to provide safe values whenever they encounter an error - do the logging - give libraries the ability to report errors and surprises (e.g. via giving them loggers) ### Style Note that some portions, like the .gitlab-ci.yml file have accummulated enough style/whitespace conflicts that an enforced style checker is now applied. To fix your contributions before submitting a change, use: ``` ./tools/style-check_source --apply ``` * * * Code submitted should roughly match the style of surrounding code. Things that will *not* be accepted are ones that often lead to errors: - skipping brackets `{}` after every `if()`, `else`, and similar ([SCI CERT C: EXP19-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP19-C.+Use+braces+for+the+body+of+an+if%2C+for%2C+or+while+statement)) Bad example: ``` if (foo) bar(); ``` Good example: ``` if (foo) { bar(); } ``` - mixing tabs and spaces in the same block of code (or config) Strongly encouraged: - don't make lines too long. If it's longer than ~80 characters, it's probably unreadable already, and the code needs to be clarified; - put operators in the beginning of a continuation line Bad example: ``` foobar = verylongexpression + anotherverylongexpression + yetanotherexpression; ``` Good example: ``` foobar = verylongexpression + anotherverylongexpression + yetanotherexpression; ``` - use `///` for documentation comments in front of definitions and `/*! ... */` for documentation comments in the beginning of modules (see [Rust doc-comments](https://doc.rust-lang.org/reference/comments.html#doc-comments)) If in doubt, check [PEP8](https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/guide.md), the [kernel coding style](https://www.kernel.org/doc/html/v4.10/process/coding-style.html), or the [Rust style guide](https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/guide.md). Maintenance ----------- Squeekboard uses Rust & Cargo for some of its dependencies. Use the `cargo.sh` script for maintaining the Cargo part of the build. The script takes the usual Cargo commands, after the first 2 positional arguments: source directory, and output artifact. So, `cargo test` becomes: ``` cd build_dir sh /source_path/cargo.sh test ``` ### Cargo dependencies All Cargo dependencies must be selected in the version available in PureOS, and added to the file `debian/control`. Please check with https://software.pureos.net/search_pkg?term=librust . Dependencies must be specified in `Cargo.toml` with 2 numbers: "major.minor". Since bugfix version number is meant to not affect the interface, this allows for safe updates. Releases ---------- Squeekboard should get a new release every time something interesting comes in. Preferably when there are no known bugs too. People will rely on theose releases, after all. ### 1. Update `Cargo.toml`. While the file is not actually used, it's a good idea to save the config in case some rare bug appears in dependencies. ``` cd squeekboard-build .../squeekboard-source/cargo.sh update ninja test cp ./Cargo.lock .../squeekboard-source ``` Then commit the updated `Cargo.lock`. ### 2. Choose the version number Squeekboard tries to use semantic versioning. It's 3 numbers separated by dots: "a.b.c". Releases which only fix bugs and nothing else are "a.b.c+1". Releases which add user-visible features in addition to bug fixes are "a.b+1.0". Releases which, in addition to the previous, change *the user contract* in incompatible ways are "a+1.0.0". "The user contract" means plugin APIs that are deemed stable, or the way language switching works, etc. In other words, incompatible changes to developers, or big changes to users bump "a" to the next natural number. ### 3. Update the number in `meson.build` It's in the `project(version: xxx)` statement. ### 4. Update packaging Packaging is in the `debian/` directory, and creates builds that can be quickly tested. ``` cd squeekboard-source gbp dch --multimaint-merge --ignore-branch ``` Inspect `debian/changelog`, and make sure the first line contains the correct version number and suite. For example: ``` squeekboard (1.13.0pureos0~amber0) amber-phone; urgency=medium ``` Commit the updated `debian/changelog`. The commit message should contain the release version and a description of changes. > Release 1.13.0 "Externality" > > Changes: > > - A system for latching and locking views > ... ### 5. Create a signed tag for downstreams The tag should be the version number with "v" in front of it. The tag message should be "squeekboard" and the tag name. Push it to the upstream repository: ``` git tag -s -u my_address@example.com v1.13.0 -m "squeekboard v1.13.0" git push v1.13.0 ``` ### 5. Create a signed tag for packaging Similar to the above, but format it for the PureOS downstream. ``` git tag -s -u my_address@example.com 'pureos/1.13.0pureos0_amber0' -m 'squeekboard 1.13.0pureos0_amber0' git push 'pureos/1.13.0pureos0_amber0' ``` ### 6. Rejoice You released a new version of Squeekboard, and made it available on PureOS. Congratulations. squeekboard-v1.17.1/doc/index.md000066400000000000000000000016141422304253700164760ustar00rootroot00000000000000Welcome to squeekboard's documentation! ======================================= Contents -------- * [Tutorial](tutorial.md) * [Contributing](hacking.md) * [Switching views](views.md) Introduction ------------ Squeekboard is the on-screen keyboard for the Librem 5 phone. For information about building, look at the [README](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md). Layouts ------- Squeekboard allows user-provided keyboard layouts. They can be created without recompiling the keyboard code. The [tutorial](tutorial.md) explains the process in detail. Layouts are created using a text-based format, based on YAML. TODO: Provide a description of the format. Squeekboard layouts are separated into *views* and use a *room metaphor* to [switch views](views.md). Contributions ------------- Anyone is free to modify *squeekboard*. See the [contributing document](hacking.md). squeekboard-v1.17.1/doc/latching.svg000066400000000000000000000627371422304253700173740ustar00rootroot00000000000000 image/svg+xml A a Ą  ̨̂ ̈ locking SAVED CURRENT locking squeekboard-v1.17.1/doc/latching_return.svg000066400000000000000000001153011422304253700207550ustar00rootroot00000000000000 image/svg+xml cuts Ą locking  ̨̂ ̈ SAVED CURRENT set_view lockingpops: false ą Ą text returns a A cuts cuts squeekboard-v1.17.1/doc/switching.svg000066400000000000000000000370741422304253700175760ustar00rootroot00000000000000 image/svg+xml a A ą Ą set_view: upper lockinglock_view: upperunlock_view: lower squeekboard-v1.17.1/doc/tutorial.md000066400000000000000000000144261422304253700172370ustar00rootroot00000000000000A guide to creating layouts =========================== This guide is based on the original Kareema's [forum post](https://forums.puri.sm/t/translations-and-virtual-touch-keyboards-tracking-localization/7669/48). It’s long overdue to write a comprehensive guide how to add a keyboard layout from start. But unfortunately, I don’t have much time left ATM. A lot of information can be found in [this](https://forums.puri.sm/t/using-non-latin-language-on-librem-5/7103/5) thread. So at least I will try to start writing a short how-to here and edit this post as I find the time. Hope this helps a bit - comments and corrections [welcome](https://source.puri.sm/Librem5/squeekboard/-/merge_requests/) ## Creating a new layout Creating a layout is easy. You don't need to recompile things, just edit and test. It's easiest to start with an existing layout. ### Get one of the existing keyboard layouts * You can get one of the keyboards from the squeekboard git repository : [https://source.puri.sm/Librem5/squeekboard](https://source.puri.sm/Librem5/squeekboard) * The keyboard layouts are located in the subdirectory [`data/keyboards/`](https://source.puri.sm/Librem5/squeekboard/-/tree/master/data/keyboards) in the `.yaml` files * Take a look and try to understand them :slight_smile: ### Creating the keyboard layout * To be written: For the time being, take a look at [Using non-latin language on Librem 5](https://forums.puri.sm/t/using-non-latin-language-on-librem-5/7103/5) * Select and enable the input source you would like to change from the Region & Language section of the device settings. Perhaps use "A user-defined custom layout" listed under Other. * Find the correct name of the .yaml file associated with that input source. This can be found with the command ``` gsettings get org.gnome.desktop.input-sources sources ``` The output should be something like this: `[('xkb', 'us'), ('xkb', 'de')]` So for example “de.yaml” would be the correct name for the German keyboard layout. If the name of your layout is not translated correctly in the list, you can fix it by adding it and recompiling Squeekboard. There is also associated files for that layout in landscape, terminal, number, emoji mode. They can be found at something analogous to `us_wide.yaml`, `terminal/us.yaml`, `number/us.yaml`, `emoji/us.yaml`, respectively. ### Testing the layout Copy your yaml file to `~/.local/share/squeekboard/keyboards/` for testing purposes. From there it should get picked up by squeekboard automatically. The yaml file will overwrite the default settings for that layout. If you want to go back to default, simply remove the file. You can also use the `test_layout` tool from the -devel package to check it for errors: ``` # squeekboard_test_layout ./mylayout.yaml Test result: OK ``` ## Contributing your changes If you want to share your layout with the world, the best way is to submit it to the Squeekboard project. The workflow is similar to any other Gitlab-based project. Above all, your layout should be working, be tested, not break anything, and make sense. ### Fork your own copy of squeekboard * Best way would be to start with a fork of the squeekboard repository: Create a user account at https://source.puri.sm/, go the the squeekboard git repository, press “Fork” in the web interface. You can find further instructions [here](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html#creating-a-fork). * Clone your fork locally with `git clone` and use the uri of your forked repo there ### Edit your keyboard and get it merged * It may be useful to check out the [generic guide how the workflow to contribute works](https://developer.puri.sm/Librem5/Contact/Contributing.html) * Create a branch: Name it “keyboard-layout-mylanguage” or whatever * Checkout your branch, edit your keyboard layout and commit your changes * Your layout **must** be correctly named, and in `data/keyboards/`. * Your layout **must** pass the `test_layout` tool with zero problems. * Your translation **must** be correctly named, and in `data/langs/`. * Your layout or translation **must** be added to automatic tests. **Don’t forget to add it** to `src/resources.rs` and the layout to `tests/meson.build` (that’s for me, because I always forget it). ### Get it merged It's always recommended to **compile and run** squeekboard before submitting your changes. This serves as a test that all is working. See instructions in the [compiling section](#compiling-and-running-squeekboard). * Push the local changes (to the branch of your fork of squeekboard) * Create a merge request for the branch to get your changes merged to the official squeekboard git repository If your changes pass automated tests (CI), then the merge request will be reviewed by the maintainers, and you might be asked to change a thing or two. ## Compiling and running Squeekboard If you want your change to become part of official Squeekboard, or if you want to add a translation of your layout name, you will have to recompile Squeekboard and test your changes there. ### Compile squeekboard * Follow the instructions found in “Building” section of the squeekboard’s README: Running squeekboard: [https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#building](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#building) ### Run squeekboard * Follow these instructions to run squeekboard: [https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#running](https://source.puri.sm/Librem5/squeekboard/blob/master/README.md#running) * Additionally take a look at the contribution document for [testing info](HACKING.md#testing) * You can either test it locally on your Linux system or use the [QEMU Librem 5 image](https://developer.puri.sm/Librem5/Development_Environment/Boards/emulators.html) * To test squeekboard locally, you need phoc. Either compile that from the sources as well or use the CI repository ci.puri.sm for Debian based systems: `deb [arch=amd64] http://ci.puri.sm/ scratch librem5` Squeekboard can be installed from there as a Debian package, too (that’s what I often do). But beware - there be dragons! You could bork your system with these packages and you should probably disable this repository again after installing what you need - these packages are not meant for production systems (or so I heard :wink: ) squeekboard-v1.17.1/doc/views.md000066400000000000000000000133311422304253700165230ustar00rootroot00000000000000Switching views ========= Squeekboard layout files are separated into *views*. What are views? ------------------- A view is the button arrangement which you see on Squeekboard's panel. The view always spans the entire panel area, so it's not possible to see two views at the same time, even if the layout contains multiple views. Views are useful because they allow to have many more buttons than would fit on the panel at the same time. That works because views can be switched. Views are different from layouts: they can be switched without affecting the active language, and without touching the globe button. Layouts cannot share views, so switching layouts *always* switches views. Switching views ------------------ The model selected for switching views is less similar to "levels" known from physical keyboards, but closer to "rooms", which may resemble a game map. Buttons don't have states. It's more of a model where each view is a room, and buttons are doors. Switching means moving to the next room, and buttons highlight according to which view/room they lead to or from. There are two basic kinds of switching buttons: one way (`set_view`), and two way (`locking`). `locking` is the more sophisticated one. When placed inside `lock_view`, it is drawn highlighted, and goes to `unlock view`. When placed inside any other view, it behaves like `set_view`. ![Diagram showing two transitions: from lowercase via `set_view` to uppercase, and back via `locking`](switching.svg) This diagram shows which buttons can switch between two views. Views are shown as circles, and buttons as rounded rectangles. The two buttons are separate, and visible only in the view *from which the switch starts*. Note that the `locking` button is shown highlighted. That's because it's in `upper` view, which matches its `lock_view`. Latching ---------- `locking` buttons provide a second mode of operation: latching. It's useful when the target view is needed only for a single button press, like entering a single accent or a single capital letter in Latin scripts. When a latching button is pressed, the keyboard remembers to come back to the current (source) view, and then the view is switched. If another `locking` button is pressed, the source view stays in memory. If a text button is pressed, the view from memory is shown again, and forgotten. ![Diagram showing the switches needed to travel across 3 views: a→A→Ą, while latching.](latching.svg) In this diagram, the dashed line connects the view the typist is seeing to the view remembered for unlatching. There are two ways to erase the memory without going back to the remembered view. Pressing the button again will permanently switch to the current view, and `set_view` will permanently switch to its target. In the room metaphor, it's as if tying a thread inside the room before going through the door to the next one. And another `locking` door while holding the thread. Once the Minotaur is slain (text button pressed), the hero follows the thread back to the starting room. The typist hero cuts the thread in two circumstances: when staying longer in the current room (press button again), or when moving through a `set_view` door. ![Diagram showing possible ways to stop latching, by staying in Ą, by unlatching back to a, and by moving on to ą view.](latching_return.svg) This diagram shows the possible ways to stop latching. One is by pressing a text button, which takes back to the original view. Another is pressing a locking button which appears highlighted (note that it can be any button, what matters is its `lock_view`). Finally, switching to another view using a button that doesn't keep the latch on forgets latching. The layout author should pay attention that `set_view`'s lack of latching does not come as a surprise to typists. Differences from keyboard levels --------------------------------------- Views are **not** like keyboard levels. On a physical keyboard, the number of buttons can not change when switching levels. In Squeekboard, they can have any arrangement of buttons you could imagine. When switching levels on a keyboard, for example by pressing Shift, the key press not only affects the meaning of other keys, but also tells the application that it's pressed down. In Squeekboard, pressing buttons to change layouts *does not* do anything but switch the layout. Pressing the switching button especially *does not* tell the application that it was pressed. (This is the reason Shift and AltGr modifiers are not implemented in Squeekboard.) Why not use the "views" model? ------------------------------------- Squeekboard's goal is to support as many scripts as possible, and the author of the initial design doesn't know a whole lot. There are two problems with using the levels metaphor: Firstly, the levels model assumes that there is a "base" and an "active" level. This does not work well with scripts that have different but equivalent modes of writing. An example is the Kana layout with Katakana and Hiragana, which are both "base". Both systems could have been combined, but the view switching designer doesn't have enough experience with different scripts to do that. Some scripts may have different non-hierarchical ways to switch character groups (Balinese?), which could make combining hierarchy with free-form switching even harder. Secondly, when dealing with languages with a hierarchy, we end up with extra work to eliminate nonsensical combinations. With "symbols" and "uppercase" levels, what does it mean to have both engaged? Eliminating that means extra work. Either validating layouts, so that it's not possible to engage "uppercase" from "symbols", or duplicating, so that "uppercase+symbols" is the same as just "symbols". With "accents" in the mix, this could become a challenge to design well. squeekboard-v1.17.1/eek/000077500000000000000000000000001422304253700150425ustar00rootroot00000000000000squeekboard-v1.17.1/eek/eek-element.c000066400000000000000000000107701422304253700174060ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ /** * SECTION:eek-element * @short_description: Base class of a keyboard element * * The #EekElementClass class represents a keyboard element, which * shall be used to implement #EekKeyboard, #EekSection, or #EekKey. */ #include "config.h" #include #include "eek-element.h" enum { PROP_0, PROP_BOUNDS, PROP_LAST }; typedef struct _EekElementPrivate { EekBounds bounds; } EekElementPrivate; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekElement, eek_element, G_TYPE_OBJECT) static void eek_element_finalize (GObject *object) { G_OBJECT_CLASS (eek_element_parent_class)->finalize (object); } static void eek_element_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { EekElement *element = EEK_ELEMENT(object); switch (prop_id) { case PROP_BOUNDS: eek_element_set_bounds (element, g_value_get_boxed (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eek_element_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { EekElement *element = EEK_ELEMENT(object); EekBounds bounds; switch (prop_id) { case PROP_BOUNDS: eek_element_get_bounds (element, &bounds); g_value_set_boxed (value, &bounds); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eek_element_class_init (EekElementClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; /* signals */ gobject_class->set_property = eek_element_set_property; gobject_class->get_property = eek_element_get_property; gobject_class->finalize = eek_element_finalize; /** * EekElement:bounds: * * The bounding box of #EekElement. */ pspec = g_param_spec_boxed ("bounds", "Bounds", "Bounding box of the element", EEK_TYPE_BOUNDS, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_BOUNDS, pspec); } static void eek_element_init (EekElement *self) { (void)self; } /** * eek_element_set_bounds: * @element: an #EekElement * @bounds: bounding box of @element * * Set the bounding box of @element to @bounds. Note that if @element * has parent, X and Y positions of @bounds are relative to the parent * position. */ void eek_element_set_bounds (EekElement *element, EekBounds *bounds) { g_return_if_fail (EEK_IS_ELEMENT(element)); EekElementPrivate *priv = eek_element_get_instance_private (element); memcpy (&priv->bounds, bounds, sizeof(EekBounds)); } /** * eek_element_get_bounds: * @element: an #EekElement * @bounds: (out): pointer where bounding box of @element will be stored * * Get the bounding box of @element. Note that if @element has * parent, position of @bounds are relative to the parent. To obtain * the absolute position, use eek_element_get_absolute_position(). */ void eek_element_get_bounds (EekElement *element, EekBounds *bounds) { g_return_if_fail (EEK_IS_ELEMENT(element)); g_return_if_fail (bounds != NULL); EekElementPrivate *priv = eek_element_get_instance_private (element); memcpy (bounds, &priv->bounds, sizeof(EekBounds)); } squeekboard-v1.17.1/eek/eek-element.h000066400000000000000000000034371422304253700174150ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ #if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION) #error "Only can be included directly." #endif #ifndef EEK_ELEMENT_H #define EEK_ELEMENT_H 1 #include #include "eek-types.h" G_BEGIN_DECLS #define EEK_TYPE_ELEMENT (eek_element_get_type()) G_DECLARE_DERIVABLE_TYPE (EekElement, eek_element, EEK, ELEMENT, GObject) struct _EekElementClass { /*< private >*/ GObjectClass parent_class; }; void eek_element_set_name (EekElement *element, const gchar *name); const gchar *eek_element_get_name (EekElement *element); void eek_element_set_bounds (EekElement *element, EekBounds *bounds); void eek_element_get_bounds (EekElement *element, EekBounds *bounds); G_END_DECLS #endif /* EEK_ELEMENT_H */ squeekboard-v1.17.1/eek/eek-gtk-keyboard.c000066400000000000000000000357551422304253700203520ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ /** * SECTION:eek-gtk-keyboard * @short_description: a #GtkWidget displaying #EekKeyboard */ #include "config.h" #include #include #include "eek-renderer.h" #include "eek-keyboard.h" #include "eek-gtk-keyboard.h" #include "eekboard/eekboard-context-service.h" #include "src/layout.h" #include "src/submission.h" #define LIBFEEDBACK_USE_UNSTABLE_API #include #define SQUEEKBOARD_APP_ID "sm.puri.squeekboard" typedef struct _EekGtkKeyboardPrivate { EekRenderer *renderer; // owned, nullable struct render_geometry render_geometry; // mutable EekboardContextService *eekboard_context; // unowned reference struct submission *submission; // unowned reference struct squeek_layout_state *layout; // unowned LevelKeyboard *keyboard; // unowned reference; it's kept in server-context GdkEventSequence *sequence; // unowned reference LfbEvent *event; } EekGtkKeyboardPrivate; G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA) static void eek_gtk_keyboard_real_realize (GtkWidget *self) { gtk_widget_set_events (self, GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK | GDK_TOUCH_MASK); GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->realize (self); } static void set_allocation_size(EekGtkKeyboard *gtk_keyboard, struct squeek_layout *layout, gdouble width, gdouble height) { // This is where size-dependent surfaces would be released EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (gtk_keyboard); priv->render_geometry = eek_render_geometry_from_allocation_size( layout, width, height); } static gboolean eek_gtk_keyboard_real_draw (GtkWidget *self, cairo_t *cr) { EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (keyboard); GtkAllocation allocation; gtk_widget_get_allocation (self, &allocation); if (!priv->keyboard) { return FALSE; } if (!priv->renderer) { PangoContext *pcontext = gtk_widget_get_pango_context (self); priv->renderer = eek_renderer_new ( priv->keyboard, pcontext); set_allocation_size (keyboard, priv->keyboard->layout, allocation.width, allocation.height); eek_renderer_set_scale_factor (priv->renderer, gtk_widget_get_scale_factor (self)); } eek_renderer_render_keyboard (priv->renderer, priv->render_geometry, priv->submission, cr, priv->keyboard); return FALSE; } // Units of virtual pixels size static enum squeek_arrangement_kind get_type(uint32_t width, uint32_t height) { (void)height; if (width < 540) { return ARRANGEMENT_KIND_BASE; } return ARRANGEMENT_KIND_WIDE; } static void eek_gtk_keyboard_real_size_allocate (GtkWidget *self, GtkAllocation *allocation) { EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD (self); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (keyboard); // check if the change would switch types enum squeek_arrangement_kind new_type = get_type( (uint32_t)(allocation->width - allocation->x), (uint32_t)(allocation->height - allocation->y)); if (priv->layout->arrangement != new_type) { priv->layout->arrangement = new_type; uint32_t time = gdk_event_get_time(NULL); eekboard_context_service_use_layout(priv->eekboard_context, priv->layout, time); } if (priv->renderer) { set_allocation_size (keyboard, priv->keyboard->layout, allocation->width, allocation->height); } GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)-> size_allocate (self, allocation); } static void on_event_triggered (LfbEvent *event, GAsyncResult *res, gpointer unused) { g_autoptr (GError) err = NULL; if (!lfb_event_trigger_feedback_finish (event, res, &err)) { g_warning ("Failed to trigger feedback for '%s': %s", lfb_event_get_event (event), err->message); } } static void depress(EekGtkKeyboard *self, gdouble x, gdouble y, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); if (!priv->keyboard) { return; } squeek_layout_depress(priv->keyboard->layout, priv->submission, x, y, priv->render_geometry.widget_to_layout, time, self); } static void drag(EekGtkKeyboard *self, gdouble x, gdouble y, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); if (!priv->keyboard) { return; } squeek_layout_drag(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout, priv->submission, x, y, priv->render_geometry.widget_to_layout, time, priv->eekboard_context, self); } static void release(EekGtkKeyboard *self, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); if (!priv->keyboard) { return; } squeek_layout_release(eekboard_context_service_get_keyboard(priv->eekboard_context)->layout, priv->submission, priv->render_geometry.widget_to_layout, time, priv->eekboard_context, self); } static gboolean eek_gtk_keyboard_real_button_press_event (GtkWidget *self, GdkEventButton *event) { if (event->type == GDK_BUTTON_PRESS && event->button == 1) { depress(EEK_GTK_KEYBOARD(self), event->x, event->y, event->time); } return TRUE; } // TODO: this belongs more in gtk_keyboard, with a way to find out which key to re-render static gboolean eek_gtk_keyboard_real_button_release_event (GtkWidget *self, GdkEventButton *event) { if (event->type == GDK_BUTTON_RELEASE && event->button == 1) { // TODO: can the event have different coords than the previous move event? release(EEK_GTK_KEYBOARD(self), event->time); } return TRUE; } static gboolean eek_gtk_keyboard_leave_event (GtkWidget *self, GdkEventCrossing *event) { if (event->type == GDK_LEAVE_NOTIFY) { // TODO: can the event have different coords than the previous move event? release(EEK_GTK_KEYBOARD(self), event->time); } return TRUE; } static gboolean eek_gtk_keyboard_real_motion_notify_event (GtkWidget *self, GdkEventMotion *event) { if (event->state & GDK_BUTTON1_MASK) { drag(EEK_GTK_KEYBOARD(self), event->x, event->y, event->time); } return TRUE; } // Only one touch stream at a time allowed. Others will be completely ignored. static gboolean handle_touch_event (GtkWidget *widget, GdkEventTouch *event) { EekGtkKeyboard *self = EEK_GTK_KEYBOARD (widget); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); /* For each new touch, release the previous one and record the new event sequence. */ if (event->type == GDK_TOUCH_BEGIN) { release(self, event->time); priv->sequence = event->sequence; depress(self, event->x, event->y, event->time); return TRUE; } /* Only allow the latest touch point to be dragged. */ if (event->type == GDK_TOUCH_UPDATE && event->sequence == priv->sequence) { drag(self, event->x, event->y, event->time); } else if (event->type == GDK_TOUCH_END || event->type == GDK_TOUCH_CANCEL) { // TODO: can the event have different coords than the previous update event? /* Only respond to the release of the latest touch point. Previous touches have already been released. */ if (event->sequence == priv->sequence) { release(self, event->time); priv->sequence = NULL; } } return TRUE; } static void eek_gtk_keyboard_real_unmap (GtkWidget *self) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); if (priv->keyboard) { squeek_layout_release_all_only( priv->keyboard->layout, priv->submission, gdk_event_get_time(NULL)); } GTK_WIDGET_CLASS (eek_gtk_keyboard_parent_class)->unmap (self); } static void eek_gtk_keyboard_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { (void)value; switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eek_gtk_keyboard_dispose (GObject *object) { EekGtkKeyboard *self = EEK_GTK_KEYBOARD (object); EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); if (priv->renderer) { eek_renderer_free(priv->renderer); priv->renderer = NULL; } if (priv->keyboard) { squeek_layout_release_all_only( priv->keyboard->layout, priv->submission, gdk_event_get_time(NULL)); priv->keyboard = NULL; } if (priv->event) { g_clear_object (&priv->event); lfb_uninit (); } G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object); } static void eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); widget_class->realize = eek_gtk_keyboard_real_realize; widget_class->unmap = eek_gtk_keyboard_real_unmap; widget_class->draw = eek_gtk_keyboard_real_draw; widget_class->size_allocate = eek_gtk_keyboard_real_size_allocate; widget_class->button_press_event = eek_gtk_keyboard_real_button_press_event; widget_class->button_release_event = eek_gtk_keyboard_real_button_release_event; widget_class->motion_notify_event = eek_gtk_keyboard_real_motion_notify_event; widget_class->leave_notify_event = eek_gtk_keyboard_leave_event; widget_class->touch_event = handle_touch_event; gobject_class->set_property = eek_gtk_keyboard_set_property; gobject_class->dispose = eek_gtk_keyboard_dispose; } static void eek_gtk_keyboard_init (EekGtkKeyboard *self) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); g_autoptr(GError) err = NULL; if (lfb_init(SQUEEKBOARD_APP_ID, &err)) { priv->event = lfb_event_new ("button-pressed"); } else { g_warning ("Failed to init libfeedback: %s", err->message); } GtkIconTheme *theme = gtk_icon_theme_get_default (); gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons"); } static void on_notify_keyboard (GObject *object, GParamSpec *spec, EekGtkKeyboard *self) { (void)spec; EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (self); priv->keyboard = eekboard_context_service_get_keyboard(EEKBOARD_CONTEXT_SERVICE(object)); if (priv->renderer) { eek_renderer_free(priv->renderer); } priv->renderer = NULL; gtk_widget_queue_draw(GTK_WIDGET(self)); } /** * Create a new #GtkWidget displaying @keyboard. * Returns: a #GtkWidget */ GtkWidget * eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_layout_state *layout) { EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL)); EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret); priv->eekboard_context = eekservice; priv->submission = submission; priv->layout = layout; priv->renderer = NULL; // This should really be done on initialization. // Before the widget is allocated, // we don't really know what geometry it takes. // When it's off the screen, we also kinda don't. struct render_geometry initial_geometry = { // Set to 100 just to make sure if there's any attempt to use it, // it actually gives plausible results instead of blowing up, // e.g. on zero division. .allocation_width = 100, .allocation_height = 100, .widget_to_layout = { .origin_x = 0, .origin_y = 0, .scale = 1, }, }; priv->render_geometry = initial_geometry; g_signal_connect (eekservice, "notify::keyboard", G_CALLBACK(on_notify_keyboard), ret); on_notify_keyboard(G_OBJECT(eekservice), NULL, ret); /* TODO: this is how a compound keyboard * made out of a layout and a suggestion bar could start. * GtkBox *box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0)); GtkEntry *fill = GTK_ENTRY(gtk_entry_new()); gtk_box_pack_start(box, GTK_WIDGET(fill), FALSE, FALSE, 0); gtk_box_pack_start(box, GTK_WIDGET(ret), TRUE, TRUE, 0); return GTK_WIDGET(box);*/ return GTK_WIDGET(ret); } /** * eek_gtk_keyboard_emit_feedback: * * Emit button press haptic feedback via libfeedack. */ void eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self) { EekGtkKeyboardPrivate *priv; g_return_if_fail (EEK_IS_GTK_KEYBOARD (self)); priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); if (priv->event) { lfb_event_trigger_feedback_async (priv->event, NULL, (GAsyncReadyCallback)on_event_triggered, NULL); } } squeekboard-v1.17.1/eek/eek-gtk-keyboard.h000066400000000000000000000033421422304253700203420ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ #if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION) #error "Only can be included directly." #endif #ifndef EEK_GTK_KEYBOARD_H #define EEK_GTK_KEYBOARD_H 1 #include #include #include "eek/eek-renderer.h" #include "eek/eek-types.h" struct submission; struct squeek_layout_state; G_BEGIN_DECLS #define EEK_TYPE_GTK_KEYBOARD (eek_gtk_keyboard_get_type()) G_DECLARE_DERIVABLE_TYPE (EekGtkKeyboard, eek_gtk_keyboard, EEK, GTK_KEYBOARD, GtkDrawingArea) struct _EekGtkKeyboardClass { /*< private >*/ GtkDrawingAreaClass parent_class; /*< private >*/ /* padding */ gpointer pdummy[24]; }; GtkWidget *eek_gtk_keyboard_new (EekboardContextService *eekservice, struct submission *submission, struct squeek_layout_state *layout); void eek_gtk_keyboard_emit_feedback (EekGtkKeyboard *self); G_END_DECLS #endif /* EEK_GTK_KEYBOARD_H */ squeekboard-v1.17.1/eek/eek-keyboard.c000066400000000000000000000062521422304253700175550ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ #include "config.h" #define _XOPEN_SOURCE 500 #include #include #include #include #include // TODO: this is Linux-specific #include #include "eek-keyboard.h" /// External linkage for Rust. /// The corresponding deinit is implemented in vkeyboard::KeyMap::drop struct keymap squeek_key_map_from_str(const char *keymap_str) { struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { g_error("No context created"); } struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { g_error("Bad keymap:\n%s", keymap_str); } xkb_context_unref(context); char *xkb_keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1); size_t keymap_len = strlen(xkb_keymap_str) + 1; g_autofree char *path = strdup("/eek_keymap-XXXXXX"); char *r = &path[strlen(path) - 6]; if (getrandom(r, 6, GRND_NONBLOCK) < 0) { g_error("Failed to get random numbers: %s", strerror(errno)); } for (unsigned i = 0; i < 6; i++) { r[i] = (r[i] & 0b1111111) | 0b1000000; // A-z r[i] = r[i] > 'z' ? '?' : r[i]; // The randomizer doesn't need to be good... } int keymap_fd = shm_open(path, O_RDWR | O_CREAT | O_EXCL, 0600); if (keymap_fd < 0) { g_error("Failed to set up keymap fd"); } shm_unlink(path); if (ftruncate(keymap_fd, (off_t)keymap_len)) { g_error("Failed to increase keymap fd size"); } char *ptr = mmap(NULL, keymap_len, PROT_WRITE, MAP_SHARED, keymap_fd, 0); if ((void*)ptr == (void*)-1) { g_error("Failed to set up mmap"); } strncpy(ptr, xkb_keymap_str, keymap_len); munmap(ptr, keymap_len); free(xkb_keymap_str); xkb_keymap_unref(keymap); struct keymap km = { .fd = keymap_fd, .fd_len = keymap_len, }; return km; } void level_keyboard_free(LevelKeyboard *self) { squeek_layout_free(self->layout); g_free(self); } LevelKeyboard* level_keyboard_new (struct squeek_layout *layout) { LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1); if (!keyboard) { g_error("Failed to create a keyboard"); } keyboard->layout = layout; return keyboard; } squeekboard-v1.17.1/eek/eek-keyboard.h000066400000000000000000000033201422304253700175530ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ #if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION) #error "Only can be included directly." #endif #ifndef EEK_KEYBOARD_H #define EEK_KEYBOARD_H 1 #include #include #include "eek-types.h" #include "src/layout.h" G_BEGIN_DECLS /// Keymap container for Rust interoperability. struct keymap { uint32_t fd; // keymap formatted as XKB string size_t fd_len; // length of the data inside keymap_fd }; /// Keyboard state holder struct _LevelKeyboard { struct squeek_layout *layout; // owned // FIXME: This no longer needs to exist, keymap was folded into layout. }; typedef struct _LevelKeyboard LevelKeyboard; gchar *eek_keyboard_get_keymap(LevelKeyboard *keyboard); LevelKeyboard* level_keyboard_new (struct squeek_layout *layout); void level_keyboard_free(LevelKeyboard *self); G_END_DECLS #endif /* EEK_KEYBOARD_H */ squeekboard-v1.17.1/eek/eek-renderer.c000066400000000000000000000376131422304253700175700ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ #define G_LOG_DOMAIN "squeekboard-eek-renderer" #include #include #include #include "eek-keyboard.h" #include "eek-renderer.h" #include "src/style.h" /* eek-keyboard-drawing.c */ static void render_button_label (cairo_t *cr, GtkStyleContext *ctx, const gchar *label, EekBounds bounds); static void render_outline (cairo_t *cr, GtkStyleContext *ctx, EekBounds bounds) { GtkBorder margin, border; gtk_style_context_get_margin(ctx, GTK_STATE_FLAG_NORMAL, &margin); gtk_style_context_get_border(ctx, GTK_STATE_FLAG_NORMAL, &border); gdouble x = margin.left + border.left; gdouble y = margin.top + border.top; EekBounds position = { .x = x, .y = y, .width = bounds.width - x - (margin.right + border.right), .height = bounds.height - y - (margin.bottom + border.bottom), }; gtk_render_background (ctx, cr, position.x, position.y, position.width, position.height); gtk_render_frame (ctx, cr, position.x, position.y, position.width, position.height); } float get_scale(cairo_t *cr) { double width = 1; double height = 1; cairo_user_to_device_distance (cr, &width, &height); return width; } /// Rust interface void eek_render_button_in_context(uint32_t scale_factor, cairo_t *cr, GtkStyleContext *ctx, EekBounds bounds, const char *icon_name, const gchar *label) { /* blank background */ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0); cairo_paint (cr); render_outline (cr, ctx, bounds); cairo_paint (cr); /* render icon (if any) */ if (icon_name) { int context_scale = ceil (get_scale (cr)); cairo_surface_t *icon_surface = eek_renderer_get_icon_surface (icon_name, 16, scale_factor * context_scale); if (icon_surface) { double width = cairo_image_surface_get_width (icon_surface); double height = cairo_image_surface_get_height (icon_surface); cairo_save (cr); cairo_translate (cr, (bounds.width - width / (scale_factor * context_scale)) / 2, (bounds.height - height / (scale_factor * context_scale)) / 2); cairo_rectangle (cr, 0, 0, width, height); cairo_clip (cr); /* Draw the shape of the icon using the foreground color */ GdkRGBA color = {0}; gtk_style_context_get_color (ctx, GTK_STATE_FLAG_NORMAL, &color); cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha); cairo_mask_surface (cr, icon_surface, 0.0, 0.0); cairo_surface_destroy(icon_surface); cairo_fill (cr); cairo_restore (cr); return; } } if (label) { render_button_label (cr, ctx, label, bounds); } } /// Prepare context for drawing the button. /// The context MUST be released using the corresponing "put" procedure /// before drawing the next button. /// Interface for Rust. GtkStyleContext * eek_get_style_context_for_button (EekRenderer *self, const char *name, const char *outline_name, const char *locked_class, uint64_t pressed) { GtkStyleContext *ctx = self->button_context; /* Set the name of the button on the widget path, using the name obtained from the button's symbol. */ g_autoptr (GtkWidgetPath) path = NULL; path = gtk_widget_path_copy (gtk_style_context_get_path (ctx)); gtk_widget_path_iter_set_name (path, -1, name); /* Update the style context with the updated widget path. */ gtk_style_context_set_path (ctx, path); /* Set the state to take into account whether the button is active (pressed) or normal. */ gtk_style_context_set_state(ctx, pressed ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL); if (locked_class) { gtk_style_context_add_class(ctx, locked_class); } gtk_style_context_add_class(ctx, outline_name); return ctx; } /// Interface for Rust. void eek_put_style_context_for_button(GtkStyleContext *ctx, const char *outline_name, const char *locked_class) { // Save and restore functions don't work if gtk_render_* was used in between gtk_style_context_set_state(ctx, GTK_STATE_FLAG_NORMAL); gtk_style_context_remove_class(ctx, outline_name); if (locked_class) { gtk_style_context_remove_class(ctx, locked_class); } } static void render_button_label (cairo_t *cr, GtkStyleContext *ctx, const gchar *label, EekBounds bounds) { PangoFontDescription *font; gtk_style_context_get(ctx, gtk_style_context_get_state(ctx), "font", &font, NULL); PangoLayout *layout = pango_cairo_create_layout (cr); pango_layout_set_font_description (layout, font); pango_font_description_free (font); pango_layout_set_text (layout, label, -1); PangoLayoutLine *line = pango_layout_get_line_readonly(layout, 0); if (line->resolved_dir == PANGO_DIRECTION_RTL) { pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); } pango_layout_set_width (layout, PANGO_SCALE * bounds.width); PangoRectangle extents = { 0, }; pango_layout_get_extents (layout, NULL, &extents); cairo_save (cr); cairo_move_to (cr, (bounds.width - (double)extents.width / PANGO_SCALE) / 2, (bounds.height - (double)extents.height / PANGO_SCALE) / 2); GdkRGBA color = {0}; gtk_style_context_get_color (ctx, GTK_STATE_FLAG_NORMAL, &color); cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha); pango_cairo_show_layout (cr, layout); cairo_restore (cr); g_object_unref (layout); } // FIXME: Pass just the active modifiers instead of entire submission void eek_renderer_render_keyboard (EekRenderer *self, struct render_geometry geometry, struct submission *submission, cairo_t *cr, LevelKeyboard *keyboard) { g_return_if_fail (geometry.allocation_width > 0.0); g_return_if_fail (geometry.allocation_height > 0.0); /* Paint the background covering the entire widget area */ gtk_render_background (self->view_context, cr, 0, 0, geometry.allocation_width, geometry.allocation_height); cairo_save(cr); cairo_translate (cr, geometry.widget_to_layout.origin_x, geometry.widget_to_layout.origin_y); cairo_scale (cr, geometry.widget_to_layout.scale, geometry.widget_to_layout.scale); squeek_draw_layout_base_view(keyboard->layout, self, cr); squeek_layout_draw_all_changed(keyboard->layout, self, cr, submission); cairo_restore (cr); } void eek_renderer_free (EekRenderer *self) { if (self->pcontext) { g_object_unref (self->pcontext); self->pcontext = NULL; } g_object_unref(self->css_provider); g_object_unref(self->view_context); g_object_unref(self->button_context); g_clear_signal_handler (&self->theme_name_id, gtk_settings_get_default()); // this is where renderer-specific surfaces would be released free(self); } static GType new_type(char *name) { GTypeInfo info = {0}; info.class_size = sizeof(GtkWidgetClass); info.instance_size = sizeof(GtkWidget); return g_type_register_static(GTK_TYPE_WIDGET, name, &info, G_TYPE_FLAG_ABSTRACT ); } static GType view_type(void) { static GType type = 0; if (!type) { type = new_type("sq_view"); } return type; } static GType button_type(void) { static GType type = 0; if (!type) { type = new_type("sq_button"); } return type; } static void on_gtk_theme_name_changed (GtkSettings *settings, gpointer foo, EekRenderer *self) { g_autofree char *name = NULL; g_object_get (settings, "gtk-theme-name", &name, NULL); g_debug ("GTK theme: %s", name); gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (self->css_provider)); gtk_style_context_remove_provider (self->button_context, GTK_STYLE_PROVIDER(self->css_provider)); gtk_style_context_remove_provider (self->view_context, GTK_STYLE_PROVIDER(self->css_provider)); g_set_object (&self->css_provider, squeek_load_style()); gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (self->css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); gtk_style_context_add_provider (self->button_context, GTK_STYLE_PROVIDER(self->css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); gtk_style_context_add_provider (self->view_context, GTK_STYLE_PROVIDER(self->css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } static void renderer_init (EekRenderer *self) { self->pcontext = NULL; self->scale_factor = 1; GtkSettings *gtk_settings; gtk_settings = gtk_settings_get_default (); self->theme_name_id = g_signal_connect (gtk_settings, "notify::gtk-theme-name", G_CALLBACK (on_gtk_theme_name_changed), self); self->css_provider = squeek_load_style(); } EekRenderer * eek_renderer_new (LevelKeyboard *keyboard, PangoContext *pcontext) { EekRenderer *renderer = calloc(1, sizeof(EekRenderer)); renderer_init(renderer); renderer->pcontext = pcontext; g_object_ref (renderer->pcontext); const char *purpose_class = "normal"; /* Create a style context for the layout */ GtkWidgetPath *path = gtk_widget_path_new(); gtk_widget_path_append_type(path, view_type()); renderer->view_context = gtk_style_context_new(); gtk_style_context_set_path(renderer->view_context, path); gtk_widget_path_unref(path); if (squeek_layout_get_kind(keyboard->layout) == ARRANGEMENT_KIND_WIDE) { gtk_style_context_add_class(renderer->view_context, "wide"); } gtk_style_context_add_provider (renderer->view_context, GTK_STYLE_PROVIDER(renderer->css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); /* Create a style context for the buttons */ path = gtk_widget_path_new(); gtk_widget_path_append_type(path, view_type()); if (squeek_layout_get_kind(keyboard->layout) == ARRANGEMENT_KIND_WIDE) { gtk_widget_path_iter_add_class(path, -1, "wide"); } /* Add style classes based on purpose */ switch (squeek_layout_get_purpose (keyboard->layout)) { case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL: purpose_class = "normal"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_ALPHA: purpose_class = "alpha"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS: purpose_class = "digits"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER: purpose_class = "number"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE: purpose_class = "phone"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL: purpose_class = "url"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL: purpose_class = "email"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NAME: purpose_class = "name"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD: purpose_class = "password"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PIN: purpose_class = "pin"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATE: purpose_class = "date"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TIME: purpose_class = "time"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATETIME: purpose_class = "datetime"; break; case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL: purpose_class = "terminal"; break; default: g_warning ("Unknown input purpose %d", squeek_layout_get_purpose(keyboard->layout)); } gtk_widget_path_iter_add_class(path, -1, purpose_class); gtk_widget_path_append_type(path, button_type()); renderer->button_context = gtk_style_context_new (); gtk_style_context_set_path(renderer->button_context, path); gtk_widget_path_unref(path); gtk_style_context_set_parent(renderer->button_context, renderer->view_context); gtk_style_context_set_state (renderer->button_context, GTK_STATE_FLAG_NORMAL); gtk_style_context_add_provider (renderer->button_context, GTK_STYLE_PROVIDER(renderer->css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); return renderer; } struct render_geometry eek_render_geometry_from_allocation_size (struct squeek_layout *layout, gdouble width, gdouble height) { struct render_geometry ret = { .allocation_width = width, .allocation_height = height, .widget_to_layout = squeek_layout_calculate_transformation( layout, width, height), }; return ret; } void eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale) { renderer->scale_factor = scale; } /// Rust interface. uint32_t eek_renderer_get_scale_factor(EekRenderer *renderer) { return renderer->scale_factor; } cairo_surface_t * eek_renderer_get_icon_surface (const gchar *icon_name, gint size, gint scale) { GError *error = NULL; cairo_surface_t *surface = gtk_icon_theme_load_surface (gtk_icon_theme_get_default (), icon_name, size, scale, NULL, 0, &error); if (surface == NULL) { g_warning ("can't get icon surface for %s: %s", icon_name, error->message); g_error_free (error); return NULL; } return surface; } squeekboard-v1.17.1/eek/eek-renderer.h000066400000000000000000000055371422304253700175750ustar00rootroot00000000000000/* * Copyright (C) 2011 Daiki Ueno * Copyright (C) 2011 Red Hat, Inc. * * 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 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 */ #ifndef EEK_RENDERER_H #define EEK_RENDERER_H 1 #include #include #include "eek-types.h" #include "src/submission.h" struct squeek_layout; /// Renders LevelKayboards /// It cannot adjust styles at runtime. typedef struct EekRenderer { PangoContext *pcontext; // owned GtkCssProvider *css_provider; // owned GtkStyleContext *view_context; // owned GtkStyleContext *button_context; // TODO: maybe move a copy to each button /// Style class for rendering the view and button CSS. gchar *extra_style; // owned // Theme name change signal handler id gulong theme_name_id; // Mutable state gint scale_factor; /* the outputs scale factor */ } EekRenderer; /// Mutable part of the renderer state. /// TODO: Possibly should include scale factor. struct render_geometry { /// Background extents gdouble allocation_width; gdouble allocation_height; /// Coords transformation struct transformation widget_to_layout; }; GType eek_renderer_get_type (void) G_GNUC_CONST; EekRenderer *eek_renderer_new (LevelKeyboard *keyboard, PangoContext *pcontext); void eek_renderer_set_scale_factor (EekRenderer *renderer, gint scale); cairo_surface_t *eek_renderer_get_icon_surface(const gchar *icon_name, gint size, gint scale); void eek_renderer_render_keyboard (EekRenderer *renderer, struct render_geometry geometry, struct submission *submission, cairo_t *cr, LevelKeyboard *keyboard); void eek_renderer_free (EekRenderer *self); struct render_geometry eek_render_geometry_from_allocation_size (struct squeek_layout *layout, gdouble width, gdouble height); G_END_DECLS #endif /* EEK_RENDERER_H */ squeekboard-v1.17.1/eek/eek-types.c000066400000000000000000000035151422304253700171200ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ /** * SECTION:eek-types * @title: Miscellaneous Types * @short_description: Miscellaneous types used in Libeek */ #include "config.h" #include #include #include "eek-types.h" /* EekPoint */ G_DEFINE_BOXED_TYPE(EekPoint, eek_point, eek_point_copy, eek_point_free); EekPoint * eek_point_copy (const EekPoint *point) { return g_slice_dup (EekPoint, point); } void eek_point_free (EekPoint *point) { g_slice_free (EekPoint, point); } void eek_point_rotate (EekPoint *point, gint angle) { gdouble r, phi; phi = atan2 (point->y, point->x); r = sqrt (point->x * point->x + point->y * point->y); phi += angle * M_PI / 180; point->x = r * cos (phi); point->y = r * sin (phi); } /* EekBounds */ G_DEFINE_BOXED_TYPE(EekBounds, eek_bounds, eek_bounds_copy, eek_bounds_free); EekBounds * eek_bounds_copy (const EekBounds *bounds) { return g_slice_dup (EekBounds, bounds); } void eek_bounds_free (EekBounds *bounds) { g_slice_free (EekBounds, bounds); } squeekboard-v1.17.1/eek/eek-types.h000066400000000000000000000047731422304253700171340ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * Copyright (C) 2019 Purism, SPC * * 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 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 */ #if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION) #error "Only can be included directly." #endif #ifndef EEK_TYPES_H #define EEK_TYPES_H 1 #include G_BEGIN_DECLS #define I_(string) g_intern_static_string (string) #define EEK_TYPE_POINT (eek_point_get_type ()) #define EEK_TYPE_BOUNDS (eek_bounds_get_type ()) typedef struct _EekBounds EekBounds; typedef struct _EekboardContextService EekboardContextService; typedef struct _ServerContextService ServerContextService; typedef struct _LevelKeyboard LevelKeyboard; /** * EekPoint: * @x: X coordinate of the point * @y: Y coordinate of the point * * 2D vertex */ typedef struct _EekPoint EekPoint; struct _EekPoint { /*< public >*/ gdouble x; gdouble y; }; GType eek_point_get_type (void) G_GNUC_CONST; EekPoint *eek_point_copy (const EekPoint *point); void eek_point_free (EekPoint *point); void eek_point_rotate (EekPoint *point, gint angle); /** * EekBounds: * @x: X coordinate of the top left point * @y: Y coordinate of the top left point * @width: width of the box * @height: height of the box * * The rectangle containing an element's bounding box. */ struct _EekBounds { /*< public >*/ gdouble x; gdouble y; gdouble width; gdouble height; }; GType eek_bounds_get_type (void) G_GNUC_CONST; EekBounds *eek_bounds_copy (const EekBounds *bounds); void eek_bounds_free (EekBounds *bounds); struct transformation { gdouble origin_x; gdouble origin_y; gdouble scale; }; G_END_DECLS #endif /* EEK_TYPES_H */ squeekboard-v1.17.1/eek/eek.c000066400000000000000000000021221422304253700157470ustar00rootroot00000000000000/* * Copyright (C) 2011 Daiki Ueno * Copyright (C) 2011 Red Hat, Inc. * * 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 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 */ /** * SECTION:eek * @title: Library Initialization */ #include "config.h" #include "eek.h" /** * eek_init: * * Initialize the Libeek library. This must be called before using * functions provided by Libeek. */ void eek_init (void) { /* void */ } squeekboard-v1.17.1/eek/eek.h000066400000000000000000000017261422304253700157650ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * 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 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 */ #ifndef EEK_H #define EEK_H 1 #define __EEK_H_INSIDE__ 1 #include "eek-keyboard.h" void eek_init (void); #endif /* EEK_H */ squeekboard-v1.17.1/eek/layersurface.c000066400000000000000000000544121422304253700177010ustar00rootroot00000000000000/* * Copyright (C) 2018 Purism SPC * SPDX-License-Identifier: GPL-3.0+ * Author: Guido Günther */ /* WARNING: this file is taken directly from phosh, with no modificaions apart from this message. Please update phosh instead of changing this file. Please copy the file back here afterwards, with the same notice. */ #define G_LOG_DOMAIN "phosh-layer-surface" #include "config.h" #include "layersurface.h" #include enum { PHOSH_LAYER_SURFACE_PROP_0, PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL, PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT, PHOSH_LAYER_SURFACE_PROP_ANCHOR, PHOSH_LAYER_SURFACE_PROP_LAYER, PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY, PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE, PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP, PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM, PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT, PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT, PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH, PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT, PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH, PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT, PHOSH_LAYER_SURFACE_PROP_NAMESPACE, PHOSH_LAYER_SURFACE_PROP_LAST_PROP }; static GParamSpec *props[PHOSH_LAYER_SURFACE_PROP_LAST_PROP]; enum { CONFIGURED, N_SIGNALS }; static guint signals [N_SIGNALS]; typedef struct { struct wl_surface *wl_surface; struct zwlr_layer_surface_v1 *layer_surface; /* Properties */ guint anchor; guint layer; gboolean kbd_interactivity; gint exclusive_zone; gint margin_top, margin_bottom; gint margin_left, margin_right; gint width, height; gint configured_width, configured_height; gchar *namespace; struct zwlr_layer_shell_v1 *layer_shell; struct wl_output *wl_output; } PhoshLayerSurfacePrivate; G_DEFINE_TYPE_WITH_PRIVATE (PhoshLayerSurface, phosh_layer_surface, GTK_TYPE_WINDOW) static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height) { PhoshLayerSurface *self = data; PhoshLayerSurfacePrivate *priv; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); gtk_window_resize (GTK_WINDOW (self), width, height); zwlr_layer_surface_v1_ack_configure(surface, serial); if (priv->configured_height != height) { priv->configured_height = height; g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT]); } if (priv->configured_width != width) { priv->configured_width = width; g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH]); } g_debug("Configured %p", self); g_signal_emit (self, signals[CONFIGURED], 0); } static void layer_surface_closed (void *data, struct zwlr_layer_surface_v1 *surface) { PhoshLayerSurface *self = data; PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self); g_return_if_fail (priv->layer_surface == surface); zwlr_layer_surface_v1_destroy(priv->layer_surface); priv->layer_surface = NULL; gtk_widget_destroy (GTK_WIDGET (self)); } static struct zwlr_layer_surface_v1_listener layer_surface_listener = { .configure = layer_surface_configure, .closed = layer_surface_closed, }; static void phosh_layer_surface_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object); PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self); gint width, height; switch (property_id) { case PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL: priv->layer_shell = g_value_get_pointer (value); break; case PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT: priv->wl_output = g_value_get_pointer (value); break; case PHOSH_LAYER_SURFACE_PROP_ANCHOR: priv->anchor = g_value_get_uint (value); break; case PHOSH_LAYER_SURFACE_PROP_LAYER: priv->layer = g_value_get_uint (value); break; case PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY: phosh_layer_surface_set_kbd_interactivity (self, g_value_get_boolean (value)); break; case PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE: phosh_layer_surface_set_exclusive_zone (self, g_value_get_int (value)); break; case PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP: phosh_layer_surface_set_margins (self, g_value_get_int (value), priv->margin_right, priv->margin_bottom, priv->margin_left); break; case PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM: phosh_layer_surface_set_margins (self, priv->margin_top, priv->margin_right, g_value_get_int (value), priv->margin_left); break; case PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT: phosh_layer_surface_set_margins (self, priv->margin_top, priv->margin_right, priv->margin_bottom, g_value_get_int (value)); break; case PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT: phosh_layer_surface_set_margins (self, priv->margin_top, g_value_get_int (value), priv->margin_bottom, priv->margin_left); break; case PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH: width = g_value_get_uint (value); phosh_layer_surface_set_size(self, width, priv->height); break; case PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT: height = g_value_get_uint (value); phosh_layer_surface_set_size(self, priv->width, height); break; case PHOSH_LAYER_SURFACE_PROP_NAMESPACE: g_free (priv->namespace); priv->namespace = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void phosh_layer_surface_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object); PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self); switch (property_id) { case PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL: g_value_set_pointer (value, priv->layer_shell); break; case PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT: g_value_set_pointer (value, priv->wl_output); break; case PHOSH_LAYER_SURFACE_PROP_ANCHOR: g_value_set_uint (value, priv->anchor); break; case PHOSH_LAYER_SURFACE_PROP_LAYER: g_value_set_uint (value, priv->layer); break; case PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY: g_value_set_boolean (value, priv->kbd_interactivity); break; case PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE: g_value_set_int (value, priv->exclusive_zone); break; case PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP: g_value_set_int (value, priv->margin_top); break; case PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM: g_value_set_int (value, priv->margin_bottom); break; case PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT: g_value_set_int (value, priv->margin_left); break; case PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT: g_value_set_int (value, priv->margin_right); break; case PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH: g_value_set_uint (value, priv->width); break; case PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT: g_value_set_uint (value, priv->height); break; case PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH: g_value_set_uint (value, priv->configured_width); break; case PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT: g_value_set_uint (value, priv->configured_height); break; case PHOSH_LAYER_SURFACE_PROP_NAMESPACE: g_value_set_string (value, priv->namespace); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused) { PhoshLayerSurfacePrivate *priv; GdkWindow *gdk_window; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); gdk_window = gtk_widget_get_window (GTK_WIDGET (self)); gdk_wayland_window_set_use_custom_surface (gdk_window); priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window); gtk_window_set_decorated (GTK_WINDOW (self), FALSE); } static void on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused) { PhoshLayerSurfacePrivate *priv; GdkWindow *gdk_window; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); if (!priv->wl_surface) { gdk_window = gtk_widget_get_window (GTK_WIDGET (self)); gdk_wayland_window_set_use_custom_surface (gdk_window); priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window); } g_debug ("Mapped %p", priv->wl_surface); priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell, priv->wl_surface, priv->wl_output, priv->layer, priv->namespace); zwlr_layer_surface_v1_set_exclusive_zone(priv->layer_surface, priv->exclusive_zone); zwlr_layer_surface_v1_set_size(priv->layer_surface, priv->width, priv->height); zwlr_layer_surface_v1_set_anchor(priv->layer_surface, priv->anchor); zwlr_layer_surface_v1_set_margin(priv->layer_surface, priv->margin_top, priv->margin_right, priv->margin_bottom, priv->margin_left); zwlr_layer_surface_v1_set_keyboard_interactivity(priv->layer_surface, priv->kbd_interactivity); zwlr_layer_surface_v1_add_listener(priv->layer_surface, &layer_surface_listener, self); wl_surface_commit(priv->wl_surface); /* Process all pending events, otherwise we end up sending ack configure * to a not yet configured surface */ wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ())); } static void on_phosh_layer_surface_unmapped (PhoshLayerSurface *self, gpointer unused) { PhoshLayerSurfacePrivate *priv; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); if (priv->layer_surface) { zwlr_layer_surface_v1_destroy(priv->layer_surface); priv->layer_surface = NULL; } priv->wl_surface = NULL; } static void phosh_layer_surface_constructed (GObject *object) { PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object); g_signal_connect (self, "realize", G_CALLBACK (on_phosh_layer_surface_realized), NULL); g_signal_connect (self, "map", G_CALLBACK (on_phosh_layer_surface_mapped), NULL); g_signal_connect (self, "unmap", G_CALLBACK (on_phosh_layer_surface_unmapped), NULL); G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object); } static void phosh_layer_surface_dispose (GObject *object) { PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object); PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self); if (priv->layer_surface) { zwlr_layer_surface_v1_destroy(priv->layer_surface); priv->layer_surface = NULL; } g_clear_pointer (&priv->namespace, g_free); G_OBJECT_CLASS (phosh_layer_surface_parent_class)->dispose (object); } static void phosh_layer_surface_class_init (PhoshLayerSurfaceClass *klass) { GObjectClass *object_class = (GObjectClass *)klass; object_class->constructed = phosh_layer_surface_constructed; object_class->dispose = phosh_layer_surface_dispose; object_class->set_property = phosh_layer_surface_set_property; object_class->get_property = phosh_layer_surface_get_property; props[PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL] = g_param_spec_pointer ( "layer-shell", "Wayland Layer Shell Global", "The layer shell wayland global", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT] = g_param_spec_pointer ( "wl-output", "Wayland Output", "The wl_output associated with this surface", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PHOSH_LAYER_SURFACE_PROP_ANCHOR] = g_param_spec_uint ( "anchor", "Anchor edges", "The edges to anchor the surface to", 0, G_MAXUINT, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PHOSH_LAYER_SURFACE_PROP_LAYER] = g_param_spec_uint ( "layer", "Layer", "The layer the surface should be attached to", 0, G_MAXUINT, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY] = g_param_spec_boolean ( "kbd-interactivity", "Keyboard interactivity", "Whether the surface interacts with the keyboard", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE] = g_param_spec_int ( "exclusive-zone", "Exclusive Zone", "Set area that is not occluded with other surfaces", -1, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT] = g_param_spec_int ( "margin-left", "Left margin", "Distance away from the left anchor point", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT] = g_param_spec_int ( "margin-right", "Right margin", "Distance away from the right anchor point", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP] = g_param_spec_int ( "margin-top", "Top margin", "Distance away from the top anchor point", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM] = g_param_spec_int ( "margin-bottom", "Bottom margin", "Distance away from the bottom anchor point", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH] = g_param_spec_uint ( "width", "Width", "The width of the layer surface", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT] = g_param_spec_uint ( "height", "Height", "The height of the layer surface", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH] = g_param_spec_uint ( "configured-width", "Configured width", "The width of the layer surface set by the compositor", 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT] = g_param_spec_uint ( "configured-height", "Configured height", "The height of the layer surface set by the compositor", 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); props[PHOSH_LAYER_SURFACE_PROP_NAMESPACE] = g_param_spec_string ( "namespace", "Namespace", "Namespace of the layer surface", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, PHOSH_LAYER_SURFACE_PROP_LAST_PROP, props); /** * PhoshLayersurface::configured * @self: The #PhoshLayersurface instance. * * This signal is emitted once we received the configure event from the * compositor. */ signals[CONFIGURED] = g_signal_new ("configured", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (PhoshLayerSurfaceClass, configured), NULL, NULL, NULL, G_TYPE_NONE, 0); } static void phosh_layer_surface_init (PhoshLayerSurface *self) { } GtkWidget * phosh_layer_surface_new (gpointer layer_shell, gpointer wl_output) { return g_object_new (PHOSH_TYPE_LAYER_SURFACE, "layer-shell", layer_shell, "wl-output", wl_output); } /** * phosh_layer_surface_get_surface: * * Get the layer layer surface or #NULL if the window * is not yet realized. */ struct zwlr_layer_surface_v1 * phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self) { PhoshLayerSurfacePrivate *priv; g_return_val_if_fail (PHOSH_IS_LAYER_SURFACE (self), NULL); priv = phosh_layer_surface_get_instance_private (self); return priv->layer_surface; } /** * phosh_layer_surface_get_wl_surface: * * Get the layer wayland surface or #NULL if the window * is not yet realized. */ struct wl_surface * phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self) { PhoshLayerSurfacePrivate *priv; g_return_val_if_fail (PHOSH_IS_LAYER_SURFACE (self), NULL); priv = phosh_layer_surface_get_instance_private (self); return priv->wl_surface; } /** * phosh_layer_surface_set_size: * * Set the size of a layer surface. A value of '-1' indicates 'use old value' */ void phosh_layer_surface_set_size(PhoshLayerSurface *self, gint width, gint height) { PhoshLayerSurfacePrivate *priv; gint old_width, old_height; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); if (priv->height == height && priv->width == width) { return; } old_width = priv->width; old_height = priv->height; if (width != -1) { priv->width = width; } if (height != -1) { priv->height = height; } if (gtk_widget_get_mapped (GTK_WIDGET (self))) { zwlr_layer_surface_v1_set_size(priv->layer_surface, priv->width, priv->height); } if (priv->height != old_height) { g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT]); } if (priv->width != old_width) { g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH]); } } /** * phosh_layer_surface_set_margins: * * Set anchor margins of a layer surface. */ void phosh_layer_surface_set_margins(PhoshLayerSurface *self, gint top, gint right, gint bottom, gint left) { PhoshLayerSurfacePrivate *priv; gint old_top, old_bottom, old_left, old_right; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); old_top = priv->margin_top; old_left = priv->margin_left; old_right = priv->margin_right; old_bottom = priv->margin_bottom; if (old_top == top && old_left == left && old_right == right && old_bottom == bottom) { return; } priv->margin_top = top; priv->margin_left = left; priv->margin_right = right; priv->margin_bottom = bottom; if (priv->layer_surface) { zwlr_layer_surface_v1_set_margin(priv->layer_surface, top, right, bottom, left); } if (old_top != top) { g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP]); } if (old_bottom != bottom) { g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM]); } if (old_left != left) { g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT]); } if (old_right != right) { g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT]); } } /** * phosh_layer_surface_set_exclusive_zone: * * Set exclusive zone of a layer surface. */ void phosh_layer_surface_set_exclusive_zone(PhoshLayerSurface *self, gint zone) { PhoshLayerSurfacePrivate *priv; gint old_zone; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); old_zone = priv->exclusive_zone; if (old_zone == zone) { return; } priv->exclusive_zone = zone; if (priv->layer_surface) { zwlr_layer_surface_v1_set_exclusive_zone(priv->layer_surface, zone); } g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE]); } /** * phosh_layer_surface_set_keyboard_interactivity: * * Set keyboard ineractivity a layer surface. */ void phosh_layer_surface_set_kbd_interactivity (PhoshLayerSurface *self, gboolean interactivity) { PhoshLayerSurfacePrivate *priv; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); if (priv->kbd_interactivity == interactivity) { return; } priv->kbd_interactivity = interactivity; if (priv->layer_surface) { zwlr_layer_surface_v1_set_keyboard_interactivity (priv->layer_surface, interactivity); } g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY]); } /** * phosh_layer_surface_wl_surface_commit: * * Forces a commit of layer surface's state. */ void phosh_layer_surface_wl_surface_commit (PhoshLayerSurface *self) { PhoshLayerSurfacePrivate *priv; g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self)); priv = phosh_layer_surface_get_instance_private (self); if (priv->wl_surface) { wl_surface_commit (priv->wl_surface); } } squeekboard-v1.17.1/eek/layersurface.h000066400000000000000000000043611422304253700177040ustar00rootroot00000000000000/* * Copyright (C) 2018 Purism SPC * * SPDX-License-Identifier: GPL-3.0+ */ /* WARNING: this file is taken directly from phosh, with no modificaions apart from this message. Please update phosh instead of changing this file. Please copy the file back here afterwards, with the same notice. */ #pragma once #include /* TODO: We use the enum constants from here, use glib-mkenums */ #include "wlr-layer-shell-unstable-v1-client-protocol.h" #define PHOSH_TYPE_LAYER_SURFACE (phosh_layer_surface_get_type ()) G_DECLARE_DERIVABLE_TYPE (PhoshLayerSurface, phosh_layer_surface, PHOSH, LAYER_SURFACE, GtkWindow) /** * PhoshLayerSurfaceClass * @parent_class: The parent class */ struct _PhoshLayerSurfaceClass { GtkWindowClass parent_class; /* Signals */ void (*configured) (PhoshLayerSurface *self); }; GtkWidget *phosh_layer_surface_new (gpointer layer_shell, gpointer wl_output); struct zwlr_layer_surface_v1 *phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self); struct wl_surface *phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self); void phosh_layer_surface_set_size(PhoshLayerSurface *self, gint width, gint height); void phosh_layer_surface_set_margins(PhoshLayerSurface *self, gint top, gint right, gint bottom, gint left); void phosh_layer_surface_set_exclusive_zone(PhoshLayerSurface *self, gint zone); void phosh_layer_surface_set_kbd_interactivity(PhoshLayerSurface *self, gboolean interactivity); void phosh_layer_surface_wl_surface_commit (PhoshLayerSurface *self); squeekboard-v1.17.1/eekboard/000077500000000000000000000000001422304253700160525ustar00rootroot00000000000000squeekboard-v1.17.1/eekboard/eekboard-context-service.c000066400000000000000000000260711422304253700231200ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include "wayland.h" #include "eek/eek-keyboard.h" #include "src/server-context-service.h" #include "eekboard/eekboard-context-service.h" enum { PROP_0, // Magic: without this, keyboard is not useable in g_object_notify PROP_KEYBOARD, PROP_LAST }; enum { DESTROYED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0, }; /** * EekboardContextService: * * Handles layout state, gsettings, and virtual-keyboard. * * TODO: Restrict to managing keyboard layouts, and maybe button repeats, * and the virtual keyboard protocol. * * The #EekboardContextService structure contains only private data * and should only be accessed using the provided API. */ struct _EekboardContextService { GObject parent; struct squeek_layout_state *layout; // Unowned LevelKeyboard *keyboard; // currently used keyboard GSettings *settings; // Owned reference // Maybe TODO: it's used only for fetching layout type. // Maybe let UI push the type to this structure? ServerContextService *ui; // unowned reference /// Needed for keymap changes after keyboard updates struct submission *submission; // unowned }; G_DEFINE_TYPE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT); static void eekboard_context_service_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { (void)value; switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eekboard_context_service_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { EekboardContextService *context = EEKBOARD_CONTEXT_SERVICE(object); switch (prop_id) { case PROP_KEYBOARD: g_value_set_object (value, context->keyboard); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eekboard_context_service_dispose (GObject *object) { G_OBJECT_CLASS (eekboard_context_service_parent_class)-> dispose (object); } static void settings_get_layout(GSettings *settings, char **type, char **layout) { if (!settings) { return; } GVariant *inputs = g_settings_get_value(settings, "sources"); if (g_variant_n_children(inputs) == 0) { g_warning("No system layout present"); *type = NULL; *layout = NULL; } else { // current layout is always first g_variant_get_child(inputs, 0, "(ss)", type, layout); } g_variant_unref(inputs); } void eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *state, uint32_t timestamp) { gchar *layout_name = state->layout_name; gchar *overlay_name = state->overlay_name; // try to get the best keyboard layout if (layout_name == NULL) { layout_name = "us"; } // overlay is "Normal" for most layouts, we will only look for "terminal" in rust code. // for now just avoid passing a null pointer if (overlay_name == NULL) { overlay_name = ""; // fallback to Normal } // generic part follows struct squeek_layout *layout = squeek_load_layout(layout_name, state->arrangement, state->purpose, overlay_name); LevelKeyboard *keyboard = level_keyboard_new(layout); // set as current LevelKeyboard *previous_keyboard = context->keyboard; context->keyboard = keyboard; // Update the keymap if necessary. // TODO: Update submission on change event if (context->submission) { submission_use_layout(context->submission, keyboard->layout, timestamp); } // Update UI g_object_notify (G_OBJECT(context), "keyboard"); // replacing the keyboard above will cause the previous keyboard to get destroyed from the UI side (eek_gtk_keyboard_dispose) if (previous_keyboard) { level_keyboard_free(previous_keyboard); } } static void eekboard_context_service_update_settings_layout(EekboardContextService *context) { g_autofree gchar *keyboard_layout = NULL; g_autofree gchar *keyboard_type = NULL; settings_get_layout(context->settings, &keyboard_type, &keyboard_layout); if (g_strcmp0(context->layout->layout_name, keyboard_layout) != 0 || context->layout->overlay_name) { g_free(context->layout->overlay_name); context->layout->overlay_name = NULL; if (keyboard_layout) { g_free(context->layout->layout_name); context->layout->layout_name = g_strdup(keyboard_layout); } // This must actually update the UI. uint32_t time = gdk_event_get_time(NULL); eekboard_context_service_use_layout(context, context->layout, time); } } static gboolean settings_handle_layout_changed(GSettings *s, gpointer keys, gint n_keys, gpointer user_data) { (void)s; (void)keys; (void)n_keys; EekboardContextService *context = user_data; eekboard_context_service_update_settings_layout(context); return TRUE; } static void eekboard_context_service_constructed (GObject *object) { (void)object; } static void eekboard_context_service_class_init (EekboardContextServiceClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; gobject_class->constructed = eekboard_context_service_constructed; gobject_class->set_property = eekboard_context_service_set_property; gobject_class->get_property = eekboard_context_service_get_property; gobject_class->dispose = eekboard_context_service_dispose; /** * EekboardContextService::destroyed: * @context: an #EekboardContextService * * Emitted when @context is destroyed. */ signals[DESTROYED] = g_signal_new ("destroyed", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * EekboardContextService:keyboard: * * An #EekKeyboard currently active in this context. */ pspec = g_param_spec_pointer("keyboard", "Keyboard", "Keyboard", G_PARAM_READABLE); g_object_class_install_property (gobject_class, PROP_KEYBOARD, pspec); } static void eekboard_context_service_init (EekboardContextService *self) { const char *schema_name = "org.gnome.desktop.input-sources"; GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default(); g_autoptr(GSettingsSchema) schema = NULL; if (!ssrc) { g_warning("No gsettings schemas installed. Layout switching unavailable."); return; } schema = g_settings_schema_source_lookup(ssrc, schema_name, TRUE); if (schema) { // Not referencing the found schema directly, // because it's not clear how... self->settings = g_settings_new (schema_name); gulong conn_id = g_signal_connect(self->settings, "change-event", G_CALLBACK(settings_handle_layout_changed), self); if (conn_id == 0) { g_warning ("Could not connect to gsettings updates, " "automatic layout changing unavailable"); } } else { g_warning("Gsettings schema %s is not installed on the system. " "Layout switching unavailable", schema_name); } } /** * eekboard_context_service_destroy: * @context: an #EekboardContextService * * Destroy @context. */ void eekboard_context_service_destroy (EekboardContextService *context) { g_return_if_fail (EEKBOARD_IS_CONTEXT_SERVICE(context)); g_signal_emit (context, signals[DESTROYED], 0); } /** * eekboard_context_service_get_keyboard: * @context: an #EekboardContextService * * Get keyboard currently active in @context. * Returns: (transfer none): an #EekKeyboard */ LevelKeyboard * eekboard_context_service_get_keyboard (EekboardContextService *context) { return context->keyboard; } void eekboard_context_service_set_hint_purpose(EekboardContextService *context, uint32_t hint, uint32_t purpose) { if (context->layout->hint != hint || context->layout->purpose != purpose) { context->layout->hint = hint; context->layout->purpose = purpose; uint32_t time = gdk_event_get_time(NULL); eekboard_context_service_use_layout(context, context->layout, time); } } void eekboard_context_service_set_overlay(EekboardContextService *context, const char* name) { if (g_strcmp0(context->layout->overlay_name, name)) { g_free(context->layout->overlay_name); context->layout->overlay_name = g_strdup(name); uint32_t time = gdk_event_get_time(NULL); eekboard_context_service_use_layout(context, context->layout, time); } } const char* eekboard_context_service_get_overlay(EekboardContextService *context) { return context->layout->overlay_name; } EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state) { EekboardContextService *context = g_object_new (EEKBOARD_TYPE_CONTEXT_SERVICE, NULL); context->layout = state; eekboard_context_service_update_settings_layout(context); uint32_t time = gdk_event_get_time(NULL); eekboard_context_service_use_layout(context, context->layout, time); return context; } void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission) { context->submission = submission; if (context->submission) { uint32_t time = gdk_event_get_time(NULL); submission_use_layout(context->submission, context->keyboard->layout, time); } } void eekboard_context_service_set_ui(EekboardContextService *context, ServerContextService *ui) { context->ui = ui; } squeekboard-v1.17.1/eekboard/eekboard-context-service.h000066400000000000000000000047221422304253700231240ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #if !defined(__EEKBOARD_SERVICE_H_INSIDE__) && !defined(EEKBOARD_COMPILATION) #error "Only can be included directly." #endif #ifndef EEKBOARD_CONTEXT_SERVICE_H #define EEKBOARD_CONTEXT_SERVICE_H 1 #include "src/submission.h" #include "src/layout.h" #include "virtual-keyboard-unstable-v1-client-protocol.h" #include "text-input-unstable-v3-client-protocol.h" G_BEGIN_DECLS #define EEKBOARD_CONTEXT_SERVICE_PATH "/org/fedorahosted/Eekboard/Context_%d" #define EEKBOARD_CONTEXT_SERVICE_INTERFACE "org.fedorahosted.Eekboard.Context" #define EEKBOARD_TYPE_CONTEXT_SERVICE (eekboard_context_service_get_type()) G_DECLARE_FINAL_TYPE(EekboardContextService, eekboard_context_service, EEKBOARD, CONTEXT_SERVICE, GObject) EekboardContextService *eekboard_context_service_new(struct squeek_layout_state *state); void eekboard_context_service_set_submission(EekboardContextService *context, struct submission *submission); void eekboard_context_service_set_ui(EekboardContextService *context, ServerContextService *ui); void eekboard_context_service_destroy (EekboardContextService *context); LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context); void eekboard_context_service_set_keymap(EekboardContextService *context, const LevelKeyboard *keyboard); void eekboard_context_service_set_hint_purpose(EekboardContextService *context, uint32_t hint, uint32_t purpose); void eekboard_context_service_use_layout(EekboardContextService *context, struct squeek_layout_state *layout, uint32_t timestamp); G_END_DECLS #endif /* EEKBOARD_CONTEXT_SERVICE_H */ squeekboard-v1.17.1/examples/000077500000000000000000000000001422304253700161145ustar00rootroot00000000000000squeekboard-v1.17.1/examples/test_layout.rs000066400000000000000000000004161422304253700210370ustar00rootroot00000000000000extern crate rs; use rs::tests::check_builtin_layout; use std::env; fn main() -> () { check_builtin_layout( env::args().nth(1).expect("No argument given").as_str(), env::args().nth(2).map(|s| s == "allow_missing_return").unwrap_or(false), ); } squeekboard-v1.17.1/meson.build000066400000000000000000000061141422304253700164420ustar00rootroot00000000000000project( 'squeekboard', 'c', 'rust', version: '1.17.1', license: 'GPLv3', meson_version: '>=0.51.0', default_options: [ 'warning_level=1', 'buildtype=debugoptimized', 'c_std=gnu11' ] ) add_project_arguments( [ '-Werror=implicit-function-declaration', '-Werror=implicit-fallthrough=3', '-Werror=maybe-uninitialized', '-Werror=missing-field-initializers', '-Werror=incompatible-pointer-types', '-Werror=int-conversion', '-Werror=redundant-decls', '-Werror=parentheses', '-Wformat-nonliteral', '-Wformat-security', '-Wformat', '-Winit-self', '-Wmaybe-uninitialized', '-Wold-style-definition', '-Wredundant-decls', '-Wstrict-prototypes', '-Wunused', ], language: 'c' ) i18n = import('i18n') if get_option('buildtype').startswith('debug') add_project_arguments('-DDEBUG=1', language : 'c') endif if get_option('strict') add_project_arguments( [ '-Werror', ], language: 'c' ) endif if get_option('buildtype') != 'plain' add_project_arguments('-fstack-protector-strong', language: 'c') endif if get_option('buildtype') == 'release' cargo_build_flags = ['--release'] # for artifacts else cargo_build_flags = [] endif prefix = get_option('prefix') bindir = join_paths(prefix, get_option('bindir')) datadir = join_paths(prefix, get_option('datadir')) localedir = join_paths(prefix, get_option('localedir')) desktopdir = join_paths(datadir, 'applications') pkgdatadir = join_paths(datadir, meson.project_name()) if get_option('depdatadir') == '' depdatadir = datadir else depdatadir = get_option('depdatadir') endif dbusdir = join_paths(depdatadir, 'dbus-1/interfaces') conf_data = configuration_data() conf_data.set_quoted('GETTEXT_PACKAGE', 'squeekboard') conf_data.set_quoted('LOCALEDIR', localedir) summary = [ '', '------------------', 'squeekboard @0@'.format(meson.project_version()), '', '------------------', '' ] message('\n'.join(summary)) # Rust deps are changing, depending on compile flags. Cargo can't handle it alone. # As a side effect, Cargo.toml never gets used. cargo_toml_in = files('Cargo.toml.in') path_data = configuration_data() path_data.set('path', meson.source_root()) cargo_toml_base = configure_file( input: 'Cargo.toml.in', output: 'Cargo.toml.base', configuration: path_data, ) cargo_patch = [] if get_option('newer') == true cargo_build_flags += ['--features', 'glib_v0_14'] cargo_deps = files('Cargo.deps.newer') else cargo_deps = files('Cargo.deps') if get_option('online') == true cargo_patch = [files('Cargo.deps.online')] endif endif cat = find_program('cat') cargo_toml = custom_target( 'Cargo.toml', output: 'Cargo.toml', command: [cat, cargo_toml_base, cargo_deps] + cargo_patch, capture: true, ) dep_cargo = find_program('cargo') cargo_script = find_program('cargo.sh') cargo_build = find_program('cargo_build.py') subdir('data') subdir('po') subdir('protocols') subdir('src') subdir('tools') subdir('tests') squeekboard-v1.17.1/meson_options.txt000066400000000000000000000012541422304253700177350ustar00rootroot00000000000000option('depdatadir', type : 'string', value : '', description : 'System data path. Will be searched for definitions instead of datadir when provided') option('tests', type: 'boolean', value: true, description: 'Whether to compile unit tests') option('newer', type: 'boolean', value: false, description: 'Build with dependencies newer than those of Byzantium') option('online', type: 'boolean', value: true, description: 'Pull packages from the internet while building, as opposed to a local regstry.') option('strict', type: 'boolean', value: true, description: 'Turn more warnings into errors') squeekboard-v1.17.1/po/000077500000000000000000000000001422304253700147145ustar00rootroot00000000000000squeekboard-v1.17.1/po/LINGUAS000066400000000000000000000000531422304253700157370ustar00rootroot00000000000000ca de fa fi fur gl he nl pt_BR ro sl uk sv squeekboard-v1.17.1/po/POTFILES.in000066400000000000000000000000671422304253700164740ustar00rootroot00000000000000data/popover.ui data/sm.puri.Squeekboard.desktop.in.in squeekboard-v1.17.1/po/ca.po000066400000000000000000000024331422304253700156410ustar00rootroot00000000000000# Catalan translation for squeekboard. # Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # maite , 2022. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2022-01-11 14:31+0000\n" "PO-Revision-Date: 2022-01-20 10:53+0100\n" "Last-Translator: maite guix \n" "Language-Team: Catalan \n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.0.1\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Emoji" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Terminal" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Configuració del teclat" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Teclat virtual" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Teclat en pantalla" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "Un teclat virtual en pantalla" squeekboard-v1.17.1/po/de.po000066400000000000000000000012741422304253700156500ustar00rootroot00000000000000# German translations for squeekboard package. # Copyright (C) 2021 THE squeekboard'S COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # Automatically generated, 2021. # msgid "" msgstr "" "Project-Id-Version: squeekboard\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-03 18:41+0100\n" "PO-Revision-Date: 2021-12-03 18:41+0100\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ASCII\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: data/popup.ui:15 msgid "Keyboard Settings" msgstr "Tastatureinstellungen" squeekboard-v1.17.1/po/fa.po000066400000000000000000000025131422304253700156430ustar00rootroot00000000000000# Persian translation for squeekboard. # Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # Danial Behzadi , 2022. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2021-12-26 15:15+0000\n" "PO-Revision-Date: 2022-01-11 18:01+0330\n" "Language-Team: Persian \n" "Language: fa\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Last-Translator: Danial Behzadi \n" "X-Generator: Poedit 3.0\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "شکلک" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "پایانه" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "تنظیمات صفحه‌کلید" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "اسکوییک‌برد" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "صفحه‌کلید لمسی" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "یک صفحهٔ کلید لمسی مجازی" squeekboard-v1.17.1/po/fi.po000066400000000000000000000025551422304253700156610ustar00rootroot00000000000000# Finnish translation for squeekboard. # Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # Jiri Grönroos , 2021. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2021-12-25 13:55+0000\n" "PO-Revision-Date: 2021-12-26 17:15+0200\n" "Last-Translator: Jiri Grönroos \n" "Language-Team: Finnish \n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.0.1\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Emoji" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Pääte" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Näppäimistön asetukset" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Näyttönäppäimistö" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "Virtuaalinen näyttönäppäimistö" squeekboard-v1.17.1/po/fur.po000066400000000000000000000024211422304253700160470ustar00rootroot00000000000000# Friulian translation for squeekboard. # Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # Fabio Tomat , 2021. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2021-12-22 13:33+0000\n" "PO-Revision-Date: 2021-12-22 15:06+0100\n" "Last-Translator: Fabio Tomat \n" "Language-Team: Friulian \n" "Language: fur\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.0.1\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Emoji" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Terminâl" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Impostazions tastiere" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Tastiere a visôr" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "Une tastiere virtuâl a visôr" squeekboard-v1.17.1/po/gl.po000066400000000000000000000027651422304253700156700ustar00rootroot00000000000000# Galician translation for squeekboard. # Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # FIRST AUTHOR , YEAR. # Fran Diéguez , 2022. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2022-02-02 17:41+0000\n" "PO-Revision-Date: 2022-02-04 16:18+0100\n" "Last-Translator: Fran Diéguez \n" "Language-Team: Galician \n" "Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-DL-Team: gl\n" "X-DL-Module: squeekboard\n" "X-DL-Branch: master\n" "X-DL-Domain: po\n" "X-DL-State: Translating\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "X-Generator: Gtranslator 41.0\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Emoticono" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Terminal" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Preferencias de teclado" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Teclado en pantalla" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "Un teclado en pantalla virtual" squeekboard-v1.17.1/po/he.po000066400000000000000000000025131422304253700156510ustar00rootroot00000000000000# Hebrew translation for squeekboard. # Copyright (C) 2022 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # Yosef Or Boczko , 2022. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2022-02-04 15:22+0000\n" "PO-Revision-Date: 2022-02-14 18:05+0200\n" "Last-Translator: Yosef Or Boczko \n" "Language-Team: Hebrew <>\n" "Language: he\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 40.0\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "רגשון" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "מסוף" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "הגדרות מקלדת" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "מקלדת על המסך" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "מקלדת מדומה על המסך" squeekboard-v1.17.1/po/meson.build000066400000000000000000000001031422304253700170500ustar00rootroot00000000000000i18n = import('i18n') i18n.gettext('squeekboard', preset : 'glib') squeekboard-v1.17.1/po/nl.po000066400000000000000000000026411422304253700156700ustar00rootroot00000000000000# Dutch translation for squeekboard. # Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # Jan Jasper de Kroon , 2021. # Nathan Follens , 2021. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2021-12-23 15:18+0000\n" "PO-Revision-Date: 2021-12-25 14:04+0100\n" "Last-Translator: Nathan Follens \n" "Language-Team: Dutch \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.0.1\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Emoji" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Terminal" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Toetsenbordinstellingen" # Dit is de naam van de applicatie #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Schermtoetsenbord" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "Een virtueel schermtoetsenbord" squeekboard-v1.17.1/po/pt_BR.po000066400000000000000000000026611422304253700162670ustar00rootroot00000000000000# Brazilian Portuguese translation for squeekboard. # Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # Rafael Fontenelle , 2021. # Luís Fernando Stürmer da Rosa , 2021. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2021-12-22 12:39+0000\n" "PO-Revision-Date: 2022-01-30 12:34-0300\n" "Last-Translator: Luís Fernando Stürmer da Rosa \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Poedit 3.0\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Emoji" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Terminal" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Configurações do teclado" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Teclado virtual" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "Um teclado virtual" squeekboard-v1.17.1/po/ro.po000066400000000000000000000025671422304253700157060ustar00rootroot00000000000000# Romanian translation for squeekboard. # Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # libre , 2021. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2021-12-22 14:45+0000\n" "PO-Revision-Date: 2021-12-22 20:05+0100\n" "Last-Translator: libre \n" "Language-Team: Romanian \n" "Language: ro\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " "20)) ? 1 : 2);;\n" "X-Generator: Gtranslator 3.30.1\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Emoji" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Terminal" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Opțiuni tastatură" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Tastatură pe ecran" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "O tastatură virtuală pe ecran" squeekboard-v1.17.1/po/sl.po000066400000000000000000000027311422304253700156750ustar00rootroot00000000000000# Slovenian translation for squeekboard. # Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # # Matej Urbančič , 2021. # msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2021-12-22 19:14+0000\n" "PO-Revision-Date: 2021-12-23 16:17+0100\n" "Last-Translator: Matej Urbančič \n" "Language-Team: Slovenian GNOME Translation Team \n" "Language: sl_SI\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" "%100==4 ? 3 : 0);\n" "X-Poedit-SourceCharset: utf-8\n" "X-Generator: Poedit 3.0.1\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Izrazne ikone" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Terminal" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Nastavitve tipkovnice" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Cvilkovnica" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Zaslonska tipkovnica" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "Navidezna zaslonska tipkovnica" squeekboard-v1.17.1/po/sv.po000066400000000000000000000024531422304253700157100ustar00rootroot00000000000000# Swedish translations for squeekboard package. # Copyright (C) 2021 THE squeekboard'S COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # Automatically generated, 2021. # # Luna Jernberg , 2021. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/" "issues\n" "POT-Creation-Date: 2021-12-22 12:47+0000\n" "PO-Revision-Date: 2021-12-22 14:15+0100\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.0\n" "Last-Translator: \n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "Language: sv\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "Emoji" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "Terminal" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "Tangentbordsinställningar" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "Skärmtangentbord" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "Ett virtuellt skärmtangentbord" squeekboard-v1.17.1/po/uk.po000066400000000000000000000030071422304253700156730ustar00rootroot00000000000000# Ukrainian translation for squeekboard. # Copyright (C) 2021 squeekboard's COPYRIGHT HOLDER # This file is distributed under the same license as the squeekboard package. # # Yuri Chornoivan , 2021. msgid "" msgstr "" "Project-Id-Version: squeekboard master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/issues\n" "POT-Creation-Date: 2021-12-22 10:36+0000\n" "PO-Revision-Date: 2021-12-22 14:46+0200\n" "Last-Translator: Yuri Chornoivan \n" "Language-Team: Ukrainian \n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Lokalize 20.12.0\n" #. translators: This is a emmoji keyboard layout #: data/popover.ui:6 msgid "Emoji" msgstr "" "Емодзі" #. translators: This is a terminal keyboard layout #: data/popover.ui:12 msgid "Terminal" msgstr "" "Термінал" #: data/popover.ui:18 msgid "Keyboard Settings" msgstr "" "Параметри клавіатури" #: data/sm.puri.Squeekboard.desktop.in.in:3 msgid "Squeekboard" msgstr "" "Squeekboard" #: data/sm.puri.Squeekboard.desktop.in.in:4 msgid "On Screen Keyboard" msgstr "" "Екранна клавіатура" #: data/sm.puri.Squeekboard.desktop.in.in:5 msgid "An on screen virtual keyboard" msgstr "" "Екранна віртуальна клавіатура" squeekboard-v1.17.1/protocols/000077500000000000000000000000001422304253700163225ustar00rootroot00000000000000squeekboard-v1.17.1/protocols/input-method-unstable-v2.xml000066400000000000000000000513731422304253700236320ustar00rootroot00000000000000 Copyright © 2008-2011 Kristian Høgsberg Copyright © 2010-2011 Intel Corporation Copyright © 2012-2013 Collabora, Ltd. Copyright © 2012, 2013 Intel Corporation Copyright © 2015, 2016 Jan Arne Petersen Copyright © 2017, 2018 Red Hat, Inc. Copyright © 2018 Purism SPC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. This protocol allows applications to act as input methods for compositors. An input method context is used to manage the state of the input method. Text strings are UTF-8 encoded, their indices and lengths are in bytes. This document adheres to the RFC 2119 when using words like "must", "should", "may", etc. Warning! The protocol described in this file is experimental and backward incompatible changes may be made. Backward compatible changes may be added together with the corresponding interface version bump. Backward incompatible changes are done by bumping the version number in the protocol and interface names and resetting the interface version. Once the protocol is to be declared stable, the 'z' prefix and the version number in the protocol and interface names are removed and the interface version number is reset. An input method object allows for clients to compose text. The objects connects the client to a text input in an application, and lets the client to serve as an input method for a seat. The zwp_input_method_v2 object can occupy two distinct states: active and inactive. In the active state, the object is associated to and communicates with a text input. In the inactive state, there is no associated text input, and the only communication is with the compositor. Initially, the input method is in the inactive state. Requests issued in the inactive state must be accepted by the compositor. Because of the serial mechanism, and the state reset on activate event, they will not have any effect on the state of the next text input. There must be no more than one input method object per seat. Notification that a text input focused on this seat requested the input method to be activated. This event serves the purpose of providing the compositor with an active input method. This event resets all state associated with previous enable, disable, surrounding_text, text_change_cause, and content_type events, as well as the state associated with set_preedit_string, commit_string, and delete_surrounding_text requests. In addition, it marks the zwp_input_method_v2 object as active, and makes any existing zwp_input_popup_surface_v2 objects visible. The surrounding_text, and content_type events must follow before the next done event if the text input supports the respective functionality. State set with this event is double-buffered. It will get applied on the next zwp_input_method_v2.done event, and stay valid until changed. Notification that no focused text input currently needs an active input method on this seat. This event marks the zwp_input_method_v2 object as inactive. The compositor must make all existing zwp_input_popup_surface_v2 objects invisible until the next activate event. State set with this event is double-buffered. It will get applied on the next zwp_input_method_v2.done event, and stay valid until changed. Updates the surrounding plain text around the cursor, excluding the preedit text. If any preedit text is present, it is replaced with the cursor for the purpose of this event. The argument text is a buffer containing the preedit string, and must include the cursor position, and the complete selection. It should contain additional characters before and after these. There is a maximum length of wayland messages, so text can not be longer than 4000 bytes. cursor is the byte offset of the cursor within the text buffer. anchor is the byte offset of the selection anchor within the text buffer. If there is no selected text, anchor must be the same as cursor. If this event does not arrive before the first done event, the input method may assume that the text input does not support this functionality and ignore following surrounding_text events. Values set with this event are double-buffered. They will get applied and set to initial values on the next zwp_input_method_v2.done event. The initial state for affected fields is empty, meaning that the text input does not support sending surrounding text. If the empty values get applied, subsequent attempts to change them may have no effect. Tells the input method why the text surrounding the cursor changed. Whenever the client detects an external change in text, cursor, or anchor position, it must issue this request to the compositor. This request is intended to give the input method a chance to update the preedit text in an appropriate way, e.g. by removing it when the user starts typing with a keyboard. cause describes the source of the change. The value set with this event is double-buffered. It will get applied and set to its initial value on the next zwp_input_method_v2.done event. The initial value of cause is input_method. Indicates the content type and hint for the current zwp_input_method_v2 instance. Values set with this event are double-buffered. They will get applied on the next zwp_input_method_v2.done event. The initial value for hint is none, and the initial value for purpose is normal. Atomically applies state changes recently sent to the client. The done event establishes and updates the state of the client, and must be issued after any changes to apply them. Text input state (content purpose, content hint, surrounding text, and change cause) is conceptually double-buffered within an input method context. Events modify the pending state, as opposed to the current state in use by the input method. A done event atomically applies all pending state, replacing the current state. After done, the new pending state is as documented for each related request. Events must be applied in the order of arrival. Neither current nor pending state are modified unless noted otherwise. Send the commit string text for insertion to the application. Inserts a string at current cursor position (see commit event sequence). The string to commit could be either just a single character after a key press or the result of some composing. The argument text is a buffer containing the string to insert. There is a maximum length of wayland messages, so text can not be longer than 4000 bytes. Values set with this event are double-buffered. They must be applied and reset to initial on the next zwp_text_input_v3.commit request. The initial value of text is an empty string. Send the pre-edit string text to the application text input. Place a new composing text (pre-edit) at the current cursor position. Any previously set composing text must be removed. Any previously existing selected text must be removed. The cursor is moved to a new position within the preedit string. The argument text is a buffer containing the preedit string. There is a maximum length of wayland messages, so text can not be longer than 4000 bytes. The arguments cursor_begin and cursor_end are counted in bytes relative to the beginning of the submitted string buffer. Cursor should be hidden by the text input when both are equal to -1. cursor_begin indicates the beginning of the cursor. cursor_end indicates the end of the cursor. It may be equal or different than cursor_begin. Values set with this event are double-buffered. They must be applied on the next zwp_input_method_v2.commit event. The initial value of text is an empty string. The initial value of cursor_begin, and cursor_end are both 0. Remove the surrounding text. before_length and after_length are the number of bytes before and after the current cursor index (excluding the preedit text) to delete. If any preedit text is present, it is replaced with the cursor for the purpose of this event. In effect before_length is counted from the beginning of preedit text, and after_length from its end (see commit event sequence). Values set with this event are double-buffered. They must be applied and reset to initial on the next zwp_input_method_v2.commit request. The initial values of both before_length and after_length are 0. Apply state changes from commit_string, set_preedit_string and delete_surrounding_text requests. The state relating to these events is double-buffered, and each one modifies the pending state. This request replaces the current state with the pending state. The connected text input is expected to proceed by evaluating the changes in the following order: 1. Replace existing preedit string with the cursor. 2. Delete requested surrounding text. 3. Insert commit string with the cursor at its end. 4. Calculate surrounding text to send. 5. Insert new preedit text in cursor position. 6. Place cursor inside preedit text. The serial number reflects the last state of the zwp_input_method_v2 object known to the client. The value of the serial argument must be equal to the number of done events already issued by that object. When the compositor receives a commit request with a serial different than the number of past done events, it must proceed as normal, except it should not change the current state of the zwp_input_method_v2 object. Creates a new zwp_input_popup_surface_v2 object wrapping a given surface. The surface gets assigned the "input_popup" role. If the surface already has an assigned role, the compositor must issue a protocol error. Allow an input method to receive hardware keyboard input and process key events to generate text events (with pre-edit) over the wire. This allows input methods which compose multiple key events for inputting text like it is done for CJK languages. The compositor should send all keyboard events on the seat to the grab holder via the returned wl_keyboard object. Nevertheless, the compositor may decide not to forward any particular event. The compositor must not further process any event after it has been forwarded to the grab holder. Releasing the resulting wl_keyboard object releases the grab. The input method ceased to be available. The compositor must issue this event as the only event on the object if there was another input_method object associated with the same seat at the time of its creation. The compositor must issue this request when the object is no longer useable, e.g. due to seat removal. The input method context becomes inert and should be destroyed after deactivation is handled. Any further requests and events except for the destroy request must be ignored. Destroys the zwp_text_input_v2 object and any associated child objects, i.e. zwp_input_popup_surface_v2 and zwp_input_method_keyboard_grab_v2. This interface marks a surface as a popup for interacting with an input method. The compositor should place it near the active text input area. It must be visible if and only if the input method is in the active state. The client must not destroy the underlying wl_surface while the zwp_input_popup_surface_v2 object exists. Notify about the position of the area of the text input expressed as a rectangle in surface local coordinates. This is a hint to the input method telling it the relative position of the text being entered. The zwp_input_method_keyboard_grab_v2 interface represents an exclusive grab of the wl_keyboard interface associated with the seat. This event provides a file descriptor to the client which can be memory-mapped to provide a keyboard mapping description. A key was pressed or released. The time argument is a timestamp with millisecond granularity, with an undefined base. Notifies clients that the modifier and/or group state has changed, and it should update its local state. Informs the client about the keyboard's repeat rate and delay. This event is sent as soon as the zwp_input_method_keyboard_grab_v2 object has been created, and is guaranteed to be received by the client before any key press event. Negative values for either rate or delay are illegal. A rate of zero will disable any repeating (regardless of the value of delay). This event can be sent later on as well with a new value if necessary, so clients should continue listening for the event past the creation of zwp_input_method_keyboard_grab_v2. The input method manager allows the client to become the input method on a chosen seat. No more than one input method must be associated with any seat at any given time. Request a new input zwp_input_method_v2 object associated with a given seat. Destroys the zwp_input_method_manager_v2 object. The zwp_input_method_v2 objects originating from it remain valid. squeekboard-v1.17.1/protocols/meson.build000066400000000000000000000015461422304253700204720ustar00rootroot00000000000000wayland_protos = dependency('wayland-protocols', version: '>=1.12') wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') wl_scanner = find_program('wayland-scanner') gen_scanner_client_header = generator(wl_scanner, output: '@BASENAME@-client-protocol.h', arguments: ['client-header', '@INPUT@', '@OUTPUT@']) gen_scanner_client_code = generator(wl_scanner, output: '@BASENAME@-protocol.c', arguments: ['private-code', '@INPUT@', '@OUTPUT@']) wl_protos = [ wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml', 'wlr-layer-shell-unstable-v1.xml', 'virtual-keyboard-unstable-v1.xml', 'input-method-unstable-v2.xml', 'text-input-unstable-v3.xml' ] wl_proto_sources = [] foreach proto: wl_protos wl_proto_sources += gen_scanner_client_header.process(proto) wl_proto_sources += gen_scanner_client_code.process(proto) endforeach squeekboard-v1.17.1/protocols/text-input-unstable-v3.xml000066400000000000000000000513101422304253700233260ustar00rootroot00000000000000 Copyright © 2012, 2013 Intel Corporation Copyright © 2015, 2016 Jan Arne Petersen Copyright © 2017, 2018 Red Hat, Inc. Copyright © 2018 Purism SPC Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the copyright holders not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. The copyright holders make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. This protocol allows compositors to act as input methods and to send text to applications. A text input object is used to manage state of what are typically text entry fields in the application. This document adheres to the RFC 2119 when using words like "must", "should", "may", etc. Warning! The protocol described in this file is experimental and backward incompatible changes may be made. Backward compatible changes may be added together with the corresponding interface version bump. Backward incompatible changes are done by bumping the version number in the protocol and interface names and resetting the interface version. Once the protocol is to be declared stable, the 'z' prefix and the version number in the protocol and interface names are removed and the interface version number is reset. The zwp_text_input_v3 interface represents text input and input methods associated with a seat. It provides enter/leave events to follow the text input focus for a seat. Requests are used to enable/disable the text-input object and set state information like surrounding and selected text or the content type. The information about the entered text is sent to the text-input object via the preedit_string and commit_string events. Text is valid UTF-8 encoded, indices and lengths are in bytes. Indices must not point to middle bytes inside a code point: they must either point to the first byte of a code point or to the end of the buffer. Lengths must be measured between two valid indices. Focus moving throughout surfaces will result in the emission of zwp_text_input_v3.enter and zwp_text_input_v3.leave events. The focused surface must commit zwp_text_input_v3.enable and zwp_text_input_v3.disable requests as the keyboard focus moves across editable and non-editable elements of the UI. Those two requests are not expected to be paired with each other, the compositor must be able to handle consecutive series of the same request. State is sent by the state requests (set_surrounding_text, set_content_type and set_cursor_rectangle) and a commit request. After an enter event or disable request all state information is invalidated and needs to be resent by the client. Destroy the wp_text_input object. Also disables all surfaces enabled through this wp_text_input object. Requests text input on the surface previously obtained from the enter event. This request must be issued every time the active text input changes to a new one, including within the current surface. Use zwp_text_input_v3.disable when there is no longer any input focus on the current surface. Clients must not enable more than one text input on the single seat and should disable the current text input before enabling the new one. At most one instance of text input may be in enabled state per instance, Requests to enable the another text input when some text input is active must be ignored by compositor. This request resets all state associated with previous enable, disable, set_surrounding_text, set_text_change_cause, set_content_type, and set_cursor_rectangle requests, as well as the state associated with preedit_string, commit_string, and delete_surrounding_text events. The set_surrounding_text, set_content_type and set_cursor_rectangle requests must follow if the text input supports the necessary functionality. State set with this request is double-buffered. It will get applied on the next zwp_text_input_v3.commit request, and stay valid until the next committed enable or disable request. The changes must be applied by the compositor after issuing a zwp_text_input_v3.commit request. Explicitly disable text input on the current surface (typically when there is no focus on any text entry inside the surface). State set with this request is double-buffered. It will get applied on the next zwp_text_input_v3.commit request. Sets the surrounding plain text around the input, excluding the preedit text. The client should notify the compositor of any changes in any of the values carried with this request, including changes caused by handling incoming text-input events as well as changes caused by other mechanisms like keyboard typing. If the client is unaware of the text around the cursor, it should not issue this request, to signify lack of support to the compositor. Text is UTF-8 encoded, and should include the cursor position, the complete selection and additional characters before and after them. There is a maximum length of wayland messages, so text can not be longer than 4000 bytes. Cursor is the byte offset of the cursor within text buffer. Anchor is the byte offset of the selection anchor within text buffer. If there is no selected text, anchor is the same as cursor. If any preedit text is present, it is replaced with a cursor for the purpose of this event. Values set with this request are double-buffered. They will get applied on the next zwp_text_input_v3.commit request, and stay valid until the next committed enable or disable request. The initial state for affected fields is empty, meaning that the text input does not support sending surrounding text. If the empty values get applied, subsequent attempts to change them may have no effect. Reason for the change of surrounding text or cursor posision. Tells the compositor why the text surrounding the cursor changed. Whenever the client detects an external change in text, cursor, or anchor posision, it must issue this request to the compositor. This request is intended to give the input method a chance to update the preedit text in an appropriate way, e.g. by removing it when the user starts typing with a keyboard. cause describes the source of the change. The value set with this request is double-buffered. It must be applied and reset to initial at the next zwp_text_input_v3.commit request. The initial value of cause is input_method. Content hint is a bitmask to allow to modify the behavior of the text input. The content purpose allows to specify the primary purpose of a text input. This allows an input method to show special purpose input panels with extra characters or to disallow some characters. Sets the content purpose and content hint. While the purpose is the basic purpose of an input field, the hint flags allow to modify some of the behavior. Values set with this request are double-buffered. They will get applied on the next zwp_text_input_v3.commit request. Subsequent attempts to update them may have no effect. The values remain valid until the next committed enable or disable request. The initial value for hint is none, and the initial value for purpose is normal. Marks an area around the cursor as a x, y, width, height rectangle in surface local coordinates. Allows the compositor to put a window with word suggestions near the cursor, without obstructing the text being input. If the client is unaware of the position of edited text, it should not issue this request, to signify lack of support to the compositor. Values set with this request are double-buffered. They will get applied on the next zwp_text_input_v3.commit request, and stay valid until the next committed enable or disable request. The initial values describing a cursor rectangle are empty. That means the text input does not support describing the cursor area. If the empty values get applied, subsequent attempts to change them may have no effect. Atomically applies state changes recently sent to the compositor. The commit request establishes and updates the state of the client, and must be issued after any changes to apply them. Text input state (enabled status, content purpose, content hint, surrounding text and change cause, cursor rectangle) is conceptually double-buffered within the context of a text input, i.e. between a committed enable request and the following committed enable or disable request. Protocol requests modify the pending state, as opposed to the current state in use by the input method. A commit request atomically applies all pending state, replacing the current state. After commit, the new pending state is as documented for each related request. Requests are applied in the order of arrival. Neither current nor pending state are modified unless noted otherwise. The compositor must count the number of commit requests coming from each zwp_text_input_v3 object and use the count as the serial in done events. Notification that this seat's text-input focus is on a certain surface. If client has created multiple text input objects, compositor must send this event to all of them. When the seat has the keyboard capability the text-input focus follows the keyboard focus. This event sets the current surface for the text-input object. Notification that this seat's text-input focus is no longer on a certain surface. The client should reset any preedit string previously set. The leave notification clears the current surface. It is sent before the enter notification for the new focus. After leave event, compositor must ignore requests from any text input instances until next enter event. When the seat has the keyboard capability the text-input focus follows the keyboard focus. Notify when a new composing text (pre-edit) should be set at the current cursor position. Any previously set composing text must be removed. Any previously existing selected text must be removed. The argument text contains the pre-edit string buffer. The parameters cursor_begin and cursor_end are counted in bytes relative to the beginning of the submitted text buffer. Cursor should be hidden when both are equal to -1. They could be represented by the client as a line if both values are the same, or as a text highlight otherwise. Values set with this event are double-buffered. They must be applied and reset to initial on the next zwp_text_input_v3.done event. The initial value of text is an empty string, and cursor_begin, cursor_end and cursor_hidden are all 0. Notify when text should be inserted into the editor widget. The text to commit could be either just a single character after a key press or the result of some composing (pre-edit). Values set with this event are double-buffered. They must be applied and reset to initial on the next zwp_text_input_v3.done event. The initial value of text is an empty string. Notify when the text around the current cursor position should be deleted. Before_length and after_length are the number of bytes before and after the current cursor index (excluding the selection) to delete. If a preedit text is present, in effect before_length is counted from the beginning of it, and after_length from its end (see done event sequence). Values set with this event are double-buffered. They must be applied and reset to initial on the next zwp_text_input_v3.done event. The initial values of both before_length and after_length are 0. Instruct the application to apply changes to state requested by the preedit_string, commit_string and delete_surrounding_text events. The state relating to these events is double-buffered, and each one modifies the pending state. This event replaces the current state with the pending state. The application must proceed by evaluating the changes in the following order: 1. Replace existing preedit string with the cursor. 2. Delete requested surrounding text. 3. Insert commit string with the cursor at its end. 4. Calculate surrounding text to send. 5. Insert new preedit text in cursor position. 6. Place cursor inside preedit text. The serial number reflects the last state of the zwp_text_input_v3 object known to the compositor. The value of the serial argument must be equal to the number of commit requests already issued on that object. When the client receives a done event with a serial different than the number of past commit requests, it must proceed as normal, except it should not change the current state of the zwp_text_input_v3 object. A factory for text-input objects. This object is a global singleton. Destroy the wp_text_input_manager object. Creates a new text-input object for a given seat. squeekboard-v1.17.1/protocols/virtual-keyboard-unstable-v1.xml000066400000000000000000000114321422304253700244700ustar00rootroot00000000000000 Copyright © 2008-2011 Kristian Høgsberg Copyright © 2010-2013 Intel Corporation Copyright © 2012-2013 Collabora, Ltd. Copyright © 2018 Purism SPC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The virtual keyboard provides an application with requests which emulate the behaviour of a physical keyboard. This interface can be used by clients on its own to provide raw input events, or it can accompany the input method protocol. Provide a file descriptor to the compositor which can be memory-mapped to provide a keyboard mapping description. Format carries a value from the keymap_format enumeration. A key was pressed or released. The time argument is a timestamp with millisecond granularity, with an undefined base. All requests regarding a single object must share the same clock. Keymap must be set before issuing this request. State carries a value from the key_state enumeration. Notifies the compositor that the modifier and/or group state has changed, and it should update state. The client should use wl_keyboard.modifiers event to synchronize its internal state with seat state. Keymap must be set before issuing this request. A virtual keyboard manager allows an application to provide keyboard input events as if they came from a physical keyboard. Creates a new virtual keyboard associated to a seat. If the compositor enables a keyboard to perform arbitrary actions, it should present an error when an untrusted client requests a new keyboard. squeekboard-v1.17.1/protocols/wlr-layer-shell-unstable-v1.xml000066400000000000000000000320701422304253700242300ustar00rootroot00000000000000 Copyright © 2017 Drew DeVault Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the copyright holders not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. The copyright holders make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Clients can use this interface to assign the surface_layer role to wl_surfaces. Such surfaces are assigned to a "layer" of the output and rendered with a defined z-depth respective to each other. They may also be anchored to the edges and corners of a screen and specify input handling semantics. This interface should be suitable for the implementation of many desktop shell components, and a broad number of other applications that interact with the desktop. Create a layer surface for an existing surface. This assigns the role of layer_surface, or raises a protocol error if another role is already assigned. Creating a layer surface from a wl_surface which has a buffer attached or committed is a client error, and any attempts by a client to attach or manipulate a buffer prior to the first layer_surface.configure call must also be treated as errors. You may pass NULL for output to allow the compositor to decide which output to use. Generally this will be the one that the user most recently interacted with. Clients can specify a namespace that defines the purpose of the layer surface. These values indicate which layers a surface can be rendered in. They are ordered by z depth, bottom-most first. Traditional shell surfaces will typically be rendered between the bottom and top layers. Fullscreen shell surfaces are typically rendered at the top layer. Multiple surfaces can share a single layer, and ordering within a single layer is undefined. An interface that may be implemented by a wl_surface, for surfaces that are designed to be rendered as a layer of a stacked desktop-like environment. Layer surface state (size, anchor, exclusive zone, margin, interactivity) is double-buffered, and will be applied at the time wl_surface.commit of the corresponding wl_surface is called. Sets the size of the surface in surface-local coordinates. The compositor will display the surface centered with respect to its anchors. If you pass 0 for either value, the compositor will assign it and inform you of the assignment in the configure event. You must set your anchor to opposite edges in the dimensions you omit; not doing so is a protocol error. Both values are 0 by default. Size is double-buffered, see wl_surface.commit. Requests that the compositor anchor the surface to the specified edges and corners. If two orthogonal edges are specified (e.g. 'top' and 'left'), then the anchor point will be the intersection of the edges (e.g. the top left corner of the output); otherwise the anchor point will be centered on that edge, or in the center if none is specified. Anchor is double-buffered, see wl_surface.commit. Requests that the compositor avoids occluding an area of the surface with other surfaces. The compositor's use of this information is implementation-dependent - do not assume that this region will not actually be occluded. A positive value is only meaningful if the surface is anchored to an edge, rather than a corner. The zone is the number of surface-local coordinates from the edge that is considered exclusive. Surfaces that do not wish to have an exclusive zone may instead specify how they should interact with surfaces that do. If set to zero, the surface indicates that it would like to be moved to avoid occluding surfaces with a positive exclusive zone. If set to -1, the surface indicates that it would not like to be moved to accommodate for other surfaces, and the compositor should extend it all the way to the edges it is anchored to. For example, a panel might set its exclusive zone to 10, so that maximized shell surfaces are not shown on top of it. A notification might set its exclusive zone to 0, so that it is moved to avoid occluding the panel, but shell surfaces are shown underneath it. A wallpaper or lock screen might set their exclusive zone to -1, so that they stretch below or over the panel. The default value is 0. Exclusive zone is double-buffered, see wl_surface.commit. Requests that the surface be placed some distance away from the anchor point on the output, in surface-local coordinates. Setting this value for edges you are not anchored to has no effect. The exclusive zone includes the margin. Margin is double-buffered, see wl_surface.commit. Set to 1 to request that the seat send keyboard events to this layer surface. For layers below the shell surface layer, the seat will use normal focus semantics. For layers above the shell surface layers, the seat will always give exclusive keyboard focus to the top-most layer which has keyboard interactivity set to true. Layer surfaces receive pointer, touch, and tablet events normally. If you do not want to receive them, set the input region on your surface to an empty region. Events is double-buffered, see wl_surface.commit. This assigns an xdg_popup's parent to this layer_surface. This popup should have been created via xdg_surface::get_popup with the parent set to NULL, and this request must be invoked before committing the popup's initial state. See the documentation of xdg_popup for more details about what an xdg_popup is and how it is used. When a configure event is received, if a client commits the surface in response to the configure event, then the client must make an ack_configure request sometime before the commit request, passing along the serial of the configure event. If the client receives multiple configure events before it can respond to one, it only has to ack the last configure event. A client is not required to commit immediately after sending an ack_configure request - it may even ack_configure several times before its next surface commit. A client may send multiple ack_configure requests before committing, but only the last request sent before a commit indicates which configure event the client really is responding to. This request destroys the layer surface. The configure event asks the client to resize its surface. Clients should arrange their surface for the new states, and then send an ack_configure request with the serial sent in this configure event at some point before committing the new surface. The client is free to dismiss all but the last configure event it received. The width and height arguments specify the size of the window in surface-local coordinates. The size is a hint, in the sense that the client is free to ignore it if it doesn't resize, pick a smaller size (to satisfy aspect ratio or resize in steps of NxM pixels). If the client picks a smaller size and is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the surface will be centered on this axis. If the width or height arguments are zero, it means the client should decide its own window dimension. The closed event is sent by the compositor when the surface will no longer be shown. The output may have been destroyed or the user may have asked for it to be removed. Further changes to the surface will be ignored. The client should destroy the resource after receiving this event, and create a new surface if they so choose. squeekboard-v1.17.1/squeekboard.doap000066400000000000000000000015651422304253700174570ustar00rootroot00000000000000 squeekboard A Wayland virtual keyboard A virtual keyboard supporting Wayland, built primarily for the Librem 5 phone. Linux Dorota Czaplejewicz squeekboard-v1.17.1/src/000077500000000000000000000000001422304253700150655ustar00rootroot00000000000000squeekboard-v1.17.1/src/action.rs000066400000000000000000000046621422304253700167200ustar00rootroot00000000000000/*! The symbol object, defining actions that the key can do when activated */ use std::ffi::CString; /// Name of the keysym #[derive(Debug, Clone, PartialEq)] pub struct KeySym(pub String); /// Use to switch views type View = String; /// Use to send modified keypresses #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Modifier { /// Control and Alt are the only modifiers /// which doesn't interfere with levels, /// so it's simple to implement as levels are deprecated in squeekboard. Control, Alt, Mod4, } /// Action to perform on the keypress and, in reverse, on keyrelease #[derive(Debug, Clone, PartialEq)] pub enum Action { /// Switch to this view SetView(View), /// Switch to a view and latch LockView { lock: View, /// When unlocked by pressing it or emitting a key unlock: View, /// Whether key has a latched state /// that pops when another key is pressed. latches: bool, /// Should take on *locked* appearance whenever latch comes back to those views. looks_locked_from: Vec, }, /// Hold this modifier for as long as the button is pressed ApplyModifier(Modifier), /// Submit some text Submit { /// Text to submit with input-method. /// If None, then keys are to be submitted instead. text: Option, /// The key events this symbol submits when submitting text is not possible keys: Vec, }, /// Erase a position behind the cursor Erase, ShowPreferences, } impl Action { pub fn is_locked(&self, view_name: &str) -> bool { match self { Action::LockView { lock, unlock: _, latches: _, looks_locked_from: _ } => lock == view_name, _ => false, } } pub fn has_locked_appearance_from(&self, locked_view_name: &str) -> bool { match self { Action::LockView { lock: _, unlock: _, latches: _, looks_locked_from } => { looks_locked_from.iter() .find(|view| locked_view_name == view.as_str()) .is_some() }, _ => false, } } pub fn is_active(&self, view_name: &str) -> bool { match self { Action::SetView(view) => view == view_name, Action::LockView { lock, unlock: _, latches: _, looks_locked_from: _ } => lock == view_name, _ => false, } } } squeekboard-v1.17.1/src/animation.rs000066400000000000000000000010031422304253700174040ustar00rootroot00000000000000/* Copyright (C) 2020 Purism SPC * SPDX-License-Identifier: GPL-3.0+ */ /*! Animation details */ use std::time::Duration; use crate::main::PixelSize; use crate::outputs::OutputId; /// The keyboard should hide after this has elapsed to prevent flickering. pub const HIDING_TIMEOUT: Duration = Duration::from_millis(200); /// The outwardly visible state of visibility #[derive(PartialEq, Debug, Clone)] pub enum Outcome { Visible { output: OutputId, height: PixelSize, }, Hidden, } squeekboard-v1.17.1/src/assert_matches.rs000066400000000000000000000275151422304253700204520ustar00rootroot00000000000000/* Taken from https://github.com/murarth/assert_matches * * git commit: 26b8b40a12823c068a829ba475d0eccc13dfc221 * * assert_matches is distributed under the terms of both the MIT license and the Apache License (Version 2.0). * Copyright (c) 2016 Murarth Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ //! Provides a macro, `assert_matches!`, which tests whether a value //! matches a given pattern, causing a panic if the match fails. //! //! See the macro [`assert_matches!`] documentation for more information. //! //! Also provides a debug-only counterpart, [`debug_assert_matches!`]. //! //! See the macro [`debug_assert_matches!`] documentation for more information //! about this macro. //! //! [`assert_matches!`]: macro.assert_matches.html //! [`debug_assert_matches!`]: macro.debug_assert_matches.html #![deny(missing_docs)] #![cfg_attr(not(test), no_std)] /// Asserts that an expression matches a given pattern. /// /// A guard expression may be supplied to add further restrictions to the /// expected value of the expression. /// /// A `match` arm may be supplied to perform additional assertions or to yield /// a value from the macro invocation. /// /// # Examples /// /// ``` /// #[macro_use] extern crate assert_matches; /// /// #[derive(Debug)] /// enum Foo { /// A(i32), /// B(&'static str), /// } /// /// # fn main() { /// let a = Foo::A(1); /// /// // Assert that `a` matches the pattern `Foo::A(_)`. /// assert_matches!(a, Foo::A(_)); /// /// // Assert that `a` matches the pattern and /// // that the contained value meets the condition `i > 0`. /// assert_matches!(a, Foo::A(i) if i > 0); /// /// let b = Foo::B("foobar"); /// /// // Assert that `b` matches the pattern `Foo::B(_)`. /// assert_matches!(b, Foo::B(s) => { /// // Perform additional assertions on the variable binding `s`. /// assert!(s.starts_with("foo")); /// assert!(s.ends_with("bar")); /// }); /// /// // Assert that `b` matches the pattern and yield the string `s`. /// let s = assert_matches!(b, Foo::B(s) => s); /// /// // Perform an assertion on the value `s`. /// assert_eq!(s, "foobar"); /// # } /// ``` #[macro_export] macro_rules! assert_matches { ( $e:expr , $($pat:pat)|+ ) => { match $e { $($pat)|+ => (), ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($($pat)|+)) } }; ( $e:expr , $($pat:pat)|+ if $cond:expr ) => { match $e { $($pat)|+ if $cond => (), ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($($pat)|+ if $cond)) } }; ( $e:expr , $($pat:pat)|+ => $arm:expr ) => { match $e { $($pat)|+ => $arm, ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($($pat)|+)) } }; ( $e:expr , $($pat:pat)|+ if $cond:expr => $arm:expr ) => { match $e { $($pat)|+ if $cond => $arm, ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($($pat)|+ if $cond)) } }; ( $e:expr , $($pat:pat)|+ , $($arg:tt)* ) => { match $e { $($pat)|+ => (), ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}", e, stringify!($($pat)|+), format_args!($($arg)*)) } }; ( $e:expr , $($pat:pat)|+ if $cond:expr , $($arg:tt)* ) => { match $e { $($pat)|+ if $cond => (), ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}", e, stringify!($($pat)|+ if $cond), format_args!($($arg)*)) } }; ( $e:expr , $($pat:pat)|+ => $arm:expr , $($arg:tt)* ) => { match $e { $($pat)|+ => $arm, ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}", e, stringify!($($pat)|+), format_args!($($arg)*)) } }; ( $e:expr , $($pat:pat)|+ if $cond:expr => $arm:expr , $($arg:tt)* ) => { match $e { $($pat)|+ if $cond => $arm, ref e => panic!("assertion failed: `{:?}` does not match `{}`: {}", e, stringify!($($pat)|+ if $cond), format_args!($($arg)*)) } }; } /// Asserts that an expression matches a given pattern. /// /// Unlike [`assert_matches!`], `debug_assert_matches!` statements are only enabled /// in non-optimized builds by default. An optimized build will omit all /// `debug_assert_matches!` statements unless `-C debug-assertions` is passed /// to the compiler. /// /// See the macro [`assert_matches!`] documentation for more information. /// /// [`assert_matches!`]: macro.assert_matches.html #[macro_export(local_inner_macros)] macro_rules! debug_assert_matches { ( $($tt:tt)* ) => { { if _assert_matches_cfg!(debug_assertions) { assert_matches!($($tt)*); } } } } #[doc(hidden)] #[macro_export] macro_rules! _assert_matches_cfg { ( $($tt:tt)* ) => { cfg!($($tt)*) } } #[cfg(test)] mod test { use std::panic::{catch_unwind, UnwindSafe}; #[derive(Debug)] enum Foo { A(i32), B(&'static str), C(&'static str), } #[test] fn test_assert_succeed() { let a = Foo::A(123); assert_matches!(a, Foo::A(_)); assert_matches!(a, Foo::A(123)); assert_matches!(a, Foo::A(i) if i == 123); assert_matches!(a, Foo::A(42) | Foo::A(123)); let b = Foo::B("foo"); assert_matches!(b, Foo::B(_)); assert_matches!(b, Foo::B("foo")); assert_matches!(b, Foo::B(s) if s == "foo"); assert_matches!(b, Foo::B(s) => assert_eq!(s, "foo")); assert_matches!(b, Foo::B(s) => { assert_eq!(s, "foo"); assert!(true) }); assert_matches!(b, Foo::B(s) if s == "foo" => assert_eq!(s, "foo")); assert_matches!(b, Foo::B(s) if s == "foo" => { assert_eq!(s, "foo"); assert!(true) }); let c = Foo::C("foo"); assert_matches!(c, Foo::B(_) | Foo::C(_)); assert_matches!(c, Foo::B("foo") | Foo::C("foo")); assert_matches!(c, Foo::B(s) | Foo::C(s) if s == "foo"); assert_matches!(c, Foo::B(s) | Foo::C(s) => assert_eq!(s, "foo")); assert_matches!(c, Foo::B(s) | Foo::C(s) => { assert_eq!(s, "foo"); assert!(true) }); assert_matches!(c, Foo::B(s) | Foo::C(s) if s == "foo" => assert_eq!(s, "foo")); assert_matches!(c, Foo::B(s) | Foo::C(s) if s == "foo" => { assert_eq!(s, "foo"); assert!(true) }); } #[test] #[should_panic] fn test_assert_panic_0() { let a = Foo::A(123); assert_matches!(a, Foo::B(_)); } #[test] #[should_panic] fn test_assert_panic_1() { let b = Foo::B("foo"); assert_matches!(b, Foo::B("bar")); } #[test] #[should_panic] fn test_assert_panic_2() { let b = Foo::B("foo"); assert_matches!(b, Foo::B(s) if s == "bar"); } #[test] #[should_panic] fn test_assert_panic_3() { let b = Foo::B("foo"); assert_matches!(b, Foo::B(s) => assert_eq!(s, "bar")); } #[test] #[should_panic] fn test_assert_panic_4() { let b = Foo::B("foo"); assert_matches!(b, Foo::B(s) if s == "bar" => assert_eq!(s, "foo")); } #[test] #[should_panic] fn test_assert_panic_5() { let b = Foo::B("foo"); assert_matches!(b, Foo::B(s) if s == "foo" => assert_eq!(s, "bar")); } #[test] #[should_panic] fn test_assert_panic_6() { let b = Foo::B("foo"); assert_matches!(b, Foo::B(s) if s == "foo" => { assert_eq!(s, "foo"); assert!(false) }); } #[test] fn test_assert_no_move() { let b = &mut Foo::A(0); assert_matches!(*b, Foo::A(0)); } #[test] fn assert_with_message() { let a = Foo::A(0); assert_matches!(a, Foo::A(_), "o noes"); assert_matches!(a, Foo::A(n) if n == 0, "o noes"); assert_matches!(a, Foo::A(n) => assert_eq!(n, 0), "o noes"); assert_matches!(a, Foo::A(n) => { assert_eq!(n, 0); assert!(n < 1) }, "o noes"); assert_matches!(a, Foo::A(n) if n == 0 => assert_eq!(n, 0), "o noes"); assert_matches!(a, Foo::A(n) if n == 0 => { assert_eq!(n, 0); assert!(n < 1) }, "o noes"); assert_matches!(a, Foo::A(_), "o noes {:?}", a); assert_matches!(a, Foo::A(n) if n == 0, "o noes {:?}", a); assert_matches!(a, Foo::A(n) => assert_eq!(n, 0), "o noes {:?}", a); assert_matches!(a, Foo::A(n) => { assert_eq!(n, 0); assert!(n < 1) }, "o noes {:?}", a); assert_matches!(a, Foo::A(_), "o noes {value:?}", value=a); assert_matches!(a, Foo::A(n) if n == 0, "o noes {value:?}", value=a); assert_matches!(a, Foo::A(n) => assert_eq!(n, 0), "o noes {value:?}", value=a); assert_matches!(a, Foo::A(n) => { assert_eq!(n, 0); assert!(n < 1) }, "o noes {value:?}", value=a); assert_matches!(a, Foo::A(n) if n == 0 => assert_eq!(n, 0), "o noes {value:?}", value=a); } fn panic_message(f: F) -> String where F: FnOnce() + UnwindSafe { let err = catch_unwind(f) .expect_err("function did not panic"); *err.downcast::() .expect("function panicked with non-String value") } #[test] fn test_panic_message() { let a = Foo::A(1); // expr, pat assert_eq!(panic_message(|| { assert_matches!(a, Foo::B(_)); }), r#"assertion failed: `A(1)` does not match `Foo::B(_)`"#); // expr, pat if cond assert_eq!(panic_message(|| { assert_matches!(a, Foo::B(s) if s == "foo"); }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`"#); // expr, pat => arm assert_eq!(panic_message(|| { assert_matches!(a, Foo::B(_) => {}); }), r#"assertion failed: `A(1)` does not match `Foo::B(_)`"#); // expr, pat if cond => arm assert_eq!(panic_message(|| { assert_matches!(a, Foo::B(s) if s == "foo" => {}); }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`"#); // expr, pat, args assert_eq!(panic_message(|| { assert_matches!(a, Foo::B(_), "msg"); }), r#"assertion failed: `A(1)` does not match `Foo::B(_)`: msg"#); // expr, pat if cond, args assert_eq!(panic_message(|| { assert_matches!(a, Foo::B(s) if s == "foo", "msg"); }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`: msg"#); // expr, pat => arm, args assert_eq!(panic_message(|| { assert_matches!(a, Foo::B(_) => {}, "msg"); }), r#"assertion failed: `A(1)` does not match `Foo::B(_)`: msg"#); // expr, pat if cond => arm, args assert_eq!(panic_message(|| { assert_matches!(a, Foo::B(s) if s == "foo" => {}, "msg"); }), r#"assertion failed: `A(1)` does not match `Foo::B(s) if s == "foo"`: msg"#); } } squeekboard-v1.17.1/src/bin/000077500000000000000000000000001422304253700156355ustar00rootroot00000000000000squeekboard-v1.17.1/src/bin/test_layout.rs000066400000000000000000000007721422304253700205650ustar00rootroot00000000000000#[macro_use] extern crate clap; extern crate rs; use rs::tests::check_layout_file; fn main() -> () { let matches = clap_app!(test_layout => (name: "squeekboard-test-layout") (about: "Test keyboard layout for errors. Returns OK or an error message containing further information.") (@arg INPUT: +required "Yaml keyboard layout file to test") ).get_matches(); if check_layout_file(matches.value_of("INPUT").unwrap()) == () { println!("Test result: OK"); } } squeekboard-v1.17.1/src/config.h.in000066400000000000000000000002421422304253700171060ustar00rootroot00000000000000/* * Autogenerated by the Meson build system. * Do not edit, your changes will be lost. */ #pragma once #mesondefine GETTEXT_PACKAGE #mesondefine LOCALEDIR squeekboard-v1.17.1/src/data/000077500000000000000000000000001422304253700157765ustar00rootroot00000000000000squeekboard-v1.17.1/src/data/loading.rs000066400000000000000000000323641422304253700177710ustar00rootroot00000000000000/* Copyright (C) 2020-2021 Purism SPC * SPDX-License-Identifier: GPL-3.0+ */ /*! Loading layout files */ use std::env; use std::fmt; use std::path::PathBuf; use std::convert::TryFrom; use super::{ Error, LoadError }; use super::parsing; use ::layout::ArrangementKind; use ::logging; use ::util::c::as_str; use ::xdg; use ::imservice::ContentPurpose; // traits, derives use ::logging::Warn; /// Gathers stuff defined in C or called by C pub mod c { use super::*; use std::os::raw::c_char; #[no_mangle] pub extern "C" fn squeek_load_layout( name: *const c_char, // name of the keyboard type_: u32, // type like Wide variant: u32, // purpose variant like numeric, terminal... overlay: *const c_char, // the overlay (looking for "terminal") ) -> *mut ::layout::Layout { let type_ = match type_ { 0 => ArrangementKind::Base, 1 => ArrangementKind::Wide, _ => panic!("Bad enum value"), }; let name = as_str(&name) .expect("Bad layout name") .expect("Empty layout name"); let variant = ContentPurpose::try_from(variant) .or_print( logging::Problem::Warning, "Received invalid purpose value", ) .unwrap_or(ContentPurpose::Normal); let overlay_str = as_str(&overlay) .expect("Bad overlay name") .expect("Empty overlay name"); let overlay_str = match overlay_str { "" => None, other => Some(other), }; let (kind, layout) = load_layout_data_with_fallback(&name, type_, variant, overlay_str); let layout = ::layout::Layout::new(layout, kind, variant); Box::into_raw(Box::new(layout)) } } const FALLBACK_LAYOUT_NAME: &str = "us"; #[derive(Debug, Clone, PartialEq)] enum DataSource { File(PathBuf), Resource(String), } impl fmt::Display for DataSource { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { DataSource::File(path) => write!(f, "Path: {:?}", path.display()), DataSource::Resource(name) => write!(f, "Resource: {}", name), } } } /* All functions in this family carry around ArrangementKind, * because it's not guaranteed to be preserved, * and the resulting layout needs to know which version was loaded. * See `squeek_layout_get_kind`. * Possible TODO: since this is used only in styling, * and makes the below code nastier than needed, maybe it should go. */ /// Returns ordered names treating `name` as the base name, /// ignoring any `+` inside. fn _get_arrangement_names(name: &str, arrangement: ArrangementKind) -> Vec<(ArrangementKind, String)> { let name_with_arrangement = match arrangement { ArrangementKind::Base => name.into(), ArrangementKind::Wide => format!("{}_wide", name), }; let mut ret = Vec::new(); if name_with_arrangement != name { ret.push((arrangement, name_with_arrangement)); } ret.push((ArrangementKind::Base, name.into())); ret } /// Returns names accounting for any `+` in the `name`, /// including the fallback to the default layout. fn get_preferred_names(name: &str, kind: ArrangementKind) -> Vec<(ArrangementKind, String)> { let mut ret = _get_arrangement_names(name, kind); let base_name_preferences = { let mut parts = name.splitn(2, '+'); match parts.next() { Some(base) => { // The name is already equal to base, so nothing to add if base == name { vec![] } else { _get_arrangement_names(base, kind) } }, // The layout's base name starts with a "+". Weird but OK. None => { log_print!(logging::Level::Surprise, "Base layout name is empty: {}", name); vec![] } } }; ret.extend(base_name_preferences.into_iter()); let fallback_names = _get_arrangement_names(FALLBACK_LAYOUT_NAME, kind); ret.extend(fallback_names.into_iter()); ret } /// Includes the subdirectory before the forward slash. type LayoutPath = String; // This is only used inside iter_fallbacks_with_meta. // Placed at the top scope // because `use LayoutPurpose::*;` // complains about "not in scope" otherwise. // This seems to be a Rust 2015 edition problem. /// Helper for determining where to look up the layout. enum LayoutPurpose<'a> { Default, Special(&'a str), } /// Returns the directory string /// where the layout should be looked up, including the slash. fn get_directory_string( content_purpose: ContentPurpose, overlay: Option<&str>) -> String { use self::LayoutPurpose::*; let layout_purpose = match overlay { None => match content_purpose { ContentPurpose::Email => Special("email"), ContentPurpose::Digits => Special("number"), ContentPurpose::Number => Special("number"), ContentPurpose::Phone => Special("number"), ContentPurpose::Pin => Special("pin"), ContentPurpose::Terminal => Special("terminal"), ContentPurpose::Url => Special("url"), _ => Default, }, Some(overlay) => Special(overlay), }; // For intuitiveness, // default purpose layouts are stored in the root directory, // as they correspond to typical text // and are seen the most often. match layout_purpose { Default => "".into(), Special(purpose) => format!("{}/", purpose), } } /// Returns an iterator over all fallback paths. fn to_layout_paths( name_fallbacks: Vec<(ArrangementKind, String)>, content_purpose: ContentPurpose, overlay: Option<&str>, ) -> impl Iterator { let prepend_directory = get_directory_string(content_purpose, overlay); name_fallbacks.into_iter() .map(move |(arrangement, name)| (arrangement, format!("{}{}", prepend_directory, name)) ) } type LayoutSource = (ArrangementKind, DataSource); fn to_layout_sources( layout_paths: impl Iterator, filesystem_path: Option, ) -> impl Iterator { layout_paths.flat_map(move |(arrangement, layout_path)| { let mut sources = Vec::new(); if let Some(path) = &filesystem_path { sources.push(( arrangement, DataSource::File( path.join(&layout_path) .with_extension("yaml") ) )); }; sources.push((arrangement, DataSource::Resource(layout_path.clone()))); sources.into_iter() }) } /// Returns possible sources, with first as the most preferred one. /// Trying order: native lang of the right kind, native base, /// fallback lang of the right kind, fallback base fn iter_layout_sources( name: &str, arrangement: ArrangementKind, purpose: ContentPurpose, ui_overlay: Option<&str>, layout_storage: Option, ) -> impl Iterator { let names = get_preferred_names(name, arrangement); let paths = to_layout_paths(names, purpose, ui_overlay); to_layout_sources(paths, layout_storage) } fn load_layout_data(source: DataSource) -> Result<::layout::LayoutData, LoadError> { let handler = logging::Print {}; match source { DataSource::File(path) => { parsing::Layout::from_file(path.clone()) .map_err(LoadError::BadData) .and_then(|layout| layout.build(handler).0.map_err(LoadError::BadKeyMap) ) }, DataSource::Resource(name) => { parsing::Layout::from_resource(&name) .and_then(|layout| layout.build(handler).0.map_err(LoadError::BadKeyMap) ) }, } } fn load_layout_data_with_fallback( name: &str, kind: ArrangementKind, purpose: ContentPurpose, overlay: Option<&str>, ) -> (ArrangementKind, ::layout::LayoutData) { // Build the path to the right keyboard layout subdirectory let path = env::var_os("SQUEEKBOARD_KEYBOARDSDIR") .map(PathBuf::from) .or_else(|| xdg::data_path("squeekboard/keyboards")); for (kind, source) in iter_layout_sources(&name, kind, purpose, overlay, path) { let layout = load_layout_data(source.clone()); match layout { Err(e) => match (e, source) { ( LoadError::BadData(Error::Missing(e)), DataSource::File(file) ) => log_print!( logging::Level::Debug, "Tried file {:?}, but it's missing: {}", file, e ), (e, source) => log_print!( logging::Level::Warning, "Failed to load layout from {}: {}, skipping", source, e ), }, Ok(layout) => { log_print!(logging::Level::Info, "Loaded layout {}", source); return (kind, layout); } } } panic!("No useful layout found!"); } #[cfg(test)] mod tests { use super::*; use ::logging::ProblemPanic; #[test] fn parsing_fallback() { assert!(parsing::Layout::from_resource(FALLBACK_LAYOUT_NAME) .map(|layout| layout.build(ProblemPanic).0.unwrap()) .is_ok() ); } /// First fallback should be to builtin, not to FALLBACK_LAYOUT_NAME #[test] fn test_fallback_basic_builtin() { let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, None, None); assert_eq!( sources.collect::>(), vec!( (ArrangementKind::Base, DataSource::Resource("nb".into())), ( ArrangementKind::Base, DataSource::Resource(FALLBACK_LAYOUT_NAME.into()) ), ) ); } /// Prefer loading from file system before builtin. #[test] fn test_preferences_order_path() { let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, None, Some(".".into())); assert_eq!( sources.collect::>(), vec!( (ArrangementKind::Base, DataSource::File("./nb.yaml".into())), (ArrangementKind::Base, DataSource::Resource("nb".into())), ( ArrangementKind::Base, DataSource::File("./us.yaml".into()) ), ( ArrangementKind::Base, DataSource::Resource("us".into()) ), ) ); } /// If layout contains a "+", it should reach for what's in front of it too. #[test] fn test_preferences_order_base() { let sources = iter_layout_sources("nb+aliens", ArrangementKind::Base, ContentPurpose::Normal, None, None); assert_eq!( sources.collect::>(), vec!( (ArrangementKind::Base, DataSource::Resource("nb+aliens".into())), (ArrangementKind::Base, DataSource::Resource("nb".into())), ( ArrangementKind::Base, DataSource::Resource(FALLBACK_LAYOUT_NAME.into()) ), ) ); } #[test] fn test_preferences_order_arrangement() { let sources = iter_layout_sources("nb", ArrangementKind::Wide, ContentPurpose::Normal, None, None); assert_eq!( sources.collect::>(), vec!( (ArrangementKind::Wide, DataSource::Resource("nb_wide".into())), (ArrangementKind::Base, DataSource::Resource("nb".into())), ( ArrangementKind::Wide, DataSource::Resource("us_wide".into()) ), ( ArrangementKind::Base, DataSource::Resource("us".into()) ), ) ); } #[test] fn test_preferences_order_overlay() { let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, Some("terminal"), None); assert_eq!( sources.collect::>(), vec!( (ArrangementKind::Base, DataSource::Resource("terminal/nb".into())), ( ArrangementKind::Base, DataSource::Resource("terminal/us".into()) ), ) ); } #[test] fn test_preferences_order_hint() { let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Terminal, None, None); assert_eq!( sources.collect::>(), vec!( (ArrangementKind::Base, DataSource::Resource("terminal/nb".into())), ( ArrangementKind::Base, DataSource::Resource("terminal/us".into()) ), ) ); } } squeekboard-v1.17.1/src/data/mod.rs000066400000000000000000000031141422304253700171220ustar00rootroot00000000000000/* Copyright (C) 2020-2021 Purism SPC * SPDX-License-Identifier: GPL-3.0+ */ /*! Combined module for dealing with layout files */ mod loading; pub mod parsing; use std::io; use std::fmt; use ::keyboard::FormattingError; /// Errors encountered loading the layout into yaml #[derive(Debug)] pub enum Error { Yaml(serde_yaml::Error), Io(io::Error), /// The file was missing. /// It's distinct from Io in order to make it matchable /// without calling io::Error::kind() Missing(io::Error), } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Error::Yaml(e) => write!(f, "YAML: {}", e), Error::Io(e) => write!(f, "IO: {}", e), Error::Missing(e) => write!(f, "Missing: {}", e), } } } impl From for Error { fn from(e: io::Error) -> Self { let kind = e.kind(); match kind { io::ErrorKind::NotFound => Error::Missing(e), _ => Error::Io(e), } } } #[derive(Debug)] pub enum LoadError { BadData(Error), MissingResource, BadResource(serde_yaml::Error), BadKeyMap(FormattingError), } impl fmt::Display for LoadError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use self::LoadError::*; match self { BadData(e) => write!(f, "Bad data: {}", e), MissingResource => write!(f, "Missing resource"), BadResource(e) => write!(f, "Bad resource: {}", e), BadKeyMap(e) => write!(f, "Bad key map: {}", e), } } } squeekboard-v1.17.1/src/data/parsing.rs000066400000000000000000000574211422304253700200200ustar00rootroot00000000000000/* Copyright (C) 2020-2021 Purism SPC * SPDX-License-Identifier: GPL-3.0+ */ /*! Parsing of the data files containing layouts */ use std::cell::RefCell; use std::collections::{ HashMap, HashSet }; use std::ffi::CString; use std::fs; use std::path::PathBuf; use std::rc::Rc; use std::vec::Vec; use xkbcommon::xkb; use super::{ Error, LoadError }; use ::action; use ::keyboard::{ KeyState, PressType, generate_keymaps, generate_keycodes, KeyCode, FormattingError }; use ::layout; use ::logging; use ::util::hash_map_map; use ::resources; // traits, derives use serde::Deserialize; use std::io::BufReader; use std::iter::FromIterator; use ::logging::Warn; // TODO: find a nice way to make sure non-positive sizes don't break layouts /// The root element describing an entire keyboard #[derive(Debug, Deserialize, PartialEq)] #[serde(deny_unknown_fields)] pub struct Layout { #[serde(default)] margins: Margins, views: HashMap>, #[serde(default)] buttons: HashMap, outlines: HashMap } #[derive(Debug, Clone, Deserialize, PartialEq, Default)] #[serde(deny_unknown_fields)] struct Margins { top: f64, bottom: f64, side: f64, } /// Buttons are embedded in a single string type ButtonIds = String; /// All info about a single button /// Buttons can have multiple instances though. #[derive(Debug, Default, Deserialize, PartialEq)] #[serde(deny_unknown_fields)] struct ButtonMeta { // TODO: structure (action, keysym, text, modifier) as an enum // to detect conflicts and missing values at compile time /// Special action to perform on activation. /// Conflicts with keysym, text, modifier. action: Option, /// The name of the XKB keysym to emit on activation. /// Conflicts with action, text, modifier. keysym: Option, /// The text to submit on activation. Will be derived from ID if not present /// Conflicts with action, keysym, modifier. text: Option, /// The modifier to apply while the key is locked /// Conflicts with action, keysym, text modifier: Option, /// If not present, will be derived from text or the button ID label: Option, /// Conflicts with label icon: Option, /// The name of the outline. If not present, will be "default" outline: Option, } #[derive(Debug, Deserialize, PartialEq, Clone)] #[serde(deny_unknown_fields)] enum Action { #[serde(rename="locking")] Locking { lock_view: String, unlock_view: String, pops: Option, #[serde(default)] looks_locked_from: Vec, }, #[serde(rename="set_view")] SetView(String), #[serde(rename="show_prefs")] ShowPrefs, /// Remove last character #[serde(rename="erase")] Erase, } #[derive(Debug, Clone, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] enum Modifier { Control, Shift, Lock, #[serde(alias="Mod1")] Alt, Mod2, Mod3, Mod4, Mod5, } #[derive(Debug, Clone, Deserialize, PartialEq)] #[serde(deny_unknown_fields)] struct Outline { width: f64, height: f64, } pub fn add_offsets<'a, I: 'a, T, F: 'a>(iterator: I, get_size: F) -> impl Iterator + 'a where I: Iterator, F: Fn(&T) -> f64, { let mut offset = 0.0; iterator.map(move |item| { let size = get_size(&item); let value = (offset, item); offset += size; value }) } impl Layout { pub fn from_resource(name: &str) -> Result { let data = resources::get_keyboard(name) .ok_or(LoadError::MissingResource)?; serde_yaml::from_str(data) .map_err(LoadError::BadResource) } pub fn from_file(path: PathBuf) -> Result { let infile = BufReader::new( fs::OpenOptions::new() .read(true) .open(&path)? ); serde_yaml::from_reader(infile).map_err(Error::Yaml) } pub fn build(self, mut warning_handler: H) -> (Result<::layout::LayoutData, FormattingError>, H) { let button_names = self.views.values() .flat_map(|rows| { rows.iter() .flat_map(|row| row.split_ascii_whitespace()) }); let button_names: HashSet<&str> = HashSet::from_iter(button_names); let button_actions: Vec<(&str, ::action::Action)> = button_names.iter().map(|name| {( *name, create_action( &self.buttons, name, self.views.keys().collect(), &mut warning_handler, ) )}).collect(); let symbolmap: HashMap = generate_keycodes( extract_symbol_names(&button_actions) ); let button_states = HashMap::::from_iter( button_actions.into_iter().map(|(name, action)| { let keycodes = match &action { ::action::Action::Submit { text: _, keys } => { keys.iter().map(|named_keysym| { symbolmap.get(named_keysym.0.as_str()) .expect( format!( "keysym {} in key {} missing from symbol map", named_keysym.0, name ).as_str() ) .clone() }).collect() }, action::Action::Erase => vec![ symbolmap.get("BackSpace") .expect(&format!("BackSpace missing from symbol map")) .clone(), ], _ => Vec::new(), }; ( name.into(), KeyState { pressed: PressType::Released, keycodes, action, } ) }) ); let keymaps = match generate_keymaps(symbolmap) { Err(e) => { return (Err(e), warning_handler) }, Ok(v) => v, }; let button_states_cache = hash_map_map( button_states, |name, state| {( name, Rc::new(RefCell::new(state)) )} ); let views: Vec<_> = self.views.iter() .map(|(name, view)| { let rows = view.iter().map(|row| { let buttons = row.split_ascii_whitespace() .map(|name| { Box::new(create_button( &self.buttons, &self.outlines, name, button_states_cache.get(name.into()) .expect("Button state not created") .clone(), &mut warning_handler, )) }); layout::Row::new( add_offsets( buttons, |button| button.size.width, ).collect() ) }); let rows = add_offsets(rows, |row| row.get_size().height) .collect(); ( name.clone(), layout::View::new(rows) ) }).collect(); // Center views on the same point. let views = { let total_size = layout::View::calculate_super_size( views.iter().map(|(_name, view)| view).collect() ); HashMap::from_iter(views.into_iter().map(|(name, view)| ( name, ( layout::c::Point { x: (total_size.width - view.get_size().width) / 2.0, y: (total_size.height - view.get_size().height) / 2.0, }, view, ), ))) }; ( Ok(::layout::LayoutData { views: views, keymaps: keymaps.into_iter().map(|keymap_str| CString::new(keymap_str) .expect("Invalid keymap string generated") ).collect(), // FIXME: use a dedicated field margins: layout::Margins { top: self.margins.top, left: self.margins.side, bottom: self.margins.bottom, right: self.margins.side, }, }), warning_handler, ) } } fn create_action( button_info: &HashMap, name: &str, view_names: Vec<&String>, warning_handler: &mut H, ) -> ::action::Action { let default_meta = ButtonMeta::default(); let symbol_meta = button_info.get(name) .unwrap_or(&default_meta); fn keysym_valid(name: &str) -> bool { xkb::keysym_from_name(name, xkb::KEYSYM_NO_FLAGS) != xkb::KEY_NoSymbol } enum SubmitData { Action(Action), Text(String), Keysym(String), Modifier(Modifier), } let submission = match ( &symbol_meta.action, &symbol_meta.keysym, &symbol_meta.text, &symbol_meta.modifier, ) { (Some(action), None, None, None) => SubmitData::Action(action.clone()), (None, Some(keysym), None, None) => SubmitData::Keysym(keysym.clone()), (None, None, Some(text), None) => SubmitData::Text(text.clone()), (None, None, None, Some(modifier)) => { SubmitData::Modifier(modifier.clone()) }, (None, None, None, None) => SubmitData::Text(name.into()), _ => { warning_handler.handle( logging::Level::Warning, &format!( "Button {} has more than one of (action, keysym, text, modifier)", name, ), ); SubmitData::Text("".into()) }, }; fn filter_view_name( button_name: &str, view_name: String, view_names: &Vec<&String>, warning_handler: &mut H, ) -> String { if view_names.contains(&&view_name) { view_name } else { warning_handler.handle( logging::Level::Warning, &format!("Button {} switches to missing view {}", button_name, view_name, ), ); "base".into() } } match submission { SubmitData::Action( Action::SetView(view_name) ) => ::action::Action::SetView( filter_view_name( name, view_name.clone(), &view_names, warning_handler, ) ), SubmitData::Action(Action::Locking { lock_view, unlock_view, pops, looks_locked_from, }) => ::action::Action::LockView { lock: filter_view_name( name, lock_view.clone(), &view_names, warning_handler, ), unlock: filter_view_name( name, unlock_view.clone(), &view_names, warning_handler, ), latches: pops.unwrap_or(true), looks_locked_from, }, SubmitData::Action( Action::ShowPrefs ) => ::action::Action::ShowPreferences, SubmitData::Action(Action::Erase) => action::Action::Erase, SubmitData::Keysym(keysym) => ::action::Action::Submit { text: None, keys: vec!(::action::KeySym( match keysym_valid(keysym.as_str()) { true => keysym.clone(), false => { warning_handler.handle( logging::Level::Warning, &format!( "Keysym name invalid: {}", keysym, ), ); "space".into() // placeholder }, } )), }, SubmitData::Text(text) => ::action::Action::Submit { text: CString::new(text.clone()).or_warn( warning_handler, logging::Problem::Warning, &format!("Text {} contains problems", text), ), keys: text.chars().map(|codepoint| { let codepoint_string = codepoint.to_string(); ::action::KeySym(match keysym_valid(codepoint_string.as_str()) { true => codepoint_string, false => format!("U{:04X}", codepoint as u32), }) }).collect(), }, SubmitData::Modifier(modifier) => match modifier { Modifier::Control => action::Action::ApplyModifier( action::Modifier::Control, ), Modifier::Alt => action::Action::ApplyModifier( action::Modifier::Alt, ), Modifier::Mod4 => action::Action::ApplyModifier( action::Modifier::Mod4, ), unsupported_modifier => { warning_handler.handle( logging::Level::Bug, &format!( "Modifier {:?} unsupported", unsupported_modifier, ), ); action::Action::Submit { text: None, keys: Vec::new(), } }, }, } } /// TODO: Since this will receive user-provided data, /// all .expect() on them should be turned into soft fails fn create_button( button_info: &HashMap, outlines: &HashMap, name: &str, state: Rc>, warning_handler: &mut H, ) -> ::layout::Button { let cname = CString::new(name.clone()) .expect("Bad name"); // don't remove, because multiple buttons with the same name are allowed let default_meta = ButtonMeta::default(); let button_meta = button_info.get(name) .unwrap_or(&default_meta); // TODO: move conversion to the C/Rust boundary let label = if let Some(label) = &button_meta.label { ::layout::Label::Text(CString::new(label.as_str()) .expect("Bad label")) } else if let Some(icon) = &button_meta.icon { ::layout::Label::IconName(CString::new(icon.as_str()) .expect("Bad icon")) } else if let Some(text) = &button_meta.text { ::layout::Label::Text( CString::new(text.as_str()) .or_warn( warning_handler, logging::Problem::Warning, &format!("Text {} is invalid", text), ).unwrap_or_else(|| CString::new("").unwrap()) ) } else { ::layout::Label::Text(cname.clone()) }; let outline_name = match &button_meta.outline { Some(outline) => { if outlines.contains_key(outline) { outline.clone() } else { warning_handler.handle( logging::Level::Warning, &format!("Outline named {} does not exist! Using default for button {}", outline, name) ); "default".into() } } None => "default".into(), }; let outline = outlines.get(&outline_name) .map(|outline| (*outline).clone()) .or_warn( warning_handler, logging::Problem::Warning, "No default outline defined! Using 1x1!", ).unwrap_or(Outline { width: 1f64, height: 1f64 }); layout::Button { name: cname, outline_name: CString::new(outline_name).expect("Bad outline"), // TODO: do layout before creating buttons size: layout::Size { width: outline.width, height: outline.height, }, label: label, state: state, } } fn extract_symbol_names<'a>(actions: &'a [(&str, action::Action)]) -> impl Iterator + 'a { actions.iter() .filter_map(|(_name, act)| { match act { action::Action::Submit { text: _, keys, } => Some(keys.clone()), action::Action::Erase => Some(vec!(action::KeySym("BackSpace".into()))), _ => None, } }) .flatten() .map(|named_keysym| named_keysym.0) } #[cfg(test)] mod tests { use super::*; use std::env; use ::logging::ProblemPanic; fn path_from_root(file: &'static str) -> PathBuf { let source_dir = env::var("SOURCE_DIR") .map(PathBuf::from) .unwrap_or_else(|e| { if let env::VarError::NotPresent = e { let this_file = file!(); PathBuf::from(this_file) .parent().unwrap() .parent().unwrap() .into() } else { panic!("{:?}", e); } }); source_dir.join(file) } #[test] fn test_parse_path() { assert_eq!( Layout::from_file(path_from_root("tests/layout.yaml")).unwrap(), Layout { margins: Margins { top: 0f64, bottom: 0f64, side: 0f64 }, views: hashmap!( "base".into() => vec!("test".into()), ), buttons: hashmap!{ "test".into() => ButtonMeta { icon: None, keysym: None, action: None, text: None, modifier: None, label: Some("test".into()), outline: None, } }, outlines: hashmap!{ "default".into() => Outline { width: 0f64, height: 0f64 }, }, } ); } /// Check if the default protection works #[test] fn test_empty_views() { let out = Layout::from_file(path_from_root("tests/layout2.yaml")); match out { Ok(_) => assert!(false, "Data mistakenly accepted"), Err(e) => { let mut handled = false; if let Error::Yaml(ye) = &e { handled = ye.to_string() .starts_with("missing field `views`"); }; if !handled { println!("Unexpected error {:?}", e); assert!(false) } } } } #[test] fn test_extra_field() { let out = Layout::from_file(path_from_root("tests/layout3.yaml")); match out { Ok(_) => assert!(false, "Data mistakenly accepted"), Err(e) => { let mut handled = false; if let Error::Yaml(ye) = &e { handled = ye.to_string() .starts_with("unknown field `bad_field`"); }; if !handled { println!("Unexpected error {:?}", e); assert!(false) } } } } #[test] fn test_layout_punctuation() { let out = Layout::from_file(path_from_root("tests/layout_key1.yaml")) .unwrap() .build(ProblemPanic).0 .unwrap(); assert_eq!( out.views["base"].1 .get_rows()[0].1 .get_buttons()[0].1 .label, ::layout::Label::Text(CString::new("test").unwrap()) ); } #[test] fn test_layout_unicode() { let out = Layout::from_file(path_from_root("tests/layout_key2.yaml")) .unwrap() .build(ProblemPanic).0 .unwrap(); assert_eq!( out.views["base"].1 .get_rows()[0].1 .get_buttons()[0].1 .label, ::layout::Label::Text(CString::new("test").unwrap()) ); } /// Test multiple codepoints #[test] fn test_layout_unicode_multi() { let out = Layout::from_file(path_from_root("tests/layout_key3.yaml")) .unwrap() .build(ProblemPanic).0 .unwrap(); assert_eq!( out.views["base"].1 .get_rows()[0].1 .get_buttons()[0].1 .state.borrow() .keycodes.len(), 2 ); } /// Test if erase yields a useable keycode #[test] fn test_layout_erase() { let out = Layout::from_file(path_from_root("tests/layout_erase.yaml")) .unwrap() .build(ProblemPanic).0 .unwrap(); assert_eq!( out.views["base"].1 .get_rows()[0].1 .get_buttons()[0].1 .state.borrow() .keycodes.len(), 1 ); } #[test] fn unicode_keysym() { let keysym = xkb::keysym_from_name( format!("U{:X}", "å".chars().next().unwrap() as u32).as_str(), xkb::KEYSYM_NO_FLAGS, ); let keysym = xkb::keysym_to_utf8(keysym); assert_eq!(keysym, "å\0"); } #[test] fn test_key_unicode() { assert_eq!( create_action( &hashmap!{ ".".into() => ButtonMeta { icon: None, keysym: None, text: None, action: None, modifier: None, label: Some("test".into()), outline: None, } }, ".", Vec::new(), &mut ProblemPanic, ), ::action::Action::Submit { text: Some(CString::new(".").unwrap()), keys: vec!(::action::KeySym("U002E".into())), }, ); } #[test] fn test_layout_margins() { let out = Layout::from_file(path_from_root("tests/layout_margins.yaml")) .unwrap() .build(ProblemPanic).0 .unwrap(); assert_eq!( out.margins, layout::Margins { top: 1.0, bottom: 3.0, left: 2.0, right: 2.0, } ); } #[test] fn test_extract_symbols() { let actions = [( "ac", action::Action::Submit { text: None, keys: vec![ action::KeySym("a".into()), action::KeySym("c".into()), ], }, )]; assert_eq!( extract_symbol_names(&actions[..]).collect::>(), vec!["a", "c"], ); } #[test] fn test_extract_symbols_erase() { let actions = [( "Erase", action::Action::Erase, )]; assert_eq!( extract_symbol_names(&actions[..]).collect::>(), vec!["BackSpace"], ); } } squeekboard-v1.17.1/src/dbus.c000066400000000000000000000062121422304253700161670ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include "dbus.h" #include "main.h" #include #include #include void dbus_handler_destroy(DBusHandler *service) { g_free (service->object_path); if (service->connection) { if (service->registration_id > 0) { g_dbus_connection_unregister_object (service->connection, service->registration_id); service->registration_id = 0; } g_object_unref (service->connection); service->connection = NULL; } if (service->introspection_data) { g_dbus_node_info_unref (service->introspection_data); service->introspection_data = NULL; } free(service); } static gboolean handle_set_visible(SmPuriOSK0 *object, GDBusMethodInvocation *invocation, gboolean arg_visible, gpointer user_data) { DBusHandler *service = user_data; if (arg_visible) { squeek_state_send_force_visible (service->state_manager); } else { squeek_state_send_force_hidden(service->state_manager); } sm_puri_osk0_complete_set_visible(object, invocation); return TRUE; } DBusHandler * dbus_handler_new (GDBusConnection *connection, const gchar *object_path, struct squeek_state_manager *state_manager) { DBusHandler *self = calloc(1, sizeof(DBusHandler)); self->object_path = g_strdup(object_path); self->connection = connection; self->state_manager = state_manager; self->dbus_interface = sm_puri_osk0_skeleton_new(); g_signal_connect(self->dbus_interface, "handle-set-visible", G_CALLBACK(handle_set_visible), self); if (self->connection && self->object_path) { GError *error = NULL; if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(self->dbus_interface), self->connection, self->object_path, &error)) { g_warning("Error registering dbus object: %s\n", error->message); g_clear_error(&error); // TODO: return an error } } return self; } // Exported to Rust void dbus_handler_set_visible(DBusHandler *service, uint8_t visible) { sm_puri_osk0_set_visible(service->dbus_interface, visible); } squeekboard-v1.17.1/src/dbus.h000066400000000000000000000034211422304253700161730ustar00rootroot00000000000000/* * Copyright (C) 2010-2011 Daiki Ueno * Copyright (C) 2010-2011 Red Hat, Inc. * Copyright (C) 2019-2020 Purism, SPC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DBUS_H_ #define DBUS_H_ 1 #include "sm.puri.OSK0.h" // From main.h struct squeek_state_manager; G_BEGIN_DECLS #define DBUS_SERVICE_PATH "/sm/puri/OSK0" #define DBUS_SERVICE_INTERFACE "sm.puri.OSK0" /// Two jobs: accept events, forwarding them to the visibility manager, /// and get updated from inside to show internal state. /// Updates are handled in the same loop as the UI. /// See main.rs typedef struct _DBusHandler { GDBusConnection *connection; SmPuriOSK0 *dbus_interface; GDBusNodeInfo *introspection_data; guint registration_id; char *object_path; /// Forward incoming events there struct squeek_state_manager *state_manager; // shared reference } DBusHandler; DBusHandler * dbus_handler_new (GDBusConnection *connection, const gchar *object_path, struct squeek_state_manager *state_manager); void dbus_handler_destroy(DBusHandler*); G_END_DECLS #endif /* DBUS_H_ */ squeekboard-v1.17.1/src/drawing.rs000066400000000000000000000172711422304253700170760ustar00rootroot00000000000000/*! Drawing the UI */ use cairo; use std::cell::RefCell; use ::action::{ Action, Modifier }; use ::keyboard; use ::layout::{ Button, Label, LatchedState, Layout }; use ::layout::c::{ Bounds, EekGtkKeyboard, Point }; use ::submission::c::Submission as CSubmission; use glib::translate::FromGlibPtrNone; use gtk::prelude::WidgetExt; use std::collections::HashSet; use std::ffi::CStr; use std::ptr; mod c { use super::*; use cairo_sys; use std::os::raw::{ c_char, c_void }; // This is constructed only in C, no need for warnings #[allow(dead_code)] #[repr(transparent)] #[derive(Clone, Copy)] pub struct EekRenderer(*const c_void); // This is constructed only in C, no need for warnings /// Just don't clone this for no reason. #[allow(dead_code)] #[repr(transparent)] #[derive(Clone, Copy)] pub struct GtkStyleContext(*const c_void); extern "C" { #[allow(improper_ctypes)] pub fn eek_renderer_get_scale_factor( renderer: EekRenderer, ) -> u32; #[allow(improper_ctypes)] pub fn eek_render_button_in_context( scale_factor: u32, cr: *mut cairo_sys::cairo_t, ctx: GtkStyleContext, bounds: Bounds, icon_name: *const c_char, label: *const c_char, ); #[allow(improper_ctypes)] pub fn eek_get_style_context_for_button( renderer: EekRenderer, name: *const c_char, outline_name: *const c_char, locked_class: *const c_char, pressed: u64, ) -> GtkStyleContext; #[allow(improper_ctypes)] pub fn eek_put_style_context_for_button( ctx: GtkStyleContext, outline_name: *const c_char, locked_class: *const c_char, ); } /// Draws all buttons that are not in the base state #[no_mangle] pub extern "C" fn squeek_layout_draw_all_changed( layout: *mut Layout, renderer: EekRenderer, cr: *mut cairo_sys::cairo_t, submission: CSubmission, ) { let layout = unsafe { &mut *layout }; let submission = submission.clone_ref(); let submission = submission.borrow(); let cr = unsafe { cairo::Context::from_raw_none(cr) }; let active_modifiers = submission.get_active_modifiers(); layout.foreach_visible_button(|offset, button| { let state = RefCell::borrow(&button.state).clone(); let locked = LockedStyle::from_action( &state.action, &active_modifiers, layout.get_view_latched(), &layout.current_view, ); if state.pressed == keyboard::PressType::Pressed || locked != LockedStyle::Free { render_button_at_position( renderer, &cr, offset, button.as_ref(), state.pressed, locked, ); } }) } #[no_mangle] pub extern "C" fn squeek_draw_layout_base_view( layout: *mut Layout, renderer: EekRenderer, cr: *mut cairo_sys::cairo_t, ) { let layout = unsafe { &mut *layout }; let cr = unsafe { cairo::Context::from_raw_none(cr) }; layout.foreach_visible_button(|offset, button| { render_button_at_position( renderer, &cr, offset, button.as_ref(), keyboard::PressType::Released, LockedStyle::Free, ); }) } } #[derive(Clone, Copy, PartialEq, Debug)] enum LockedStyle { Free, Latched, Locked, } impl LockedStyle { fn from_action( action: &Action, mods: &HashSet, latched_view: &LatchedState, current_view: &str, ) -> LockedStyle { let active_mod = match action { Action::ApplyModifier(m) => mods.contains(m), _ => false, }; let active_view = action.is_active(current_view); let latched_button = match latched_view { LatchedState::Not => false, LatchedState::FromView(view) => !action.has_locked_appearance_from(view), }; match (active_mod, active_view, latched_button) { // Modifiers don't latch. (true, _, _) => LockedStyle::Locked, (false, true, false) => LockedStyle::Locked, (false, true, true) => LockedStyle::Latched, _ => LockedStyle::Free, } } } /// Renders a button at a position (button's own bounds ignored) fn render_button_at_position( renderer: c::EekRenderer, cr: &cairo::Context, position: Point, button: &Button, pressed: keyboard::PressType, locked: LockedStyle, ) { cr.save(); cr.translate(position.x, position.y); cr.rectangle( 0.0, 0.0, button.size.width, button.size.height ); cr.clip(); let scale_factor = unsafe { c::eek_renderer_get_scale_factor(renderer) }; let bounds = button.get_bounds(); let (label_c, icon_name_c) = match &button.label { Label::Text(text) => (text.as_ptr(), ptr::null()), Label::IconName(name) => { let l = unsafe { // CStr doesn't allocate anything, so it only points to // the 'static str, avoiding a memory leak CStr::from_bytes_with_nul_unchecked(b"icon\0") }; (l.as_ptr(), name.as_ptr()) }, }; with_button_context( renderer, button, pressed, locked, |ctx| unsafe { // TODO: split into separate procedures: // draw outline, draw label, draw icon. c::eek_render_button_in_context( scale_factor, cairo::Context::to_raw_none(&cr), *ctx, bounds, icon_name_c, label_c, ) } ); cr.restore(); } fn with_button_context R>( renderer: c::EekRenderer, button: &Button, pressed: keyboard::PressType, locked: LockedStyle, operation: F, ) -> R { let outline_name_c = button.outline_name.as_ptr(); let locked_class_c = match locked { LockedStyle::Free => ptr::null(), LockedStyle::Locked => unsafe { CStr::from_bytes_with_nul_unchecked(b"locked\0").as_ptr() }, LockedStyle::Latched => unsafe { CStr::from_bytes_with_nul_unchecked(b"latched\0").as_ptr() }, }; let ctx = unsafe { c::eek_get_style_context_for_button( renderer, button.name.as_ptr(), outline_name_c, locked_class_c, pressed as u64, ) }; let r = operation(&ctx); unsafe { c::eek_put_style_context_for_button( ctx, outline_name_c, locked_class_c, ) }; r } pub fn queue_redraw(keyboard: EekGtkKeyboard) { let widget = unsafe { gtk::Widget::from_glib_none(keyboard.0) }; widget.queue_draw(); } #[cfg(test)] mod test { use super::*; #[test] fn test_exit_only() { assert_eq!( LockedStyle::from_action( &Action::LockView { lock: "ab".into(), unlock: "a".into(), latches: true, looks_locked_from: vec!["b".into()], }, &HashSet::new(), &LatchedState::FromView("b".into()), "ab", ), LockedStyle::Locked, ); } } squeekboard-v1.17.1/src/event_loop/000077500000000000000000000000001422304253700172375ustar00rootroot00000000000000squeekboard-v1.17.1/src/event_loop/driver.rs000066400000000000000000000110451422304253700211010ustar00rootroot00000000000000/* Copyright (C) 2021 Purism SPC * SPDX-License-Identifier: GPL-3.0+ */ /*! This drives the loop from the `loop` module. * * The tracker loop needs to be driven somehow, * and connected to the external world, * both on the side of receiving and sending events. * * That's going to be implementation-dependent, * connecting to some external mechanisms * for time, messages, and threading/callbacks. * * This is the "imperative shell" part of the software, * and no longer unit-testable. */ use crate::event_loop; use crate::logging; use crate::main::Commands; use crate::state::{ Application, Event }; use glib; use std::sync::mpsc; use std::thread; use std::time::Instant; // Traits use crate::logging::Warn; /// Type of the sender that waits for external events type Sender = mpsc::Sender; /// Type of the sender that waits for internal state changes type UISender = glib::Sender; /// This loop driver spawns a new thread which updates the state in a loop, /// in response to incoming events. /// It sends outcomes to the glib main loop using a channel. /// The outcomes are applied by the UI end of the channel in the `main` module. // This could still be reasonably tested, // by creating a glib::Sender and checking what messages it receives. #[derive(Clone)] pub struct Threaded { thread: Sender, } impl Threaded { pub fn new(ui: UISender, initial_state: Application) -> Self { let (sender, receiver) = mpsc::channel(); let saved_sender = sender.clone(); thread::spawn(move || { let mut state = event_loop::State::new(initial_state, Instant::now()); loop { match receiver.recv() { Ok(event) => { state = Self::handle_loop_event(&sender, state, event, &ui); }, Err(e) => { logging::print(logging::Level::Bug, &format!("Senders hung up, aborting: {}", e)); return; }, }; } }); Self { thread: saved_sender, } } pub fn send(&self, event: Event) -> Result<(), mpsc::SendError> { self.thread.send(event) } fn handle_loop_event(loop_sender: &Sender, state: event_loop::State, event: Event, ui: &UISender) -> event_loop::State { let now = Instant::now(); let (new_state, commands) = event_loop::handle_event(state.clone(), event, now); ui.send(commands) .or_warn(&mut logging::Print, logging::Problem::Bug, "Can't send to UI"); if new_state.scheduled_wakeup != state.scheduled_wakeup { if let Some(when) = new_state.scheduled_wakeup { Self::schedule_timeout_wake(loop_sender, when); } } new_state } fn schedule_timeout_wake(loop_sender: &Sender, when: Instant) { let sender = loop_sender.clone(); thread::spawn(move || { let now = Instant::now(); thread::sleep(when - now); sender.send(Event::TimeoutReached(when)) .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't wake visibility manager"); }); } } /// For calling in only mod c { use super::*; use crate::state::Presence; use crate::state::visibility; use crate::util::c::Wrapped; #[no_mangle] pub extern "C" fn squeek_state_send_force_visible(mgr: Wrapped) { let sender = mgr.clone_ref(); let sender = sender.borrow(); sender.send(Event::Visibility(visibility::Event::ForceVisible)) .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager"); } #[no_mangle] pub extern "C" fn squeek_state_send_force_hidden(sender: Wrapped) { let sender = sender.clone_ref(); let sender = sender.borrow(); sender.send(Event::Visibility(visibility::Event::ForceHidden)) .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager"); } #[no_mangle] pub extern "C" fn squeek_state_send_keyboard_present(sender: Wrapped, present: u32) { let sender = sender.clone_ref(); let sender = sender.borrow(); let state = if present == 0 { Presence::Missing } else { Presence::Present }; sender.send(Event::PhysicalKeyboard(state)) .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager"); } } squeekboard-v1.17.1/src/event_loop/mod.rs000066400000000000000000000151271422304253700203720ustar00rootroot00000000000000/* Copyright (C) 2021 Purism SPC * SPDX-License-Identifier: GPL-3.0+ */ /*! The loop abstraction for driving state changes. * It binds to the state tracker in `state::Application`, * and actually gets driven by a driver in the `driver` module. * * * * * * * If we performed updates in a tight loop, * the state tracker would have been all we need. * * `` * loop { * event = current_event() * outcome = update_state(event) * io.apply(outcome) * } * `` * * This is enough to process all events, * and keep the window always in sync with the current state. * * However, we're trying to be conservative, * and not waste time performing updates that don't change state, * so we have to react to events that end up influencing the state. * * One complication from that is that animation steps * are not a response to events coming from the owner of the loop, * but are needed by the loop itself. * * This is where the rest of bugs hide: * too few scheduled wakeups mean missed updates and wrong visible state. * Too many wakeups can slow down the process, or make animation jittery. * The loop iteration is kept as a pure function to stay testable. */ pub mod driver; // This module is tightly coupled to the shape of data passed around in this project. // That's not a problem as long as there's only one loop. // They can still be abstracted into Traits, // and the loop parametrized over them. use crate::main::Commands; use crate::state; use crate::state::Event; use std::cmp; use std::time::{ Duration, Instant }; /// This keeps the state of the tracker loop between iterations #[derive(Clone)] struct State { state: state::Application, scheduled_wakeup: Option, last_update: Instant, } impl State { fn new(initial_state: state::Application, now: Instant) -> Self { Self { state: initial_state, scheduled_wakeup: None, last_update: now, } } } /// A single iteration of the loop, updating its persistent state. /// - updates tracker state, /// - determines outcome, /// - determines next scheduled animation wakeup, /// and because this is a pure function, it's easily testable. /// It returns the new state, and the message to send onwards. fn handle_event( mut loop_state: State, event: Event, now: Instant, ) -> (State, Commands) { // Calculate changes to send to the consumer, // based on publicly visible state. // The internal state may change more often than the publicly visible one, // so the resulting changes may be no-ops. let old_state = loop_state.state.clone(); let last_update = loop_state.last_update; loop_state.state = loop_state.state.apply_event(event.clone(), now); loop_state.last_update = now; let new_outcome = loop_state.state.get_outcome(now); let commands = old_state.get_outcome(last_update) .get_commands_to_reach(&new_outcome); // Timeout events are special: they affect the scheduled timeout. loop_state.scheduled_wakeup = match event { Event::TimeoutReached(when) => { if when > now { // Special handling for scheduled events coming in early. // Wait at least 10 ms to avoid Zeno's paradox. // This is probably not needed though, // if the `now` contains the desired time of the event. // But then what about time "reversing"? Some(cmp::max( when, now + Duration::from_millis(10), )) } else { // There's only one timeout in flight, and it's this one. // It's about to complete, and then the tracker can be cleared. // I'm not sure if this is strictly necessary. None } }, _ => loop_state.scheduled_wakeup.clone(), }; // Reschedule timeout if the new state calls for it. let scheduled = &loop_state.scheduled_wakeup; let desired = loop_state.state.get_next_wake(now); loop_state.scheduled_wakeup = match (scheduled, desired) { (&Some(scheduled), Some(next)) => { if scheduled > next { // State wants a wake to happen before the one which is already scheduled. // The previous state is removed in order to only ever keep one in flight. // That hopefully avoids pileups, // e.g. because the system is busy // and the user keeps doing something that queues more events. Some(next) } else { // Not changing the case when the wanted wake is *after* scheduled, // because wakes are not expensive as long as they don't pile up, // and I can't see a pileup potential when it doesn't retrigger itself. // Skipping an expected event is much more dangerous. Some(scheduled) } }, (None, Some(next)) => Some(next), // No need to change the unneeded wake - see above. // (Some(_), None) => ... (other, _) => other.clone(), }; (loop_state, commands) } #[cfg(test)] mod test { use super::*; use crate::animation; use crate::imservice::{ ContentHint, ContentPurpose }; use crate::main::PanelCommand; use crate::state::{ Application, InputMethod, InputMethodDetails, Presence, visibility }; use crate::state::test::application_with_fake_output; fn imdetails_new() -> InputMethodDetails { InputMethodDetails { purpose: ContentPurpose::Normal, hint: ContentHint::NONE, } } #[test] fn schedule_hide() { let start = Instant::now(); // doesn't matter when. It would be better to have a reproducible value though let mut now = start; let state = Application { im: InputMethod::Active(imdetails_new()), physical_keyboard: Presence::Missing, visibility_override: visibility::State::NotForced, ..application_with_fake_output(start) }; let l = State::new(state, now); let (l, commands) = handle_event(l, InputMethod::InactiveSince(now).into(), now); assert_matches!(commands.panel_visibility, Some(PanelCommand::Show{..})); assert_eq!(l.scheduled_wakeup, Some(now + animation::HIDING_TIMEOUT)); now += animation::HIDING_TIMEOUT; let (l, commands) = handle_event(l, Event::TimeoutReached(now), now); assert_eq!(commands.panel_visibility, Some(PanelCommand::Hide)); assert_eq!(l.scheduled_wakeup, None); } } squeekboard-v1.17.1/src/float_ord.rs000066400000000000000000000124001422304253700174010ustar00rootroot00000000000000//! Order floating point numbers, into this ordering: //! //! NaN | -Infinity | x < 0 | -0 | +0 | x > 0 | +Infinity | NaN /* Adapted from https://github.com/notriddle/rust-float-ord revision e995165f * maintained by Michael Howell * licensed under MIT / Apache-2.0 licenses * * This version drops any dependency on rand. * Caution: Don't pull the version from crates.io * before making sure rand is optional. */ extern crate core; use ::float_ord::core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; use ::float_ord::core::hash::{Hash, Hasher}; use ::float_ord::core::mem::transmute; /// A wrapper for floats, that implements total equality and ordering /// and hashing. #[derive(Clone, Copy)] pub struct FloatOrd(pub T); macro_rules! float_ord_impl { ($f:ident, $i:ident, $n:expr) => { impl FloatOrd<$f> { fn convert(self) -> $i { let u = unsafe { transmute::<$f, $i>(self.0) }; let bit = 1 << ($n - 1); if u & bit == 0 { u | bit } else { !u } } } impl PartialEq for FloatOrd<$f> { fn eq(&self, other: &Self) -> bool { self.convert() == other.convert() } } impl Eq for FloatOrd<$f> {} impl PartialOrd for FloatOrd<$f> { fn partial_cmp(&self, other: &Self) -> Option { self.convert().partial_cmp(&other.convert()) } } impl Ord for FloatOrd<$f> { fn cmp(&self, other: &Self) -> Ordering { self.convert().cmp(&other.convert()) } } impl Hash for FloatOrd<$f> { fn hash(&self, state: &mut H) { self.convert().hash(state); } } } } float_ord_impl!(f32, u32, 32); float_ord_impl!(f64, u64, 64); /// Sort a slice of floats. /// /// # Allocation behavior /// /// This routine uses a quicksort implementation that does not heap allocate. /// /// # Example /// /// ``` /// use rs::float_ord; /// let mut v = [-5.0, 4.0, 1.0, -3.0, 2.0]; /// /// float_ord::sort(&mut v); /// assert!(v == [-5.0, -3.0, 1.0, 2.0, 4.0]); /// ``` #[allow(dead_code)] pub fn sort(v: &mut [T]) where FloatOrd: Ord { let v_: &mut [FloatOrd] = unsafe { transmute(v) }; v_.sort_unstable(); } #[cfg(test)] mod tests { extern crate std; use self::std::collections::hash_map::DefaultHasher; use self::std::hash::{Hash, Hasher}; use super::FloatOrd; #[test] fn test_ord() { assert!(FloatOrd(1.0f64) < FloatOrd(2.0f64)); assert!(FloatOrd(2.0f32) > FloatOrd(1.0f32)); assert!(FloatOrd(1.0f64) == FloatOrd(1.0f64)); assert!(FloatOrd(1.0f32) == FloatOrd(1.0f32)); assert!(FloatOrd(0.0f64) > FloatOrd(-0.0f64)); assert!(FloatOrd(0.0f32) > FloatOrd(-0.0f32)); assert!(FloatOrd(::float_ord::core::f64::NAN) == FloatOrd(::float_ord::core::f64::NAN)); assert!(FloatOrd(::float_ord::core::f32::NAN) == FloatOrd(::float_ord::core::f32::NAN)); assert!(FloatOrd(-::float_ord::core::f64::NAN) < FloatOrd(::float_ord::core::f64::NAN)); assert!(FloatOrd(-::float_ord::core::f32::NAN) < FloatOrd(::float_ord::core::f32::NAN)); assert!(FloatOrd(-::float_ord::core::f64::INFINITY) < FloatOrd(::float_ord::core::f64::INFINITY)); assert!(FloatOrd(-::float_ord::core::f32::INFINITY) < FloatOrd(::float_ord::core::f32::INFINITY)); assert!(FloatOrd(::float_ord::core::f64::INFINITY) < FloatOrd(::float_ord::core::f64::NAN)); assert!(FloatOrd(::float_ord::core::f32::INFINITY) < FloatOrd(::float_ord::core::f32::NAN)); assert!(FloatOrd(-::float_ord::core::f64::NAN) < FloatOrd(::float_ord::core::f64::INFINITY)); assert!(FloatOrd(-::float_ord::core::f32::NAN) < FloatOrd(::float_ord::core::f32::INFINITY)); } fn hash(f: F) -> u64 { let mut hasher = DefaultHasher::new(); f.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { assert_ne!(hash(FloatOrd(0.0f64)), hash(FloatOrd(-0.0f64))); assert_ne!(hash(FloatOrd(0.0f32)), hash(FloatOrd(-0.0f32))); assert_eq!(hash(FloatOrd(-0.0f64)), hash(FloatOrd(-0.0f64))); assert_eq!(hash(FloatOrd(0.0f32)), hash(FloatOrd(0.0f32))); assert_ne!(hash(FloatOrd(::float_ord::core::f64::NAN)), hash(FloatOrd(-::float_ord::core::f64::NAN))); assert_ne!(hash(FloatOrd(::float_ord::core::f32::NAN)), hash(FloatOrd(-::float_ord::core::f32::NAN))); assert_eq!(hash(FloatOrd(::float_ord::core::f64::NAN)), hash(FloatOrd(::float_ord::core::f64::NAN))); assert_eq!(hash(FloatOrd(-::float_ord::core::f32::NAN)), hash(FloatOrd(-::float_ord::core::f32::NAN))); } #[test] fn test_sort_nan() { let nan = ::float_ord::core::f64::NAN; let mut v = [-1.0, 5.0, 0.0, -0.0, nan, 1.5, nan, 3.7]; super::sort(&mut v); assert!(v[0] == -1.0); assert!(v[1] == 0.0 && v[1].is_sign_negative()); assert!(v[2] == 0.0 && !v[2].is_sign_negative()); assert!(v[3] == 1.5); assert!(v[4] == 3.7); assert!(v[5] == 5.0); assert!(v[6].is_nan()); assert!(v[7].is_nan()); } } squeekboard-v1.17.1/src/imservice.c000066400000000000000000000047561422304253700172330ustar00rootroot00000000000000#include "submission.h" #include struct imservice; void imservice_handle_input_method_activate(void *data, struct zwp_input_method_v2 *input_method); void imservice_handle_input_method_deactivate(void *data, struct zwp_input_method_v2 *input_method); void imservice_handle_surrounding_text(void *data, struct zwp_input_method_v2 *input_method, const char *text, uint32_t cursor, uint32_t anchor); void imservice_handle_done(void *data, struct zwp_input_method_v2 *input_method); void imservice_handle_content_type(void *data, struct zwp_input_method_v2 *input_method, uint32_t hint, uint32_t purpose); void imservice_handle_text_change_cause(void *data, struct zwp_input_method_v2 *input_method, uint32_t cause); void imservice_handle_unavailable(void *data, struct zwp_input_method_v2 *input_method); static const struct zwp_input_method_v2_listener input_method_listener = { .activate = imservice_handle_input_method_activate, .deactivate = imservice_handle_input_method_deactivate, .surrounding_text = imservice_handle_surrounding_text, .text_change_cause = imservice_handle_text_change_cause, .content_type = imservice_handle_content_type, .done = imservice_handle_done, .unavailable = imservice_handle_unavailable, }; /// Un-inlined struct zwp_input_method_v2 *imservice_manager_get_input_method(struct zwp_input_method_manager_v2 *manager, struct wl_seat *seat) { return zwp_input_method_manager_v2_get_input_method(manager, seat); } /// Un-inlined to let Rust link to it void imservice_connect_listeners(struct zwp_input_method_v2 *im, struct imservice* imservice) { zwp_input_method_v2_add_listener(im, &input_method_listener, imservice); } void eek_input_method_commit_string(struct zwp_input_method_v2 *zwp_input_method_v2, const char *text) { zwp_input_method_v2_commit_string(zwp_input_method_v2, text); } void eek_input_method_delete_surrounding_text(struct zwp_input_method_v2 *zwp_input_method_v2, uint32_t before_length, uint32_t after_length) { zwp_input_method_v2_delete_surrounding_text(zwp_input_method_v2, before_length, after_length); }; void eek_input_method_commit(struct zwp_input_method_v2 *zwp_input_method_v2, uint32_t serial) { zwp_input_method_v2_commit(zwp_input_method_v2, serial); } /// Declared explicitly because _destroy is inline, /// making it unavailable in Rust void imservice_destroy_im(struct zwp_input_method_v2 *im) { zwp_input_method_v2_destroy(im); } squeekboard-v1.17.1/src/imservice.h000066400000000000000000000000001422304253700172120ustar00rootroot00000000000000squeekboard-v1.17.1/src/imservice.rs000066400000000000000000000275021422304253700174270ustar00rootroot00000000000000/*! Manages zwp_input_method_v2 protocol. * * Library module. */ use std::boxed::Box; use std::ffi::CString; use std::fmt; use std::num::Wrapping; use std::string::String; use std::time::Instant; use crate::event_loop::driver; use crate::state; use crate::state::Event; use ::logging; use ::util::c::into_cstring; // Traits use std::convert::TryFrom; use ::logging::Warn; /// Gathers stuff defined in C or called by C pub mod c { use super::*; use std::os::raw::{c_char, c_void}; use std::ptr; // The following defined in C /// struct zwp_input_method_v2* #[repr(transparent)] #[derive(PartialEq, Clone, Copy)] pub struct InputMethod(*const c_void); impl InputMethod { pub fn is_null(&self) -> bool { self.0.is_null() } pub fn null() -> Self { Self(ptr::null()) } } extern "C" { fn imservice_destroy_im(im: InputMethod); #[allow(improper_ctypes)] // IMService will never be dereferenced in C pub fn imservice_connect_listeners(im: InputMethod, imservice: *const IMService); pub fn eek_input_method_commit_string(im: InputMethod, text: *const c_char); pub fn eek_input_method_delete_surrounding_text(im: InputMethod, before: u32, after: u32); pub fn eek_input_method_commit(im: InputMethod, serial: u32); } // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers // TODO: is unsafe needed here? #[no_mangle] pub extern "C" fn imservice_handle_input_method_activate(imservice: *mut IMService, im: InputMethod) { let imservice = check_imservice(imservice, im).unwrap(); imservice.preedit_string = String::new(); imservice.pending = IMProtocolState { active: true, ..IMProtocolState::default() }; } #[no_mangle] pub extern "C" fn imservice_handle_input_method_deactivate(imservice: *mut IMService, im: InputMethod) { let imservice = check_imservice(imservice, im).unwrap(); imservice.pending = IMProtocolState { active: false, ..imservice.pending.clone() }; } #[no_mangle] pub extern "C" fn imservice_handle_surrounding_text(imservice: *mut IMService, im: InputMethod, text: *const c_char, cursor: u32, _anchor: u32) { let imservice = check_imservice(imservice, im).unwrap(); imservice.pending = IMProtocolState { surrounding_text: into_cstring(text) .expect("Received invalid string") .expect("Received null string"), surrounding_cursor: cursor, ..imservice.pending.clone() }; } #[no_mangle] pub extern "C" fn imservice_handle_content_type(imservice: *mut IMService, im: InputMethod, hint: u32, purpose: u32) { let imservice = check_imservice(imservice, im).unwrap(); imservice.pending = IMProtocolState { content_hint: { ContentHint::from_bits(hint) .or_print( logging::Problem::Warning, "Received invalid hint flags", ) .unwrap_or(ContentHint::NONE) }, content_purpose: { ContentPurpose::try_from(purpose) .or_print( logging::Problem::Warning, "Received invalid purpose value", ) .unwrap_or(ContentPurpose::Normal) }, ..imservice.pending.clone() }; } #[no_mangle] pub extern "C" fn imservice_handle_text_change_cause(imservice: *mut IMService, im: InputMethod, cause: u32) { let imservice = check_imservice(imservice, im).unwrap(); imservice.pending = IMProtocolState { text_change_cause: { ChangeCause::try_from(cause) .or_print( logging::Problem::Warning, "Received invalid cause value", ) .unwrap_or(ChangeCause::InputMethod) }, ..imservice.pending.clone() }; } #[no_mangle] pub extern "C" fn imservice_handle_done(imservice: *mut IMService, im: InputMethod) { let imservice = check_imservice(imservice, im).unwrap(); imservice.current = imservice.pending.clone(); imservice.serial += Wrapping(1u32); imservice.send_event(); } // TODO: this is really untested #[no_mangle] pub extern "C" fn imservice_handle_unavailable(imservice: *mut IMService, im: InputMethod) { let imservice = check_imservice(imservice, im).unwrap(); unsafe { imservice_destroy_im(im); } // no need to care about proper double-buffering, // the keyboard is already decommissioned imservice.current.active = false; imservice.send_event(); } // FIXME: destroy and deallocate // Helpers /// Convenience method for referencing the IMService raw pointer, /// and for verifying that the input method passed along /// matches the one in the `imservice`. /// /// The lifetime of the returned value is 'static, /// due to the fact that the lifetime of a raw pointer is undefined. /// Care must be take /// not to exceed the lifetime of the pointer with the reference, /// especially not to store it. fn check_imservice(imservice: *mut IMService, im: InputMethod) -> Result<&'static mut IMService, &'static str> { if imservice.is_null() { return Err("Null imservice pointer"); } let imservice: &mut IMService = unsafe { &mut *imservice }; if im == imservice.im { Ok(imservice) } else { Err("Imservice doesn't contain the input method") } } } bitflags!{ /// Map to `text_input_unstable_v3.content_hint` values pub struct ContentHint: u32 { const NONE = 0x0; const COMPLETION = 0x1; const SPELLCHECK = 0x2; const AUTO_CAPITALIZATION = 0x4; const LOWERCASE = 0x8; const UPPERCASE = 0x10; const TITLECASE = 0x20; const HIDDEN_TEXT = 0x40; const SENSITIVE_DATA = 0x80; const LATIN = 0x100; const MULTILINE = 0x200; } } /// Map to `text_input_unstable_v3.content_purpose` values /// /// ``` /// use rs::imservice::ContentPurpose; /// assert_eq!(ContentPurpose::Alpha as u32, 1); /// ``` #[derive(Debug, Copy, Clone)] pub enum ContentPurpose { Normal = 0, Alpha = 1, Digits = 2, Number = 3, Phone = 4, Url = 5, Email = 6, Name = 7, Password = 8, Pin = 9, Date = 10, Time = 11, Datetime = 12, Terminal = 13, } // Utilities from ::logging need a printable error type pub struct UnrecognizedValue; impl fmt::Display for UnrecognizedValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Unrecognized value") } } impl TryFrom for ContentPurpose { type Error = UnrecognizedValue; fn try_from(num: u32) -> Result { use self::ContentPurpose::*; match num { 0 => Ok(Normal), 1 => Ok(Alpha), 2 => Ok(Digits), 3 => Ok(Number), 4 => Ok(Phone), 5 => Ok(Url), 6 => Ok(Email), 7 => Ok(Name), 8 => Ok(Password), 9 => Ok(Pin), 10 => Ok(Date), 11 => Ok(Time), 12 => Ok(Datetime), 13 => Ok(Terminal), _ => Err(UnrecognizedValue), } } } /// Map to `text_input_unstable_v3.change_cause` values #[derive(Debug, Clone)] pub enum ChangeCause { InputMethod = 0, Other = 1, } impl TryFrom for ChangeCause { type Error = UnrecognizedValue; fn try_from(num: u32) -> Result { match num { 0 => Ok(ChangeCause::InputMethod), 1 => Ok(ChangeCause::Other), _ => Err(UnrecognizedValue) } } } /// Describes the desired state of the input method as requested by the server #[derive(Clone)] struct IMProtocolState { surrounding_text: CString, surrounding_cursor: u32, content_purpose: ContentPurpose, content_hint: ContentHint, text_change_cause: ChangeCause, active: bool, } impl Default for IMProtocolState { fn default() -> IMProtocolState { IMProtocolState { surrounding_text: CString::default(), surrounding_cursor: 0, // TODO: mark that there's no cursor content_hint: ContentHint::NONE, content_purpose: ContentPurpose::Normal, text_change_cause: ChangeCause::InputMethod, active: false, } } } pub struct IMService { /// Owned reference (still created and destroyed in C) pub im: c::InputMethod, sender: driver::Threaded, pending: IMProtocolState, current: IMProtocolState, // turn current into an idiomatic representation? preedit_string: String, serial: Wrapping, } pub enum SubmitError { /// The input method had not been activated NotActive, } impl IMService { pub fn new( im: c::InputMethod, sender: driver::Threaded, ) -> Box { // IMService will be referenced to by C, // so it needs to stay in the same place in memory via Box let imservice = Box::new(IMService { im, sender, pending: IMProtocolState::default(), current: IMProtocolState::default(), preedit_string: String::new(), serial: Wrapping(0u32), }); unsafe { c::imservice_connect_listeners( im, imservice.as_ref() as *const IMService, ); } imservice } pub fn commit_string(&self, text: &CString) -> Result<(), SubmitError> { match self.current.active { true => { unsafe { c::eek_input_method_commit_string(self.im, text.as_ptr()) } Ok(()) }, false => Err(SubmitError::NotActive), } } pub fn delete_surrounding_text( &self, before: u32, after: u32, ) -> Result<(), SubmitError> { match self.current.active { true => { unsafe { c::eek_input_method_delete_surrounding_text( self.im, before, after, ) } Ok(()) }, false => Err(SubmitError::NotActive), } } pub fn commit(&mut self) -> Result<(), SubmitError> { match self.current.active { true => { unsafe { c::eek_input_method_commit(self.im, self.serial.0) } Ok(()) }, false => Err(SubmitError::NotActive), } } pub fn is_active(&self) -> bool { self.current.active } fn send_event(&self) { let state = &self.current; let timestamp = Instant::now(); let message = if state.active { state::InputMethod::Active( state::InputMethodDetails { hint: state.content_hint, purpose: state.content_purpose, } ) } else { state::InputMethod::InactiveSince(timestamp) }; self.sender.send(Event::InputMethod(message)) .or_warn(&mut logging::Print, logging::Problem::Warning, "Can't send to state manager"); } } squeekboard-v1.17.1/src/keyboard.rs000066400000000000000000000214701422304253700172370ustar00rootroot00000000000000/*! State of the emulated keyboard and keys. * Regards the keyboard as if it was composed of switches. */ use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use std::io; use std::mem; use std::ptr; use std::rc::Rc; use std::string::FromUtf8Error; use ::action::Action; use ::util; // Traits use std::io::Write; use std::iter::{ FromIterator, IntoIterator }; #[derive(Debug, Clone, Copy, PartialEq)] pub enum PressType { Released = 0, Pressed = 1, } /// The extended, unambiguous layout-keycode #[derive(Debug, Clone)] pub struct KeyCode { pub code: u32, pub keymap_idx: usize, } bitflags!{ /// Map to `virtual_keyboard.modifiers` modifiers values /// From https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Keyboard_State pub struct Modifiers: u8 { const SHIFT = 0x1; const LOCK = 0x2; const CONTROL = 0x4; /// Alt const MOD1 = 0x8; const MOD2 = 0x10; const MOD3 = 0x20; /// Meta const MOD4 = 0x40; /// AltGr const MOD5 = 0x80; } } /// When the submitted actions of keys need to be tracked, /// they need a stable, comparable ID #[derive(Clone, PartialEq)] pub struct KeyStateId(*const KeyState); #[derive(Debug, Clone)] pub struct KeyState { pub pressed: PressType, /// A cache of raw keycodes derived from Action::Submit given a keymap pub keycodes: Vec, /// Static description of what the key does when pressed or released pub action: Action, } impl KeyState { #[must_use] pub fn into_released(self) -> KeyState { KeyState { pressed: PressType::Released, ..self } } #[must_use] pub fn into_pressed(self) -> KeyState { KeyState { pressed: PressType::Pressed, ..self } } /// KeyStates instances are the unique identifiers of pressed keys, /// and the actions submitted with them. pub fn get_id(keystate: &Rc>) -> KeyStateId { KeyStateId(keystate.as_ptr() as *const KeyState) } } /// Sorts an iterator by converting it to a Vector and back fn sorted<'a, I: Iterator>( iter: I ) -> impl Iterator { let mut v: Vec = iter.collect(); v.sort(); v.into_iter() } /// Generates a mapping where each key gets a keycode, starting from ~~8~~ /// HACK: starting from 9, because 8 results in keycode 0, /// which the compositor likes to discard pub fn generate_keycodes<'a, C: IntoIterator>( key_names: C, ) -> HashMap { HashMap::from_iter( // Sort to remove a source of indeterminism in keycode assignment. sorted(key_names.into_iter()) .zip(util::cycle_count(9..255)) .map(|(name, (code, keymap_idx))| ( String::from(name), KeyCode { code, keymap_idx }, )) ) } #[derive(Debug)] pub enum FormattingError { Utf(FromUtf8Error), Format(io::Error), } impl fmt::Display for FormattingError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { FormattingError::Utf(e) => write!(f, "UTF: {}", e), FormattingError::Format(e) => write!(f, "Format: {}", e), } } } impl From for FormattingError { fn from(e: io::Error) -> Self { FormattingError::Format(e) } } /// Index is the key code, String is the occupant. /// Starts all empty. /// https://gitlab.freedesktop.org/xorg/xserver/-/issues/260 type SingleKeyMap = [Option; 256]; fn single_key_map_new() -> SingleKeyMap { // Why can't we just initialize arrays without tricks -_- ? unsafe { // Inspired by // https://www.reddit.com/r/rust/comments/5n7bh1/how_to_create_an_array_of_a_type_with_clone_but/ #[cfg(feature = "rustc_less_1_36")] let mut array: SingleKeyMap = mem::uninitialized(); #[cfg(not(feature = "rustc_less_1_36"))] let mut array: SingleKeyMap = mem::MaybeUninit::uninit().assume_init(); for element in array.iter_mut() { ptr::write(element, None); } array } } pub fn generate_keymaps(symbolmap: HashMap::) -> Result, FormattingError> { let mut bins: Vec = Vec::new(); for (name, KeyCode { code, keymap_idx }) in symbolmap.into_iter() { if keymap_idx >= bins.len() { bins.resize_with( keymap_idx + 1, || single_key_map_new(), ); } bins[keymap_idx][code as usize] = Some(name); } let mut out = Vec::new(); for bin in bins { out.push(generate_keymap(&bin)?); } Ok(out) } /// Generates a de-facto single level keymap. /// Key codes must not repeat and must remain between 9 and 255. fn generate_keymap( symbolmap: &SingleKeyMap, ) -> Result { let mut buf: Vec = Vec::new(); writeln!( buf, "xkb_keymap {{ xkb_keycodes \"squeekboard\" {{ minimum = 8; maximum = 255;" )?; let pairs: Vec<(&String, usize)> = symbolmap.iter() // Attach a key code to each cell. .enumerate() // Get rid of empty keycodes. .filter_map(|(code, name)| name.as_ref().map(|n| (n, code))) .collect(); // Xorg can only consume up to 255 keys, so this may not work in Xwayland. // Two possible solutions: // - use levels to cram multiple characters into one key // - swap layouts on key presses for (_name, keycode) in &pairs { write!( buf, " = {0};", keycode, )?; } writeln!( buf, " indicator 1 = \"Caps Lock\"; // Xwayland won't accept without it. }}; xkb_symbols \"squeekboard\" {{ " )?; for (name, keycode) in pairs { write!( buf, " key {{ [ {} ] }};", keycode, name, )?; } writeln!( buf, " }}; xkb_types \"squeekboard\" {{ virtual_modifiers Squeekboard; // No modifiers! Needed for Xorg for some reason. // Those names are needed for Xwayland. type \"ONE_LEVEL\" {{ modifiers= none; level_name[Level1]= \"Any\"; }}; type \"TWO_LEVEL\" {{ level_name[Level1]= \"Base\"; }}; type \"ALPHABETIC\" {{ level_name[Level1]= \"Base\"; }}; type \"KEYPAD\" {{ level_name[Level1]= \"Base\"; }}; type \"SHIFT+ALT\" {{ level_name[Level1]= \"Base\"; }}; }}; xkb_compatibility \"squeekboard\" {{ // Needed for Xwayland again. interpret Any+AnyOf(all) {{ action= SetMods(modifiers=modMapMods,clearLocks); }}; }}; }};" )?; //println!("{}", String::from_utf8(buf.clone()).unwrap()); String::from_utf8(buf).map_err(FormattingError::Utf) } #[cfg(test)] mod tests { use super::*; use xkbcommon::xkb; #[test] fn test_keymap_single_resolve() { let mut key_map = single_key_map_new(); key_map[9] = Some("a".into()); key_map[10] = Some("c".into()); let keymap_str = generate_keymap(&key_map).unwrap(); let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); let keymap = xkb::Keymap::new_from_string( &context, keymap_str.clone(), xkb::KEYMAP_FORMAT_TEXT_V1, xkb::KEYMAP_COMPILE_NO_FLAGS, ).expect("Failed to create keymap"); let state = xkb::State::new(&keymap); assert_eq!(state.key_get_one_sym(9), xkb::KEY_a); assert_eq!(state.key_get_one_sym(10), xkb::KEY_c); } #[test] fn test_keymap_second_resolve() { let keymaps = generate_keymaps(hashmap!( "a".into() => KeyCode { keymap_idx: 1, code: 9 }, )).unwrap(); let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); let keymap = xkb::Keymap::new_from_string( &context, keymaps[1].clone(), // this index is part of the test xkb::KEYMAP_FORMAT_TEXT_V1, xkb::KEYMAP_COMPILE_NO_FLAGS, ).expect("Failed to create keymap"); let state = xkb::State::new(&keymap); assert_eq!(state.key_get_one_sym(9), xkb::KEY_a); } #[test] fn test_symbolmap_overflow() { // The 257th key (U1101) is interesting. // Use Unicode encoding for being able to use in xkb keymaps. let keynames = (0..258).map(|num| format!("U{:04X}", 0x1000 + num)); let keycodes = generate_keycodes(keynames); // test now let code = keycodes.get("U1101").expect("Did not find the tested keysym"); assert_eq!(code.keymap_idx, 1); } } squeekboard-v1.17.1/src/layout.h000066400000000000000000000051161422304253700165560ustar00rootroot00000000000000#ifndef __LAYOUT_H #define __LAYOUT_H #include #include #include "eek/eek-element.h" #include "eek/eek-gtk-keyboard.h" #include "eek/eek-renderer.h" #include "eek/eek-types.h" #include "src/submission.h" #include "virtual-keyboard-unstable-v1-client-protocol.h" #include "text-input-unstable-v3-client-protocol.h" enum squeek_arrangement_kind { ARRANGEMENT_KIND_BASE = 0, ARRANGEMENT_KIND_WIDE = 1, }; struct squeek_layout_state { enum squeek_arrangement_kind arrangement; enum zwp_text_input_v3_content_purpose purpose; enum zwp_text_input_v3_content_hint hint; char *layout_name; char *overlay_name; }; struct squeek_layout; struct transformation squeek_layout_calculate_transformation( const struct squeek_layout *layout, double allocation_width, double allocation_size); struct squeek_layout *squeek_load_layout(const char *name, uint32_t type, uint32_t variant_type, const char *overlay_name); enum squeek_arrangement_kind squeek_layout_get_kind(const struct squeek_layout *); uint32_t squeek_layout_get_purpose(const struct squeek_layout *); void squeek_layout_free(struct squeek_layout*); void squeek_layout_release(struct squeek_layout *layout, struct submission *submission, struct transformation widget_to_layout, uint32_t timestamp, EekboardContextService *manager, EekGtkKeyboard *ui_keyboard); void squeek_layout_release_all_only(struct squeek_layout *layout, struct submission *submission, uint32_t timestamp); void squeek_layout_depress(struct squeek_layout *layout, struct submission *submission, double x_widget, double y_widget, struct transformation widget_to_layout, uint32_t timestamp, EekGtkKeyboard *ui_keyboard); void squeek_layout_drag(struct squeek_layout *layout, struct submission *submission, double x_widget, double y_widget, struct transformation widget_to_layout, uint32_t timestamp, EekboardContextService *manager, EekGtkKeyboard *ui_keyboard); void squeek_layout_draw_all_changed(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr, struct submission *submission); void squeek_draw_layout_base_view(struct squeek_layout *layout, EekRenderer* renderer, cairo_t *cr); #endif squeekboard-v1.17.1/src/layout.rs000066400000000000000000001337161422304253700167630ustar00rootroot00000000000000/*! * Layout-related data. * * The `View` contains `Row`s and each `Row` contains `Button`s. * They carry data relevant to their positioning only, * except the Button, which also carries some data * about its appearance and function. * * The layout is determined bottom-up, by measuring `Button` sizes, * deriving `Row` sizes from them, and then centering them within the `View`. * * That makes the `View` position immutable, * and therefore different than the other positions. * * Note that it might be a better idea * to make `View` position depend on its contents, * and let the renderer scale and center it within the widget. */ use std::cell::RefCell; use std::collections::{ HashMap, HashSet }; use std::ffi::CString; use std::fmt; use std::rc::Rc; use std::vec::Vec; use ::action::Action; use ::drawing; use ::keyboard::KeyState; use ::logging; use ::manager; use ::submission::{ Submission, SubmitData, Timestamp }; use ::util::find_max_double; use ::imservice::ContentPurpose; // Traits use std::borrow::Borrow; use ::logging::Warn; /// Gathers stuff defined in C or called by C pub mod c { use super::*; use gtk_sys; use std::os::raw::c_void; use crate::submission::c::Submission as CSubmission; use std::ops::{ Add, Sub }; // The following defined in C #[repr(transparent)] #[derive(Copy, Clone)] pub struct EekGtkKeyboard(pub *const gtk_sys::GtkWidget); extern "C" { #[allow(improper_ctypes)] pub fn eek_gtk_keyboard_emit_feedback( keyboard: EekGtkKeyboard, ); } /// Defined in eek-types.h #[repr(C)] #[derive(Clone, Debug, PartialEq)] pub struct Point { pub x: f64, pub y: f64, } impl Add for Point { type Output = Self; fn add(self, other: Self) -> Self { &self + other } } impl Add for &Point { type Output = Point; fn add(self, other: Point) -> Point { Point { x: self.x + other.x, y: self.y + other.y, } } } impl Sub<&Point> for Point { type Output = Point; fn sub(self, other: &Point) -> Point { Point { x: self.x - other.x, y: self.y - other.y, } } } /// Defined in eek-types.h #[repr(C)] #[derive(Clone, Debug, PartialEq)] pub struct Bounds { pub x: f64, pub y: f64, pub width: f64, pub height: f64 } impl Bounds { pub fn contains(&self, point: &Point) -> bool { point.x > self.x && point.x < self.x + self.width && point.y > self.y && point.y < self.y + self.height } } /// Translate and then scale #[repr(C)] pub struct Transformation { pub origin_x: f64, pub origin_y: f64, pub scale: f64, } impl Transformation { /// Applies the new transformation after this one pub fn chain(self, next: Transformation) -> Transformation { Transformation { origin_x: self.origin_x + self.scale * next.origin_x, origin_y: self.origin_y + self.scale * next.origin_y, scale: self.scale * next.scale, } } fn forward(&self, p: Point) -> Point { Point { x: (p.x - self.origin_x) / self.scale, y: (p.y - self.origin_y) / self.scale, } } fn reverse(&self, p: Point) -> Point { Point { x: p.x * self.scale + self.origin_x, y: p.y * self.scale + self.origin_y, } } pub fn reverse_bounds(&self, b: Bounds) -> Bounds { let start = self.reverse(Point { x: b.x, y: b.y }); let end = self.reverse(Point { x: b.x + b.width, y: b.y + b.height, }); Bounds { x: start.x, y: start.y, width: end.x - start.x, height: end.y - start.y, } } } // This is constructed only in C, no need for warnings #[allow(dead_code)] #[repr(transparent)] pub struct LevelKeyboard(*const c_void); // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers /// Positions the layout contents within the available space. /// The origin of the transformation is the point inside the margins. #[no_mangle] pub extern "C" fn squeek_layout_calculate_transformation( layout: *const Layout, allocation_width: f64, allocation_height: f64, ) -> Transformation { let layout = unsafe { &*layout }; layout.calculate_transformation(Size { width: allocation_width, height: allocation_height, }) } #[no_mangle] pub extern "C" fn squeek_layout_get_kind(layout: *const Layout) -> u32 { let layout = unsafe { &*layout }; layout.kind.clone() as u32 } #[no_mangle] pub extern "C" fn squeek_layout_get_purpose(layout: *const Layout) -> u32 { let layout = unsafe { &*layout }; layout.purpose.clone() as u32 } #[no_mangle] pub extern "C" fn squeek_layout_free(layout: *mut Layout) { unsafe { Box::from_raw(layout) }; } /// Entry points for more complex procedures and algorithms which span multiple modules pub mod procedures { use super::*; /// Release pointer in the specified position #[no_mangle] pub extern "C" fn squeek_layout_release( layout: *mut Layout, submission: CSubmission, widget_to_layout: Transformation, time: u32, manager: manager::c::Manager, ui_keyboard: EekGtkKeyboard, ) { let time = Timestamp(time); let layout = unsafe { &mut *layout }; let submission = submission.clone_ref(); let mut submission = submission.borrow_mut(); let ui_backend = UIBackend { widget_to_layout, keyboard: ui_keyboard, }; // The list must be copied, // because it will be mutated in the loop for key in layout.pressed_keys.clone() { let key: &Rc> = key.borrow(); seat::handle_release_key( layout, &mut submission, Some(&ui_backend), time, Some(manager), key, ); } drawing::queue_redraw(ui_keyboard); } /// Release all buttons but don't redraw #[no_mangle] pub extern "C" fn squeek_layout_release_all_only( layout: *mut Layout, submission: CSubmission, time: u32, ) { let layout = unsafe { &mut *layout }; let submission = submission.clone_ref(); let mut submission = submission.borrow_mut(); // The list must be copied, // because it will be mutated in the loop for key in layout.pressed_keys.clone() { let key: &Rc> = key.borrow(); seat::handle_release_key( layout, &mut submission, None, // don't update UI Timestamp(time), None, // don't switch layouts &mut key.clone(), ); } } #[no_mangle] pub extern "C" fn squeek_layout_depress( layout: *mut Layout, submission: CSubmission, x_widget: f64, y_widget: f64, widget_to_layout: Transformation, time: u32, ui_keyboard: EekGtkKeyboard, ) { let layout = unsafe { &mut *layout }; let submission = submission.clone_ref(); let mut submission = submission.borrow_mut(); let point = widget_to_layout.forward( Point { x: x_widget, y: y_widget } ); let state = layout.find_button_by_position(point) .map(|place| place.button.state.clone()); if let Some(state) = state { seat::handle_press_key( layout, &mut submission, Timestamp(time), &state, ); // maybe TODO: draw on the display buffer here drawing::queue_redraw(ui_keyboard); unsafe { eek_gtk_keyboard_emit_feedback(ui_keyboard); } }; } // FIXME: this will work funny // when 2 touch points are on buttons and moving one after another // Solution is to have separate pressed lists for each point #[no_mangle] pub extern "C" fn squeek_layout_drag( layout: *mut Layout, submission: CSubmission, x_widget: f64, y_widget: f64, widget_to_layout: Transformation, time: u32, manager: manager::c::Manager, ui_keyboard: EekGtkKeyboard, ) { let time = Timestamp(time); let layout = unsafe { &mut *layout }; let submission = submission.clone_ref(); let mut submission = submission.borrow_mut(); let ui_backend = UIBackend { widget_to_layout, keyboard: ui_keyboard, }; let point = ui_backend.widget_to_layout.forward( Point { x: x_widget, y: y_widget } ); let pressed = layout.pressed_keys.clone(); let button_info = { let place = layout.find_button_by_position(point); place.map(|place| {( place.button.state.clone(), place.button.clone(), place.offset, )}) }; if let Some((state, _button, _view_position)) = button_info { let mut found = false; for wrapped_key in pressed { let key: &Rc> = wrapped_key.borrow(); if Rc::ptr_eq(&state, &wrapped_key.0) { found = true; } else { seat::handle_release_key( layout, &mut submission, Some(&ui_backend), time, Some(manager), key, ); } } if !found { seat::handle_press_key( layout, &mut submission, time, &state, ); // maybe TODO: draw on the display buffer here unsafe { eek_gtk_keyboard_emit_feedback(ui_keyboard); } } } else { for wrapped_key in pressed { let key: &Rc> = wrapped_key.borrow(); seat::handle_release_key( layout, &mut submission, Some(&ui_backend), time, Some(manager), key, ); } } drawing::queue_redraw(ui_keyboard); } #[cfg(test)] mod test { use super::*; fn near(a: f64, b: f64) -> bool { (a - b).abs() < ((a + b) * 0.001f64).abs() } #[test] fn transform_back() { let transform = Transformation { origin_x: 10f64, origin_y: 11f64, scale: 12f64, }; let point = Point { x: 1f64, y: 1f64 }; let transformed = transform.reverse(transform.forward(point.clone())); assert!(near(point.x, transformed.x)); assert!(near(point.y, transformed.y)); } } } } pub struct ButtonPlace<'a> { button: &'a Button, offset: c::Point, } #[derive(Debug, Clone, PartialEq)] pub struct Size { pub width: f64, pub height: f64, } #[derive(Debug, Clone, PartialEq)] pub enum Label { /// Text used to display the symbol Text(CString), /// Icon name used to render the symbol IconName(CString), } /// The graphical representation of a button #[derive(Clone, Debug)] pub struct Button { /// ID string, e.g. for CSS pub name: CString, /// Label to display to the user pub label: Label, pub size: Size, /// The name of the visual class applied pub outline_name: CString, /// current state, shared with other buttons pub state: Rc>, } impl Button { pub fn get_bounds(&self) -> c::Bounds { c::Bounds { x: 0.0, y: 0.0, width: self.size.width, height: self.size.height, } } } /// The graphical representation of a row of buttons #[derive(Clone, Debug)] pub struct Row { /// Buttons together with their offset from the left relative to the row. /// ie. the first button always start at 0. buttons: Vec<(f64, Box