diff --git a/dconf/.config/dconf/user b/dconf/.config/dconf/user index d0559a685..e644d720f 100644 Binary files a/dconf/.config/dconf/user and b/dconf/.config/dconf/user differ diff --git a/qtile/.config/qtile/LICENSE b/qtile/.config/qtile/LICENSE new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/qtile/.config/qtile/LICENSE @@ -0,0 +1,674 @@ + 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 +. diff --git a/qtile/.config/qtile/art/Arch_Wallpaper-MM.png b/qtile/.config/qtile/art/Arch_Wallpaper-MM.png deleted file mode 100644 index 19a3002f5..000000000 Binary files a/qtile/.config/qtile/art/Arch_Wallpaper-MM.png and /dev/null differ diff --git a/qtile/.config/qtile/art/Archlinux-icon.svg b/qtile/.config/qtile/art/Archlinux-icon.svg deleted file mode 100644 index e01378af3..000000000 Binary files a/qtile/.config/qtile/art/Archlinux-icon.svg and /dev/null differ diff --git a/qtile/.config/qtile/art/base.png b/qtile/.config/qtile/art/base.png deleted file mode 100644 index 19bf67e34..000000000 Binary files a/qtile/.config/qtile/art/base.png and /dev/null differ diff --git a/qtile/.config/qtile/cfg.json b/qtile/.config/qtile/cfg.json new file mode 100644 index 000000000..748158975 --- /dev/null +++ b/qtile/.config/qtile/cfg.json @@ -0,0 +1,14 @@ +{ + "bar": "shapes", + "bar2": "shapes", + "browser": "firefox", + "term": "alacritty", + "term2": "kitty", + "editor": "code", + "files": "nemo", + "menu": "menu", + "power": "powermenu_run", + "passwords": "passmenu", + "youtube": "youtube_subs", + "wallpaper": "~/.config/feh/backgrounds/Arch_Wallpaper-MM.png" +} \ No newline at end of file diff --git a/qtile/.config/qtile/colors.py b/qtile/.config/qtile/colors.py deleted file mode 100644 index 3bac6052e..000000000 --- a/qtile/.config/qtile/colors.py +++ /dev/null @@ -1,38 +0,0 @@ -colorScheme = [ - "283036", # 0 - "ff5959", # 1 - "59ff59", # 2 - "ffff59", # 3 - "9059ff", # 4 - "ff59f9", # 5 - "59fff9", # 6 - "e5e9f0", # 7 - "43515e", # 8 - "ffa6a6", # 9 - "a6ffa6", # 10 - "ffffa6", # 11 - "c5a6ff", # 12 - "ffa6fc", # 13 - "a6fffc", # 14 - "e5e9f0", # 15 - "e5e9f0", # foregroundColor - "283036", # backgroundColor - "434c5e", # backgroundColor -] - -widgetColors = [ - "ff5959", # 1 - "59ff59", # 2 - "ffff59", # 3 - "9059ff", # 4 - "ff59f9", # 5 - "59fff9", # 6 - "e5e9f0", # 7 - "43515e", # 8 - "ffa6a6", # 9 - "a6ffa6", # 10 -] - -foregroundColor = colorScheme[16] -backgroundColor = colorScheme[17] -currentColor = colorScheme[18] diff --git a/qtile/.config/qtile/config.py b/qtile/.config/qtile/config.py index 572a29665..a91f90bc1 100644 --- a/qtile/.config/qtile/config.py +++ b/qtile/.config/qtile/config.py @@ -1,317 +1,14 @@ -#!/usr/bin/env python - -# Copyright 2022 The-Repo-Club - -# 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, Variables.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. - -import locale -import subprocess - -from widgets import Widgets -from groups import Groups -from keys import Keys -from variables import Commands, Variables -from colors import colorScheme, currentColor - -locale.setlocale(locale.LC_ALL, "") - -from libqtile import qtile, bar, layout, hook -from libqtile.config import Key, Click, Drag, Screen, Match, ScratchPad, DropDown - -from libqtile.lazy import lazy - -from typing import Callable - -################### -## Color Schemes ## -################### - -from colors import foregroundColor, backgroundColor - -########### -## Utils ## -########### - - -def go_to_group(name: str) -> Callable: - def _inner(qtile: qtile) -> None: - if len(qtile.screens) == 1: - qtile.groups_map[name].cmd_toscreen() - return - - if name in "12345": - qtile.focus_screen(0) - qtile.groups_map[name].cmd_toscreen() - else: - qtile.focus_screen(1) - qtile.groups_map[name].cmd_toscreen() - - return _inner - - -############ -## Groups ## -############ - -groups = Groups.groups - -# Define scratchpads -groups.append( - ScratchPad( - "Hyper_L", - [ - DropDown( - "term", - "kitty --name=scratch", - width=0.6, - height=0.6, - x=0.2, - y=0.1, - opacity=1, - ), - DropDown( - "clifm", - "kitty --name=clifm -e clifm", - width=0.6, - height=0.6, - x=0.2, - y=0.1, - opacity=0.8, - ), - DropDown( - "btop", - "kitty --name=btop -e btop", - width=0.6, - height=0.6, - x=0.2, - y=0.1, - opacity=0.8, - ), - DropDown( - "volume", - "pavucontrol", - width=0.6, - height=0.6, - x=0.2, - y=0.1, - opacity=0.8, - ), - ], - ) +from core import ( # noqa: F401 + floating_layout, + groups, + hooks, + keys, + layouts, + mouse, + screens, + widget_defaults, ) -################## -## Key Bindings ## -################## - -keys = Keys.keys - -for i in groups: - keys.extend( - [ - Key([Variables.MOD], i.name, lazy.function(go_to_group(i.name))), - Key([Variables.MOD, "shift"], i.name, lazy.window.togroup(i.name)), - ] - ) - - -#################### -## Layouts Config ## -#################### - -# Layout Theme -layout_theme = { - "border_width": 2, - "margin": 5, - "border_focus": colorScheme[10], - "border_normal": currentColor, -} - -layouts = [ - layout.Tile( - **layout_theme, - add_after_last=True, - ), - layout.Columns( - **layout_theme, - ), - layout.Max( - **layout_theme, - ), - # Try more layouts by unleashing below layouts. - layout.Stack(**layout_theme, num_stacks=2), - # layout.Bsp(**layout_theme), - layout.MonadThreeCol( - **layout_theme, - ratio=0.4, - new_client_position="after_current", - ), - layout.Matrix( - **layout_theme, - ), - layout.MonadTall( - **layout_theme, - ), - layout.MonadWide( - **layout_theme, - ), - layout.RatioTile( - **layout_theme, - ), - # layout.TreeTab(**layout_theme,), - # layout.VerticVariables.ALTile(**layout_theme,), - layout.Zoomy( - **layout_theme, - ), -] - -floating_layout = layout.Floating( - **layout_theme, - float_rules=[ - # Run the utility of `xprop` to see the wm class and name of an X client. - *layout.Floating.default_float_rules, - Match(wm_class="confirmreset"), # gitk - Match(wm_class="makebranch"), # gitk - Match(wm_class="maketag"), # gitk - Match(wm_class="ssh-askpass"), # ssh-askpass - Match(title="branchdialog"), # gitk - Match(title="pinentry"), # GPG key password entry - ], -) - -################### -## Screen Config ## -################### - -widget_defaults = dict( - font="Hack Nerd Font", - foreground=foregroundColor, - background=backgroundColor, - fontsize=14, - padding=2, -) -extension_defaults = widget_defaults.copy() - -screens = [ - Screen( - top=bar.Bar( - [ - Widgets.launcher, - Widgets.groupBox1, - Widgets.currentLayout, - Widgets.power, - Widgets.windowName, - Widgets.volume, - Widgets.backlight, - Widgets.net, - Widgets.date, - Widgets.time, - ], - 28, - background=backgroundColor, - margin=5, - # border_width=[2, 2, 2, 2], # Draw top and bottom borders - # border_color=["#a6ffa6", "#a6ffa6", "#a6ffa6", - # "#a6ffa6"] # Borders are green - ), - bottom=bar.Bar( - [ - Widgets.weather, - Widgets.updates, - Widgets.space, - Widgets.tray, - Widgets.sep, - Widgets.xcompmgr, - Widgets.github, - Widgets.chords, - ], - 28, - background=backgroundColor, - margin=5, - # border_width=[2, 2, 2, 2], # Draw top and bottom borders - # border_color=["#a6ffa6", "#a6ffa6", "#a6ffa6", - # "#a6ffa6"] # Borders are green - ), - ), - Screen( - top=bar.Bar( - [ - Widgets.launcher, - Widgets.groupBox2, - Widgets.currentLayout, - Widgets.power, - Widgets.windowName, - Widgets.volume, - Widgets.backlight, - Widgets.net, - Widgets.date, - Widgets.time, - ], - 28, - background=backgroundColor, - margin=5, - # border_width=[2, 2, 2, 2], # Draw top and bottom borders - # border_color=["#a6ffa6", "#a6ffa6", "#a6ffa6", - # "#a6ffa6"] # Borders are green - ), - bottom=bar.Bar( - [ - Widgets.weather, - Widgets.updates, - Widgets.space, - Widgets.xcompmgr, - Widgets.github, - Widgets.chords, - ], - 28, - background=backgroundColor, - margin=5, - # border_width=[2, 2, 2, 2], # Draw top and bottom borders - # border_color=["#a6ffa6", "#a6ffa6", "#a6ffa6", - # "#a6ffa6"] # Borders are green - ), - ), -] - -################### -## Floating Drag ## -################### -mouse = [ - Drag( - [Variables.MOD], - "Button1", - lazy.window.set_position_floating(), - start=lazy.window.get_position(), - ), - Drag( - [Variables.MOD], - "Button3", - lazy.window.set_size_floating(), - start=lazy.window.get_size(), - ), - Click([Variables.MOD], "Button2", lazy.window.bring_to_front()), -] - -################### -## Other Configs ## -################### - follow_mouse_focus = True bring_front_click = False cursor_warp = False @@ -335,54 +32,3 @@ wl_input_rules = None # We choose LG3D to maximize irony: it is a 3D non-reparenting WM written in # java that happens to be on java's whitelist. wmname = "Qtile" - - -@hook.subscribe.screens_reconfigured -async def _(): - if len(qtile.screens) > 1: - Widgets.groupBox1.visible_groups = ["1", "2", "3", "4", "5"] - Widgets.groupBox2.visible_groups = ["6", "7", "8", "9", "0"] - else: - Widgets.groupBox1.visible_groups = [ - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "0", - ] - - -@hook.subscribe.startup_once -def start_once(): - if len(qtile.screens) > 1: - Widgets.groupBox1.visible_groups = ["1", "2", "3", "4", "5"] - Widgets.groupBox2.visible_groups = ["6", "7", "8", "9", "0"] - else: - Widgets.groupBox1.visible_groups = [ - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "0", - ] - - for configure in Commands.configure: - subprocess.Popen([configure], shell=True) - - for command in Commands.autostart: - subprocess.Popen([command], shell=True) - - -@hook.subscribe.client_managed -def auto_focus(window): - window.group.cmd_toscreen() diff --git a/qtile/.config/qtile/core/__init__.py b/qtile/.config/qtile/core/__init__.py new file mode 100644 index 000000000..6266a5a04 --- /dev/null +++ b/qtile/.config/qtile/core/__init__.py @@ -0,0 +1,22 @@ +from core import hooks +from core.bar.base import defaults +from core.groups import groups +from core.keys import keys +from core.layouts import floating_layout, layouts +from core.mouse import mouse +from core.screens import screens + +widget_defaults = defaults.copy() +extension_defaults = defaults.copy() + +__all__ = [ + "extension_defaults", + "floating_layout", + "groups", + "hooks", + "keys", + "layouts", + "mouse", + "screens", + "widget_defaults", +] diff --git a/qtile/.config/qtile/core/bar/__init__.py b/qtile/.config/qtile/core/bar/__init__.py new file mode 100644 index 000000000..3d186c31a --- /dev/null +++ b/qtile/.config/qtile/core/bar/__init__.py @@ -0,0 +1,5 @@ +from core.bar.base import Bar + +__all__ = [ + "Bar", +] diff --git a/qtile/.config/qtile/core/bar/base.py b/qtile/.config/qtile/core/bar/base.py new file mode 100644 index 000000000..ea929a500 --- /dev/null +++ b/qtile/.config/qtile/core/bar/base.py @@ -0,0 +1,75 @@ +from importlib import import_module +from os import listdir +from os.path import isfile, join + +from libqtile import bar + +from extras import PowerLineDecoration, RectDecoration +from utils.config import cfg + +defaults = { + "font": "Hack Nerd Font", + "fontsize": 10, + "padding": None, +} + + +class Bar: + def __init__(self, theme: str) -> None: + self.theme = theme + + @property + def themes(self) -> set[str]: + path = join(cfg.path(), "core", "bar") + excluded_files = {"__init__.py", "base.py"} + return { + file.removesuffix(".py") + for file in listdir(path) + if isfile(join(path, file)) and file not in excluded_files + } + + @property + def config(self) -> dict | None: + if self.theme not in self.themes: + return None + module = import_module(f"core.bar.{self.theme}") + return {"widgets": module.widgets(), **module.bar} + + def create(self) -> bar.BarType | None: + if not self.config: + return None + return bar.Bar(**self.config) + + +def base(bg: str | None, fg: str) -> dict: + return { + "background": bg, + "foreground": fg, + } + + +def icon_font(size=15) -> dict: + font = "Hack Nerd Font" + return {"font": font, "fontsize": size} + + +def powerline(path: str | list[tuple], size=9) -> dict: + return { "decorations": [ + PowerLineDecoration( + path=path, + size=size, + ) + ]} # fmt: skip + + +def rectangle(side: str = "") -> dict: + return { "decorations": [ + RectDecoration( + filled = True, + radius = { + "left": [8, 0, 0, 8], + "right": [0, 8, 8, 0] + }.get(side, 8), + use_widget_background = True, + ) + ]} # fmt: skip diff --git a/qtile/.config/qtile/core/bar/shapes.py b/qtile/.config/qtile/core/bar/shapes.py new file mode 100644 index 000000000..24548aa3b --- /dev/null +++ b/qtile/.config/qtile/core/bar/shapes.py @@ -0,0 +1,242 @@ +from libqtile.bar import CALCULATED +from libqtile.lazy import lazy + +from core.bar.base import base, icon_font, powerline, rectangle +from extras import Clock, GroupBox, TextBox, modify, widget +from utils.config import cfg +from utils.palette import palette + +bar = { + "background": palette.backgroundColor, + "border_color": palette.backgroundColor, + "border_width": 2, + "margin": 5, + "opacity": 1, + "size": 28, +} + + +def sep(fg, offset=0, padding=8) -> TextBox: + return TextBox( + **base(None, fg), + **icon_font(), + offset=offset, + padding=padding, + text="󰇙", + ) + + +def menu(bg, fg) -> TextBox: + return modify( + TextBox, + **base(bg, fg), + **icon_font(), + **rectangle(), + mouse_callbacks={"Button1": lazy.spawn(cfg.menu)}, + offset=4, + padding=7, + text="󰍜", + ) + + +def groups(bg) -> GroupBox: + return GroupBox( + **icon_font(), + background=bg, + borderwidth=2, + colors=palette.widgetColors, + highlight_color=palette.currentColor, + highlight_method="line", + inactive=palette.foregroundColor, + invert=True, + margin_y=4, + margin_x=4, + padding_y=6, + padding_x=6, + rainbow=True, + hide_unused=True, + use_mouse_wheel=True, + ) + + +def volume(bg, fg) -> list: + return [ + modify( + TextBox, + **base(bg, fg), + **icon_font(), + **rectangle("left"), + text="", + x=4, + ), + widget.Volume( + **base(bg, fg), + **powerline("arrow_right"), + check_mute_command="pamixer --get-mute", + check_mute_string="true", + get_volume_command="pamixer --get-volume-human", + mute_command="pamixer --toggle-mute", + update_interval=0.1, + volume_down_command="pamixer --decrease 5", + volume_up_command="pamixer --increase 5", + ), + ] + + +def updates(bg, fg) -> list: + return [ + TextBox( + **base(bg, fg), + **icon_font(), + offset=-1, + text="", + x=-5, + ), + widget.CheckUpdates( + **base(bg, fg), + **rectangle("right"), + colour_have_updates=fg, + colour_no_updates=fg, + display_format="{updates} updates ", + distro="Arch_checkupdates", + initial_text="No updates ", + no_update_string="No updates ", + padding=0, + update_interval=3600, + ), + ] + + +def power(bg, fg) -> TextBox: + return modify( + TextBox, + **base(bg, fg), + **icon_font(), + **rectangle(), + mouse_callbacks={"Button1": lazy.spawn(cfg.power)}, + offset=4, + padding=7, + text="", + ) + + +def window_name(bg, fg) -> object: + return widget.WindowName( + **base(bg, fg), + format="{name}", + max_chars=60, + width=CALCULATED, + ) + + +def cpu(bg, fg) -> list: + return [ + TextBox( + **base(bg, fg), + **icon_font(), + **rectangle("left"), + offset=3, + text="󰍛", + x=5, + ), + widget.CPU( + **base(bg, fg), + **powerline("arrow_right"), + format="{load_percent:.0f}%", + ), + ] + + +def ram(bg, fg) -> list: + return [ + TextBox( + **base(bg, fg), + **icon_font(), + offset=-2, + padding=5, + text="󰘚", + x=-2, + ), + widget.Memory( + **base(bg, fg), + **powerline("arrow_right"), + format="{MemUsed: .0f}{mm}/{SwapUsed: .0f}{ms} ", + padding=-1, + ), + ] + + +def disk(bg, fg) -> list: + return [ + TextBox( + **base(bg, fg), + **icon_font(), + offset=-1, + text="", + x=-5, + ), + widget.DF( + **base(bg, fg), + **rectangle("right"), + format="{f} GB ", + padding=0, + partition="/", + visible_on_warn=False, + warn_color=fg, + ), + ] + + +def clock(bg, fg) -> list: + return [ + modify( + TextBox, + **base(bg, fg), + **icon_font(), + **rectangle("left"), + offset=2, + text="", + x=4, + ), + modify( + Clock, + **base(bg, fg), + **rectangle("right"), + format="%A - %I:%M %p ", + long_format="%B %-d, %Y ", + padding=6, + ), + ] + + +def tray(bg, fg) -> list: + return widget.Systray( + **base(bg, fg), + fmt="{}", + padding=5, + ) + + +def widgets(): + return [ + widget.Spacer(length=2), + menu(palette.colorScheme[2], palette.currentColor), + sep(palette.currentColor, offset=-8), + groups(None), + sep(palette.currentColor, offset=4, padding=4), + *volume(palette.colorScheme[3], palette.currentColor), + *updates(palette.colorScheme[12], palette.currentColor), + sep(palette.currentColor, offset=4, padding=4), + power(palette.colorScheme[1], palette.currentColor), + widget.Spacer(), + window_name(None, palette.foregroundColor), + widget.Spacer(), + *cpu(palette.colorScheme[5], palette.currentColor), + *ram(palette.colorScheme[6], palette.currentColor), + *disk(palette.colorScheme[9], palette.currentColor), + sep(palette.currentColor), + tray(None, palette.currentColor), + sep(palette.currentColor), + *clock(palette.colorScheme[10], palette.currentColor), + widget.Spacer(length=2), + ] diff --git a/qtile/.config/qtile/core/groups.py b/qtile/.config/qtile/core/groups.py new file mode 100644 index 000000000..04a5e83e1 --- /dev/null +++ b/qtile/.config/qtile/core/groups.py @@ -0,0 +1,134 @@ +import re +from libqtile.config import Group, Key, Match, ScratchPad, DropDown +from libqtile.lazy import lazy + +from core.keys import keys, mod +from utils.match import wm_class + +groups: list[Group] = [] + +for key, label, layout, matches in [ + ( + "1", + "一", + "monadthreecol", + Match(wm_class=re.compile("^Alacritty.*|^Kitty.*", re.IGNORECASE)), + ), + ( + "2", + "二", + "max", + Match(wm_class=re.compile("^Code.*|^Jetbrains.*", re.IGNORECASE)), + ), + ( + "3", + "三", + None, + Match(wm_class=re.compile("^Nemo.*", re.IGNORECASE)), + ), + ( + "4", + "四", + "max", + Match(wm_class=re.compile("^Aseprite.*|^Krita.*", re.IGNORECASE)), + ), + ( + "5", + "五", + "max", + Match(wm_class=re.compile("^CmusImage.*", re.IGNORECASE)), + ), + ( + "6", + "六", + "max", + Match(wm_class=re.compile("^Firefox.*|^Brave.*", re.IGNORECASE)), + ), + ( + "7", + "七", + "max", + Match(wm_class=re.compile("^Mail.*|^Thunderbird.*", re.IGNORECASE)), + ), + ( + "8", + "八", + "max", + Match(wm_class=re.compile("^Steam.*|^Minecraft.*|^0ad.*", re.IGNORECASE)), + ), + ( + "9", + "九", + "max", + Match(wm_class=re.compile("^Discord.*", re.IGNORECASE)), + ), + ( + "0", + "零", + "max", + Match(wm_class=re.compile("^Software.*|^Virt.*|^Btop.*", re.IGNORECASE)), + ), +]: + groups.append( + Group( + name=key, + position=key, + matches=matches, + label=label, + layout=layout, + persist=True, + exclusive=False, + ) + ) + + keys.extend([ + # mod1 + letter of group = switch to group + Key([mod], key, lazy.group[key].toscreen(toggle=True)), + + # mod1 + shift + letter of group = move focused window to group + Key([mod, "shift"], key, lazy.window.togroup(key)), + ]) # fmt: skip + + groups.append( + ScratchPad( + "Hyper_L", + [ + DropDown( + "term", + "kitty --name=scratch", + width=0.6, + height=0.6, + x=0.2, + y=0.1, + opacity=1, + ), + DropDown( + "clifm", + "kitty --name=clifm -e clifm", + width=0.6, + height=0.6, + x=0.2, + y=0.1, + opacity=0.8, + ), + DropDown( + "btop", + "kitty --name=btop -e btop", + width=0.6, + height=0.6, + x=0.2, + y=0.1, + opacity=0.8, + ), + DropDown( + "volume", + "pavucontrol", + width=0.6, + height=0.6, + x=0.2, + y=0.1, + opacity=0.8, + ), + ], + ) + ) diff --git a/qtile/.config/qtile/core/hooks.py b/qtile/.config/qtile/core/hooks.py new file mode 100644 index 000000000..db69423aa --- /dev/null +++ b/qtile/.config/qtile/core/hooks.py @@ -0,0 +1,45 @@ +import asyncio +import subprocess + +from libqtile import hook + +from core.screens import screens + +bars = [screen.top for screen in screens] +margins = [sum(bar.margin) if bar else -1 for bar in bars] # type: ignore +configure = [ + "autostart", + "youtube_subs -d", + "autorandr --load qtile", + "setxkbmap -option caps:escape", +] + + +@hook.subscribe.startup +def startup(): + for bar, margin in zip(bars, margins): + if not margin: + bar.window.window.set_property( + name="WM_NAME", + value="QTILE_BAR", + type="STRING", + format=8, + ) + + +@hook.subscribe.startup_once +def start_once(): + for command in configure: + subprocess.Popen([command], shell=True) + + +@hook.subscribe.client_managed +def auto_focus(window): + window.group.cmd_toscreen() + + +@hook.subscribe.client_new +async def client_new(client): + await asyncio.sleep(0.5) + if client.name == "Spotify": + client.togroup("e") diff --git a/qtile/.config/qtile/core/keys.py b/qtile/.config/qtile/core/keys.py new file mode 100644 index 000000000..e6b3a4cdc --- /dev/null +++ b/qtile/.config/qtile/core/keys.py @@ -0,0 +1,149 @@ +from os import environ + +from libqtile.config import Key, KeyChord +from libqtile.lazy import lazy +from libqtile.utils import guess_terminal + +from extras import float_to_front +from utils.config import cfg + +if int(environ.get("QTILE_XEPHYR", 0)) > 0: + mod, alt = "mod1", "control" + restart = lazy.restart() +else: + mod, alt = "mod4", "mod1" + restart = lazy.reload_config() + +if not cfg.term: + cfg.term = guess_terminal() + +keys = [Key(*key) for key in [ # type: ignore + # switch between windows + ([mod], "h", lazy.layout.left()), + ([mod], "l", lazy.layout.right()), + ([mod], "j", lazy.layout.down()), + ([mod], "k", lazy.layout.up()), + + # move windows between columns + ([mod, "shift"], "h", lazy.layout.shuffle_left()), + ([mod, "shift"], "l", lazy.layout.shuffle_right()), + ([mod, "shift"], "j", lazy.layout.shuffle_down()), + ([mod, "shift"], "k", lazy.layout.shuffle_up()), + + # increase/decrease window size + ([mod], "i", lazy.layout.grow()), + ([mod], "m", lazy.layout.shrink()), + + # window management + ([mod, "shift"], "space", lazy.layout.flip()), + ([mod], "o", lazy.layout.maximize()), + ([mod], "n", lazy.layout.normalize()), + ([mod], "q", lazy.window.kill()), + ([mod, "shift"], "space", lazy.window.toggle_fullscreen()), + + # floating window management + ([mod], "space", lazy.window.toggle_floating()), + ([mod], "c", lazy.window.center()), + ([mod], "f", lazy.function(float_to_front)), + + # toggle between layouts + ([mod], "Tab", lazy.next_layout()), + + # qtile stuff + ([mod, "control"], "b", lazy.hide_show_bar()), + ([mod, "control"], "s", lazy.shutdown()), + ([mod, "shift"], "r", restart), + + # terminal + ([mod], "Return", lazy.spawn(cfg.term)), + ([mod, "shift"], "Return", lazy.spawn(cfg.files)), + + # app launcher + ([mod], "r", lazy.spawn("rofi -show window")), + ([mod], "m", lazy.spawn(cfg.menu)), + ([mod], "p", lazy.spawn(cfg.passwords)), + ([mod], "y", lazy.spawn(cfg.youtube)), + + # web browser + ([mod], "b", lazy.spawn(cfg.browser)), + + # code editor + ([mod], "c", lazy.spawn(cfg.editor)), + + # backlight + ([mod], "XF86AudioLowerVolume", lazy.spawn("brightnessctl set 5%-")), + ([mod], "XF86AudioRaiseVolume", lazy.spawn("brightnessctl set +5%")), + + # volume + ([], "XF86AudioMute", lazy.spawn("pamixer --toggle-mute")), + ([], "XF86AudioLowerVolume", lazy.spawn("pamixer --decrease 5")), + ([], "XF86AudioRaiseVolume", lazy.spawn("pamixer --increase 5")), + + # player + ([], "XF86AudioPlay", lazy.spawn("playerctl play-pause")), + ([], "XF86AudioPrev", lazy.spawn("playerctl previous")), + ([], "XF86AudioNext", lazy.spawn("playerctl next")), +]] # fmt: skip + +keys.extend( + [ + # Grow windows. If current window is on the edge of screen and direction + # will be to screen edge - window would shrink. + KeyChord( + [mod], + "r", + [ + Key([], "h", lazy.layout.grow_left(), desc="Grow window to the left"), + Key( + [], + "l", + lazy.layout.grow_right(), + desc="Grow window to the right", + ), + Key([], "j", lazy.layout.grow_down(), desc="Grow window down"), + Key([], "k", lazy.layout.grow_up(), desc="Grow window up"), + ], + mode=True, + name="Resize Windows", + ), + KeyChord( + [mod, "control"], + "g", + [ + Key([], "s", lazy.spawn("prime-run steam"), desc="Spawn steam"), + Key( + [], + "m", + lazy.spawn("prime-run minecraft"), + desc="Spawn minecraft", + ), + ], + mode=False, + name="Launch Game", + ), + KeyChord( + [mod], + "Print", + [ + Key([], "w", lazy.spawn("win-shot -w"), desc="Screen Shot Window"), + Key([], "s", lazy.spawn("win-shot -s"), desc="Screen Shot Selected"), + Key([], "f", lazy.spawn("win-shot -f"), desc="Screen Shot Full"), + ], + mode=False, + name="Take a Screenshot", + ), + ] +) + +keys.extend( + [ + Key( + ["control"], + "Return", + lazy.group["Hyper_L"].dropdown_toggle("term"), + ), + Key([alt], "c", lazy.group["Hyper_L"].dropdown_toggle("clifm")), + Key([alt], "b", lazy.group["Hyper_L"].dropdown_toggle("btop")), + Key([alt], "v", lazy.group["Hyper_L"].dropdown_toggle("volume")), + ] +) diff --git a/qtile/.config/qtile/core/layouts.py b/qtile/.config/qtile/core/layouts.py new file mode 100644 index 000000000..72d001bb2 --- /dev/null +++ b/qtile/.config/qtile/core/layouts.py @@ -0,0 +1,89 @@ +from libqtile import layout + +from utils.match import title, wm_class +from utils.palette import palette + +layout_theme = { + "border_focus": palette.colorScheme[10], + "border_normal": palette.currentColor, + "border_width": 2, + "margin": 10, + "single_border_width": 0, + "single_margin": 10, +} + +layouts = [ + layout.Tile( + **layout_theme, + add_after_last=True, + ), + layout.Columns( + **layout_theme, + ), + layout.Max( + **layout_theme, + ), + # Try more layouts by unleashing below layouts. + layout.Stack( + **layout_theme, + num_stacks=2, + ), + # layout.Bsp(**layout_theme), + layout.MonadThreeCol( + **layout_theme, + ratio=0.4, + new_client_position="after_current", + ), + layout.Matrix( + **layout_theme, + ), + layout.MonadTall( + **layout_theme, + change_ratio=0.02, + min_ratio=0.30, + max_ratio=0.70, + ), + layout.MonadWide( + **layout_theme, + ), + layout.RatioTile( + **layout_theme, + ), + # layout.TreeTab(**layout_theme,), + # layout.VerticVariables.ALTile(**layout_theme,), + layout.Zoomy( + **layout_theme, + ), +] + +floating_layout = layout.Floating( + border_focus=palette.colorScheme[4], + border_normal=palette.currentColor, + border_width=0, + fullscreen_border_width=0, + float_rules=[ + *layout.Floating.default_float_rules, + *wm_class( + "confirmreset", + "Display", + "floating", + "gnome-screenshot", + "gpicview", + "lxappearance", + "makebranch", + "maketag", + "pavucontrol", + "psterm", + "ssh-askpass", + "steam", + "thunar", + "Xephyr", + "xfce4-about", + ), + *title( + "branchdialog", + "minecraft-launcher", + "pinentry", + ), + ], +) diff --git a/qtile/.config/qtile/core/mouse.py b/qtile/.config/qtile/core/mouse.py new file mode 100644 index 000000000..f16ec9c99 --- /dev/null +++ b/qtile/.config/qtile/core/mouse.py @@ -0,0 +1,29 @@ +from libqtile.config import Click, Drag +from libqtile.lazy import lazy + +from core.keys import mod + +mouse = [ + # left click + Drag( + [mod], + "Button1", + lazy.window.set_position_floating(), + start=lazy.window.get_position(), + ), + + # right click + Drag( + [mod], + "Button3", + lazy.window.set_size_floating(), + start=lazy.window.get_size(), + ), + + # scroll wheel + Click( + [mod], + "Button2", + lazy.window.bring_to_front(), + ), +] # fmt: skip diff --git a/qtile/.config/qtile/core/screens.py b/qtile/.config/qtile/core/screens.py new file mode 100644 index 000000000..8b3803b9a --- /dev/null +++ b/qtile/.config/qtile/core/screens.py @@ -0,0 +1,17 @@ +from libqtile.config import Screen + +from core.bar import Bar +from utils.config import cfg + +screens = [ + Screen( + wallpaper=cfg.wallpaper, + wallpaper_mode="fill", + top=Bar(cfg.bar).create(), + ), + Screen( + wallpaper=cfg.wallpaper, + wallpaper_mode="fill", + top=Bar(cfg.bar2).create(), + ), +] diff --git a/qtile/.config/qtile/ext/multiColorTag.py b/qtile/.config/qtile/ext/multiColorTag.py deleted file mode 100644 index 5fa5e19af..000000000 --- a/qtile/.config/qtile/ext/multiColorTag.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (c) 2023 The-Repo-Club -# -# 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. - -from libqtile import widget -from libqtile.confreader import ConfigError - - -class MultiColorTag(widget.GroupBox): - def __init__(self, **config): - super().__init__(**config) - self.tag_colors = config.get("tag_colors", []) - self.this_current_screen_border = config.get("this_current_screen_border", []) - - if not isinstance(self.tag_colors, list): - raise ConfigError("MultiColorTag: tag_colors must be a list") - if not isinstance(self.this_current_screen_border, list): - raise ConfigError( - "MultiColorTag: this_current_screen_border must be a list" - ) - - def draw(self): - self.drawer.clear(self.background or self.bar.background) - - offset = self.margin_x - num_tag_colors = len(self.tag_colors) - num_this_current_screen_border = len(self.this_current_screen_border) - - for i, g in enumerate(self.groups): - effective_tag_colors_index = i % num_tag_colors - effective_this_current_screen_border_index = ( - i % num_this_current_screen_border - ) - - bw = self.box_width([g]) - - if self.group_has_urgent(g): - text_color = self.urgent_text - elif g.windows: - text_color = self.active - else: - text_color = self.inactive - - if effective_tag_colors_index < len(self.tag_colors): - text_color = self.tag_colors[effective_tag_colors_index] - - if g.screen: - if self.block_highlight_text_color: - text_color = self.block_highlight_text_color - if self.bar.screen.group.name == g.name: - if self.qtile.current_screen == self.bar.screen: - border = self.this_current_screen_border[ - effective_this_current_screen_border_index - ] - else: - border = self.this_screen_border - else: - if self.qtile.current_screen == g.screen: - border = self.other_current_screen_border - else: - border = self.other_screen_border - elif self.group_has_urgent(g): - border = self.urgent_border - else: - border = None - - self.drawbox( - offset, - g.label, - border, - text_color, - highlight_color=self.highlight_color, - width=bw, - rounded=self.rounded, - block=False, - line=True, - highlighted=False, - ) - offset += bw + self.spacing - self.drawer.draw(offsetx=self.offset, offsety=self.offsety, width=self.width) diff --git a/qtile/.config/qtile/extras/__init__.py b/qtile/.config/qtile/extras/__init__.py new file mode 100644 index 000000000..79aeaec27 --- /dev/null +++ b/qtile/.config/qtile/extras/__init__.py @@ -0,0 +1,24 @@ +from qtile_extras import widget # type: ignore +from qtile_extras.widget import modify # type: ignore +from qtile_extras.widget.decorations import ( # type: ignore + BorderDecoration, + PowerLineDecoration, + RectDecoration, +) + +from extras.clock import Clock +from extras.groupbox import GroupBox +from extras.misc import float_to_front +from extras.textbox import TextBox + +__all__ = [ + "BorderDecoration", + "Clock", + "float_to_front", + "GroupBox", + "modify", + "PowerLineDecoration", + "RectDecoration", + "TextBox", + "widget", +] diff --git a/qtile/.config/qtile/extras/clock.py b/qtile/.config/qtile/extras/clock.py new file mode 100644 index 000000000..3bb183cda --- /dev/null +++ b/qtile/.config/qtile/extras/clock.py @@ -0,0 +1,26 @@ +from libqtile.widget import clock + + +class Clock(clock.Clock): + defaults = [ + ( + "long_format", + "%A %d %B %Y | %H:%M", + "Format to show when widget is clicked.", + ), + ] + + def __init__(self, **config): + super().__init__(**config) + self.add_defaults(Clock.defaults) + self.short_format = self.format + self.toggled = False + self.add_callbacks({"Button1": self.toggle}) + + def toggle(self): + if self.toggled: + self.format = self.short_format + else: + self.format = self.long_format + self.toggled = not self.toggled + self.update(self.poll()) diff --git a/qtile/.config/qtile/extras/drawer.py b/qtile/.config/qtile/extras/drawer.py new file mode 100644 index 000000000..a81e85b9a --- /dev/null +++ b/qtile/.config/qtile/extras/drawer.py @@ -0,0 +1,53 @@ +from libqtile.backend.base import drawer + + +def framed(self, border_width, border_color, pad_x, pad_y, highlight_color=None): + return TextFrame( + self, border_width, border_color, pad_x, pad_y, highlight_color=highlight_color + ) + + +class TextFrame(drawer.TextFrame): + def __init__( + self, layout, border_width, border_color, pad_x, pad_y, highlight_color=None + ): + super().__init__( + layout, border_width, border_color, pad_x, pad_y, highlight_color + ) + + def draw( + self, x, y, rounded=True, fill=False, line=False, highlight=False, invert=False + ): + self.drawer.set_source_rgb(self.border_color) + opts = [ + x, + y, + self.layout.width + self.pad_left + self.pad_right, + self.layout.height + self.pad_top + self.pad_bottom, + self.border_width, + ] + if line: + if highlight: + self.drawer.set_source_rgb(self.highlight_color) + self.drawer.fillrect(*opts) + self.drawer.set_source_rgb(self.border_color) + + opts[1] = 0 if invert else self.height - self.border_width + opts[3] = self.border_width + + self.drawer.fillrect(*opts) + elif fill: + if rounded: + self.drawer.rounded_fillrect(*opts) + else: + self.drawer.fillrect(*opts) + else: + if rounded: + self.drawer.rounded_rectangle(*opts) + else: + self.drawer.rectangle(*opts) + self.drawer.ctx.stroke() + self.layout.draw(x + self.pad_left, y + self.pad_top) + + def draw_line(self, x, y, highlighted, inverted): + self.draw(x, y, line=True, highlight=highlighted, invert=inverted) diff --git a/qtile/.config/qtile/extras/groupbox.py b/qtile/.config/qtile/extras/groupbox.py new file mode 100644 index 000000000..73c954eb0 --- /dev/null +++ b/qtile/.config/qtile/extras/groupbox.py @@ -0,0 +1,191 @@ +from libqtile.widget import base, groupbox + +from extras.drawer import framed + + +class GroupBox(groupbox.GroupBox): + defaults = [ + ( + "invert", + False, + "Invert line position when 'line' highlight method isn't highlighted.", + ), + ( + "rainbow", + False, + "If set to True, 'colors' will be used instead of '*_screen_border'.", + ), + ( + "colors", + False, + "Receive a list of strings." + "Allows each label to have its own independent/unique color when selected, overriding the 'active' parameter.", + ), + ( + "icons", + { + "active": "", + "empty": "○", + "occupied": "◉", + }, + "Will be used in the 'icon' highlight method.", + ), + ] + + def __init__(self, **config): + super().__init__(**config) + self.add_defaults(GroupBox.defaults) + + def _configure(self, qtile, bar): + super()._configure(qtile, bar) + self.layout.framed = framed.__get__(self.layout) + + def drawbox( + self, + offset, + text, + bordercolor, + textcolor, + highlight_color=None, + width=None, + rounded=False, + block=False, + line=False, + highlighted=False, + inverted=False, + ): + self.layout.text = self.fmt.format(text) + self.layout.font_family = self.font + self.layout.font_size = self.fontsize + self.layout.colour = textcolor + if width is not None: + self.layout.width = width + if line: + pad_y = [ + (self.bar.height - self.layout.height - self.borderwidth) / 2, + (self.bar.height - self.layout.height + self.borderwidth) / 2, + ] + if highlighted: + inverted = False + else: + pad_y = self.padding_y + + if bordercolor is None: + # border colour is set to None when we don't want to draw a border at all + # Rather than dealing with alpha blending issues, we just set border width + # to 0. + border_width = 0 + framecolor = self.background or self.bar.background + else: + border_width = self.borderwidth + framecolor = bordercolor + + framed = self.layout.framed(border_width, framecolor, 0, pad_y, highlight_color) + y = self.margin_y + if self.center_aligned: + for t in base.MarginMixin.defaults: + if t[0] == "margin": + y += (self.bar.height - framed.height) / 2 - t[1] + break + if block and bordercolor is not None: + framed.draw_fill(offset, y, rounded) + elif line: + framed.draw_line(offset, y, highlighted, inverted) + else: + framed.draw(offset, y, rounded) + + def draw(self): + self.drawer.clear(self.background or self.bar.background) + + def color(index: int) -> str: + try: + return self.colors[index] + except IndexError: + return "FFFFFF" + + offset = self.margin_x + for i, g in enumerate(self.groups): + is_block = self.highlight_method == "block" + is_line = self.highlight_method == "line" + is_icon = self.highlight_method == "icon" + to_highlight = False + + bw = self.box_width([g]) + + if self.group_has_urgent(g) and self.urgent_alert_method == "text": + text_color = self.urgent_text + elif g.windows: + text_color = color(i) if self.colors else self.active + icon = self.icons["occupied"] + else: + text_color = self.inactive + icon = self.icons["empty"] + + if g.screen: + if self.highlight_method == "text": + border = None + text_color = self.this_current_screen_border + elif is_icon: + icon = self.icons["active"] + border = None + text_color = ( + color(i) if self.colors else self.this_current_screen_border + ) + else: + if self.block_highlight_text_color: + text_color = self.block_highlight_text_color + + if self.bar.screen.group.name == g.name: + if self.qtile.current_screen == self.bar.screen: + if self.rainbow and self.colors: + border = color(i) if g.windows else self.inactive + else: + border = self.this_current_screen_border + to_highlight = True + else: + if self.rainbow and self.colors: + border = color(i) if g.windows else self.inactive + else: + border = self.this_screen_border + to_highlight = True + + else: + if self.qtile.current_screen == g.screen: + if self.rainbow and self.colors: + border = color(i) if g.windows else self.inactive + else: + border = self.other_current_screen_border + else: + if self.rainbow and self.colors: + border = color(i) if g.windows else self.inactive + else: + border = self.other_screen_border + + elif self.group_has_urgent(g) and self.urgent_alert_method in ( + "border", + "block", + "line", + ): + border = self.urgent_border + if self.urgent_alert_method == "block": + is_block = True + elif self.urgent_alert_method == "line": + is_line = True + else: + border = None + + self.drawbox( + offset, + icon if is_icon else g.label, + border, + text_color, + highlight_color=self.highlight_color, + width=bw, + rounded=self.rounded, + block=is_block, + line=is_line, + highlighted=to_highlight, + inverted=self.invert, + ) + offset += bw + self.spacing + self.drawer.draw(offsetx=self.offset, offsety=self.offsety, width=self.width) diff --git a/qtile/.config/qtile/extras/misc.py b/qtile/.config/qtile/extras/misc.py new file mode 100644 index 000000000..5b708a42a --- /dev/null +++ b/qtile/.config/qtile/extras/misc.py @@ -0,0 +1,7 @@ +from libqtile.core.manager import Qtile + + +def float_to_front(qtile: Qtile) -> None: + for window in qtile.current_group.windows: + if window.floating: + window.bring_to_front() diff --git a/qtile/.config/qtile/extras/textbox.py b/qtile/.config/qtile/extras/textbox.py new file mode 100644 index 000000000..c26b449a1 --- /dev/null +++ b/qtile/.config/qtile/extras/textbox.py @@ -0,0 +1,94 @@ +import math + +from libqtile import bar +from libqtile.widget import textbox + + +class TextBox(textbox.TextBox): + def __init__( + self, + offset=0, + text=" ", + width=bar.CALCULATED, + x=0, + y=0, + **config, + ): + super().__init__(text, width, **config) + self.add_offset = offset + self.add_x = x + self.add_y = y + + def calculate_length(self): + if self.text: + if self.bar.horizontal: + return ( + min(self.layout.width, self.bar.width) + + self.actual_padding * 2 + + self.add_offset + ) + else: + return ( + min(self.layout.width, self.bar.height) + + self.actual_padding * 2 + + self.add_offset + ) + else: + return 0 + + def draw(self): + if not self.can_draw(): + return + self.drawer.clear(self.background or self.bar.background) + + # size = self.bar.height if self.bar.horizontal else self.bar.width + self.drawer.ctx.save() + + if not self.bar.horizontal: + # Left bar reads bottom to top + if self.bar.screen.left is self.bar: + self.drawer.ctx.rotate(-90 * math.pi / 180.0) + self.drawer.ctx.translate(-self.length, 0) + + # Right bar is top to bottom + else: + self.drawer.ctx.translate(self.bar.width, 0) + self.drawer.ctx.rotate(90 * math.pi / 180.0) + + # If we're scrolling, we clip the context to the scroll width less the padding + # Move the text layout position (and we only see the clipped portion) + if self._should_scroll: + self.drawer.ctx.rectangle( + self.actual_padding, + 0, + self._scroll_width - 2 * self.actual_padding, + self.bar.size, + ) + self.drawer.ctx.clip() + + size = self.bar.height if self.bar.horizontal else self.bar.width + + self.layout.draw( + (self.actual_padding or 0) - self._scroll_offset + self.add_x, + int(size / 2.0 - self.layout.height / 2.0) + 1 + self.add_y, + ) + self.drawer.ctx.restore() + + self.drawer.draw( + offsetx=self.offsetx, + offsety=self.offsety, + width=self.width, + height=self.height, + ) + + # We only want to scroll if: + # - User has asked us to scroll and the scroll width is smaller than the layout (should_scroll=True) + # - We are still scrolling (is_scrolling=True) + # - We haven't already queued the next scroll (scroll_queued=False) + if self._should_scroll and self._is_scrolling and not self._scroll_queued: + self._scroll_queued = True + if self._scroll_offset == 0: + interval = self.scroll_delay + else: + interval = self.scroll_interval + self._scroll_timer = self.timeout_add(interval, self.do_scroll) diff --git a/qtile/.config/qtile/groups.py b/qtile/.config/qtile/groups.py deleted file mode 100644 index b54b154c9..000000000 --- a/qtile/.config/qtile/groups.py +++ /dev/null @@ -1,128 +0,0 @@ -import re -from libqtile.config import Group, Match - - -class Groups(object): - groups = [ - # first group that hold the terminals - Group( - label="一", - init=True, - persist=True, - exclusive=False, - matches=[ - Match(wm_class=re.compile("^Alacritty.*|^Kitty.*", re.IGNORECASE)) - ], - layout="monadthreecol", - position=1, - screen_affinity=1, - name="1", - ), - Group( - label="二", - init=True, - persist=True, - exclusive=False, - matches=[Match(wm_class=re.compile("^Code.*|^Jetbrains.*", re.IGNORECASE))], - position=2, - screen_affinity=1, - name="2", - ), - Group( - label="三", - init=True, - persist=True, - exclusive=False, - matches=[Match(wm_class=re.compile("^Nemo.*", re.IGNORECASE))], - position=3, - screen_affinity=1, - name="3", - ), - Group( - label="四", - init=True, - persist=True, - exclusive=False, - matches=[Match(wm_class=re.compile("^Aseprite.*|^Krita.*", re.IGNORECASE))], - position=4, - screen_affinity=1, - name="4", - ), - Group( - label="五", - init=True, - persist=True, - exclusive=False, - matches=[Match(wm_class=re.compile("^CmusImage.*", re.IGNORECASE))], - position=5, - screen_affinity=1, - name="5", - ), - Group( - label="六", - init=True, - persist=True, - exclusive=False, - matches=[ - Match( - wm_class=re.compile("^Firefox.*|^Brave.*", re.IGNORECASE), - role=["browser"], - ) - ], - position=6, - screen_affinity=2, - name="6", - ), - Group( - label="七", - init=True, - persist=True, - exclusive=False, - matches=[ - Match(wm_class=re.compile("^Mail.*|^Thunderbird.*", re.IGNORECASE)) - ], - position=7, - screen_affinity=2, - name="7", - ), - Group( - label="八", - init=True, - persist=True, - exclusive=False, - matches=[ - Match( - wm_class=re.compile("^Steam.*|^Minecraft.*|^0ad.*", re.IGNORECASE) - ) - ], - position=8, - screen_affinity=2, - name="8", - ), - Group( - label="九", - init=True, - persist=True, - exclusive=False, - matches=[Match(wm_class=re.compile("^Discord.*", re.IGNORECASE))], - position=9, - screen_affinity=2, - name="9", - ), - Group( - label="零", - init=True, - persist=True, - exclusive=False, - matches=[ - Match( - wm_class=re.compile( - "^Software Management.*|^Virt.*|^Btop.*", re.IGNORECASE - ) - ) - ], - position=10, - screen_affinity=2, - name="0", - ), - ] diff --git a/qtile/.config/qtile/keys.py b/qtile/.config/qtile/keys.py deleted file mode 100644 index 2d667cde7..000000000 --- a/qtile/.config/qtile/keys.py +++ /dev/null @@ -1,164 +0,0 @@ -from variables import Commands, Variables - -from libqtile.lazy import lazy - -from libqtile.config import Key, KeyChord - - -class Keys(object): - keys = [ - # qtile commands - Key( - [Variables.MOD, Variables.SHIFT], - "r", - lazy.reload_config(), - desc="Reload the config", - ), - Key([Variables.MOD, Variables.CTRL], "r", lazy.restart(), desc="Restart qtile"), - # Switch between windows - Key([Variables.MOD], "h", lazy.layout.left(), desc="Move focus to left"), - Key([Variables.MOD], "l", lazy.layout.right(), desc="Move focus to right"), - Key([Variables.MOD], "j", lazy.layout.down(), desc="Move focus down"), - Key([Variables.MOD], "k", lazy.layout.up(), desc="Move focus up"), - # reset all windows - Key( - [Variables.MOD], "n", lazy.layout.normalize(), desc="Reset all window sizes" - ), - # Toggle between different layouts as defined below - Key([Variables.MOD], "Tab", lazy.next_layout(), desc="Toggle between layouts"), - Key( - [Variables.MOD], "t", lazy.window.toggle_floating(), desc="Toggle floating" - ), - Key([Variables.MOD], "q", lazy.window.kill(), desc="Kill focused window"), - # Custom keybinds - Key( - [Variables.MOD], - "Return", - lazy.spawn(Commands.terminal), - desc="Launch terminal", - ), - Key([Variables.MOD], "m", lazy.spawn(Commands.menu), desc="Launch menu"), - Key( - [Variables.MOD], - "p", - lazy.spawn(Commands.passmenu), - desc="Launch password menu", - ), - Key( - [Variables.MOD, Variables.CTRL], - "f", - lazy.spawn(Commands.browser), - desc="Launch browser", - ), - Key( - [Variables.MOD, Variables.CTRL], - "c", - lazy.spawn(Commands.editor), - desc="Launch editor", - ), - Key( - [Variables.MOD, Variables.SHIFT], - "e", - lazy.spawn(Commands.powermenu), - desc="Launch power menu", - ), - Key( - [Variables.MOD, Variables.SHIFT], - "Return", - lazy.spawn(Commands.files), - desc="Launch files", - ), - Key([Variables.MOD], "b", lazy.spawn(Commands.btop), desc="Launch btop"), - # Audio Settings - Key([], "XF86AudioMute", lazy.spawn("amixer set Master toggle")), - Key( - [], - "XF86AudioLowerVolume", - lazy.spawn("amixer set Master '5%-' unmute"), - ), - Key( - [], - "XF86AudioRaiseVolume", - lazy.spawn("amixer set Master '5%+' unmute"), - ), - # https://github.com/acrisci/playerctl/ - Key([], "XF86AudioPlay", lazy.spawn("playerctl play-pause")), - Key([], "XF86AudioNext", lazy.spawn("playerctl next")), - Key([], "XF86AudioPrev", lazy.spawn("playerctl previous")), - Key([], "XF86AudioStop", lazy.spawn("playerctl stop")), - # xBacklight - Key([], "XF86MonBrightnessUp", lazy.spawn("brightnessctl set 5%+")), - Key([], "XF86MonBrightnessDown", lazy.spawn("brightnessctl set 5%-")), - ] - - ################ - ## Key Chords ## - ################ - - keys.extend( - [ - # Grow windows. If current window is on the edge of screen and direction - # will be to screen edge - window would shrink. - KeyChord( - [Variables.MOD], - "r", - [ - Key( - [], "h", lazy.layout.grow_left(), desc="Grow window to the left" - ), - Key( - [], - "l", - lazy.layout.grow_right(), - desc="Grow window to the right", - ), - Key([], "j", lazy.layout.grow_down(), desc="Grow window down"), - Key([], "k", lazy.layout.grow_up(), desc="Grow window up"), - ], - mode=True, - name="Resize Windows", - ), - KeyChord( - [Variables.MOD, Variables.CTRL], - "g", - [ - Key([], "s", lazy.spawn("prime-run steam"), desc="Spawn steam"), - Key( - [], - "m", - lazy.spawn("prime-run minecraft"), - desc="Spawn minecraft", - ), - ], - mode=False, - name="Launch Game", - ), - KeyChord( - [Variables.MOD], - "Print", - [ - Key([], "w", lazy.spawn("win-shot -w"), desc="Screen Shot Window"), - Key( - [], "s", lazy.spawn("win-shot -s"), desc="Screen Shot Selected" - ), - Key([], "f", lazy.spawn("win-shot -f"), desc="Screen Shot Full"), - ], - mode=False, - name="Take a Screenshot", - ), - ] - ) - - # Scratchpad keybindings - keys.extend( - [ - Key( - [Variables.CTRL], - "Return", - lazy.group["Hyper_L"].dropdown_toggle("term"), - ), - Key([Variables.ALT], "c", lazy.group["Hyper_L"].dropdown_toggle("clifm")), - Key([Variables.ALT], "b", lazy.group["Hyper_L"].dropdown_toggle("btop")), - Key([Variables.ALT], "v", lazy.group["Hyper_L"].dropdown_toggle("volume")), - ] - ) diff --git a/qtile/.config/qtile/scripts/qtile-cheat b/qtile/.config/qtile/scripts/qtile-cheat deleted file mode 100755 index 316ce27f1..000000000 --- a/qtile/.config/qtile/scripts/qtile-cheat +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python3 - -import json -from os.path import expanduser - -import gi - -gi.require_version('Gtk', '3.0') -gi.require_version('Gdk', '3.0') -from gi.repository import Gdk, Gio, GLib, Gtk - -configFile = expanduser("~/.config/qtile/keybinds.json") -with open(f'{configFile}', mode='r') as inputfile: - data = json.load(inputfile) - - -def mode_label(mode): - 'Create a GTK label for mode' '' - label = Gtk.Label() - label.set_text(str(mode)) - return label - - -class WMCheatWindow(Gtk.ApplicationWindow): - - def __init__(self, **kwargs): - super().__init__(**kwargs) - self._tab_lookup = dict() - self.set_default_size(-1, 740) - self.set_border_width(3) - - accel_group = Gtk.AccelGroup() - accel_group.connect(Gdk.keyval_from_name('Left'), Gdk.ModifierType.SUPER_MASK, 0, self.prev_mode) - accel_group.connect(Gdk.keyval_from_name('Right'), Gdk.ModifierType.SUPER_MASK, 0, self.next_mode) - accel_group.connect(Gdk.keyval_from_name('Escape'), 0, 0, self._quit) - self.add_accel_group(accel_group) - - self.set_type_hint(Gdk.WindowTypeHint.DIALOG) - - self.notebook = Gtk.Notebook(scrollable=True) - for (category, array) in data.items(): - self.category = Gtk.Box() - self.category.set_border_width(10) - - store = Gtk.ListStore(str, str, str, str) - - for description in array: - keybind = array[description]['keybind'] - command = array[description]['command'] - store.append([category, str(description), str(keybind), str(command)]) - - tree = Gtk.TreeView(model=store, headers_visible=True, enable_search=False, search_column=1) - tree.get_selection().set_mode(Gtk.SelectionMode.BROWSE) - tree.set_cursor(Gtk.TreePath(0), None, False) - - description_column = Gtk.TreeViewColumn("Description", Gtk.CellRendererText(), text=1) - description_column.set_min_width(300) - description_column.set_max_width(500) - tree.append_column(description_column) - - keybind_column = Gtk.TreeViewColumn("Keybind", Gtk.CellRendererText(), text=2) - keybind_column.set_min_width(300) - keybind_column.set_max_width(500) - tree.append_column(keybind_column) - - # command_column = Gtk.TreeViewColumn("Command", - # Gtk.CellRendererText(), - # text=3) - # command_column.set_min_width(300) - # command_column.set_max_width(500) - # tree.append_column(command_column) - - scrolled = Gtk.ScrolledWindow() - scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) - scrolled.add(tree) - - self._tab_lookup[category] = self.notebook.get_n_pages() - self.notebook.append_page(scrolled, mode_label(category)) - - self.add(self.notebook) - self.current_page().grab_focus() - - style = Gtk.CssProvider() - style.load_from_data(WMCheat.CSS) - Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), style, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) - - def current_page(self): - return self.notebook.get_nth_page(self.notebook.get_current_page()) - - def _init_mode(self, mode): - store = Gtk.ListStore(str, str, str) - - def focus_mode(self, mode): - 'Focus on a mode by its name' - idx = self._tab_lookup.get(mode, 0) - self.notebook.set_current_page(idx) - - def next_mode(self, *args): - self.notebook.next_page() - - def prev_mode(self, *args): - self.notebook.prev_page() - - def _quit(self, *args): - self.close() - - -class WMCheat(Gtk.Application): - CSS = b""" - * { - font-size: 16px; - } - @binding-set i3-binds { - bind "slash" { "start-interactive-search" () }; - bind "j" { "move-cursor" (display-lines, 1) }; - bind "k" { "move-cursor" (display-lines, -1) }; - } - GtkTreeView, treeview { - -gtk-key-bindings: i3-binds; - } - """ - - def __init__(self): - super().__init__(application_id="com.github.The-Repo-Club.keybinds", flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) - self.add_main_option('mode', ord('m'), 0, GLib.OptionArg.STRING, "Mode tab to open", "MODE") - self._window = None - - def do_command_line(self, cl): - if not self._window: - self._window = WMCheatWindow(application=self, title="Window Manager Cheatsheet") - self._window.show_all() - - mode = cl.get_options_dict().lookup_value('mode') - if mode: - mode = mode.get_string() - self._window.focus_mode(mode) - self._window.present() - return 0 - - def do_startup(self): - Gtk.Application.do_startup(self) - - -if __name__ == '__main__': - import sys - import signal - app = WMCheat() - # so ctrl+c still works - GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, app.quit) - app.run(sys.argv) diff --git a/qtile/.config/qtile/scripts/xcompmgr-toggle.sh b/qtile/.config/qtile/scripts/xcompmgr-toggle.sh old mode 100755 new mode 100644 diff --git a/qtile/.config/qtile/scripts/xcompmgr.sh b/qtile/.config/qtile/scripts/xcompmgr.sh old mode 100755 new mode 100644 diff --git a/qtile/.config/qtile/utils/__init__.py b/qtile/.config/qtile/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/qtile/.config/qtile/utils/config.py b/qtile/.config/qtile/utils/config.py new file mode 100644 index 000000000..3a13f12fe --- /dev/null +++ b/qtile/.config/qtile/utils/config.py @@ -0,0 +1,44 @@ +import json +from dataclasses import asdict, dataclass +from os import getcwd +from os.path import exists, expanduser, join + + +@dataclass +class Config: + bar: str = "shapes" + bar2: str = "" + browser: str = "" + term: str = "" + term2: str = "" + editor: str = "" + files: str = "" + menu: str = "" + power: str = "" + passwords: str = "" + youtube: str = "" + wallpaper: str = "" + + @staticmethod + def path() -> str: + xdg = expanduser("~/.config/qtile") + return xdg if exists(xdg) else getcwd() + + @classmethod + def load(cls) -> "Config": + file = join(cls.path(), "cfg.json") + if not exists(file): + cls.generate(file) + return cls() + with open(file, "r") as f: + content = json.load(f) + return cls(**content) + + @classmethod + def generate(cls, file: str) -> None: + with open(file, "w") as f: + content = asdict(cls()) + f.write(json.dumps(content, indent=2)) + + +cfg = Config.load() diff --git a/qtile/.config/qtile/utils/match.py b/qtile/.config/qtile/utils/match.py new file mode 100644 index 000000000..574ab4760 --- /dev/null +++ b/qtile/.config/qtile/utils/match.py @@ -0,0 +1,18 @@ +from libqtile.config import Match + + +class Matches: + def __init__(self, property: str, values: tuple) -> None: + self.property = property + self.values = values + + def generate(self) -> list[Match]: + return [Match(**{self.property: i}) for i in self.values] + + +def wm_class(*values: str): + return Matches("wm_class", values).generate() + + +def title(*values: str): + return Matches("title", values).generate() diff --git a/qtile/.config/qtile/utils/palette.py b/qtile/.config/qtile/utils/palette.py new file mode 100644 index 000000000..32ee0d71d --- /dev/null +++ b/qtile/.config/qtile/utils/palette.py @@ -0,0 +1,46 @@ +from dataclasses import dataclass + + +@dataclass(frozen=True) +class MinimalMistakes: + colorScheme = [ + "283036", # 0 + "ff5959", # 1 + "59ff59", # 2 + "ffff59", # 3 + "9059ff", # 4 + "ff59f9", # 5 + "59fff9", # 6 + "e5e9f0", # 7 + "43515e", # 8 + "ffa6a6", # 9 + "a6ffa6", # 10 + "ffffa6", # 11 + "c5a6ff", # 12 + "ffa6fc", # 13 + "a6fffc", # 14 + "e5e9f0", # 15 + "e5e9f0", # foregroundColor + "283036", # backgroundColor + "434c5e", # selectionColor + ] + + widgetColors = [ + "ff5959", # 1 + "59ff59", # 2 + "ffff59", # 3 + "9059ff", # 4 + "ff59f9", # 5 + "59fff9", # 6 + "e5e9f0", # 7 + "43515e", # 8 + "ffa6a6", # 9 + "a6ffa6", # 10 + ] + + foregroundColor = colorScheme[16] + backgroundColor = colorScheme[17] + currentColor = colorScheme[18] + + +palette = MinimalMistakes() diff --git a/qtile/.config/qtile/variables.py b/qtile/.config/qtile/variables.py deleted file mode 100644 index 2675318ec..000000000 --- a/qtile/.config/qtile/variables.py +++ /dev/null @@ -1,25 +0,0 @@ -class Variables(object): - ALT = "mod1" - MOD = "mod4" - CTRL = "control" - SHIFT = "shift" - - -class Commands(object): - editor = "code" - menu = "menu" - browser = "firefox" - terminal = "alacritty" - btop = "kitty --class=btop -e btop" - powermenu = "rofi -show powermenu -config ~/.config/rofi/powermenu.rasi" - vbox = "virt-manager" - files = "nemo" - mail = "thunderbird" - passmenu = "passmenu" - - autostart = ["autostart"] - configure = [ - "youtube_subs -d", - "autorandr --load qtile", - "setxkbmap -option caps:escape", - ] diff --git a/qtile/.config/qtile/widgets.py b/qtile/.config/qtile/widgets.py deleted file mode 100644 index a963e27b7..000000000 --- a/qtile/.config/qtile/widgets.py +++ /dev/null @@ -1,234 +0,0 @@ -from libqtile import widget -from libqtile.lazy import lazy -from os.path import expanduser -import subprocess - -from ext.multiColorTag import MultiColorTag - -from colors import colorScheme, widgetColors, foregroundColor, backgroundColor - - -class Widgets(object): - sep = widget.Sep( - linewidth=0, - padding=10, - foreground=colorScheme[15], - background=colorScheme[0], - ) - - space = widget.Spacer() - - launcher = widget.LaunchBar( - text_only=True, - fontsize=18, - foreground=colorScheme[0], - background=colorScheme[2], - progs=[ - (" 󰣇 ", "menu"), - ], - ) - - power = widget.LaunchBar( - text_only=True, - foreground=colorScheme[0], - background=colorScheme[1], - progs=[ - (" ⏻ ", "rofi -show powermenu -config ~/.config/rofi/powermenu.rasi"), - ], - ) - - groupBox1 = MultiColorTag( - margin_y=4, - margin_x=4, - padding_y=6, - padding_x=6, - borderwidth=2, - disable_drag=True, - active=colorScheme[6], - inactive=foregroundColor, - hide_unused=True, - rounded=False, - highlight_method="line", - highlight_color=backgroundColor, - tag_colors=widgetColors, - this_current_screen_border=widgetColors, - this_screen_border=colorScheme[1], - other_screen_border=colorScheme[6], - other_current_screen_border=colorScheme[6], - urgent_alert_method="line", - urgent_border=colorScheme[9], - urgent_text=colorScheme[1], - foreground=foregroundColor, - background=backgroundColor, - use_mouse_wheel=True, - ) - - groupBox2 = MultiColorTag( - margin_y=4, - margin_x=4, - padding_y=6, - padding_x=6, - borderwidth=2, - disable_drag=True, - active=colorScheme[6], - inactive=foregroundColor, - hide_unused=True, - rounded=False, - highlight_method="line", - highlight_color=backgroundColor, - tag_colors=widgetColors, - this_current_screen_border=widgetColors, - this_screen_border=colorScheme[1], - other_screen_border=colorScheme[6], - other_current_screen_border=colorScheme[6], - urgent_alert_method="line", - urgent_border=colorScheme[9], - urgent_text=colorScheme[1], - foreground=foregroundColor, - background=backgroundColor, - use_mouse_wheel=True, - ) - - windowName = widget.WindowName( - foreground=backgroundColor, - background=colorScheme[10], - max_chars=42, - padding=10, - ) - - volume = widget.Volume( - fmt=": {}", - foreground=backgroundColor, - background=colorScheme[2], - padding=10, - ) - - backlight = widget.Backlight( - fmt="󰞏 {}", - foreground=backgroundColor, - background=colorScheme[4], - padding=10, - backlight_name="intel_backlight", - ) - - net = widget.Net( - fmt="󰛳 {}", - format="{down} ↓↑ {up}", - foreground=backgroundColor, - background=colorScheme[5], - padding=10, - interface="wlan0", - ) - - date = widget.Clock( - fmt=" {}", - foreground=backgroundColor, - background=colorScheme[6], - format="%d %B %Y", - padding=10, - ) - - time = widget.Clock( - fmt=" {}", - foreground=backgroundColor, - background=colorScheme[6], - format="%I:%M %p", - padding=10, - ) - - tray = widget.Systray( - fmt="{}", - padding=7, - ) - - currentLayout = widget.CurrentLayoutIcon( - fmt="{}", - background=colorScheme[0], - scale=0.7, - padding=5, - ) - - chords = widget.Chord( - fmt=" {} ", - chords_colors={ - "Resize Windows": (colorScheme[1], backgroundColor), - "Launch Game": (colorScheme[2], backgroundColor), - "Take a Screenshot": (colorScheme[3], backgroundColor), - }, - name_transform=lambda name: name.upper(), - ) - - weather = widget.OpenWeather( - fmt=" 󰖕 {}", - foreground=backgroundColor, - background=colorScheme[9], - location="Darlington,UK", - format="{location_city}: {main_temp}°{units_temperature} ", - ) - - updates = widget.CheckUpdates( - fmt="{}", - colour_have_updates=colorScheme[2], - colour_no_updates=colorScheme[1], - padding=10, - distro="Arch_checkupdates", - no_update_string="Fully Updated!", - mouse_callbacks={ - "Button1": lazy.spawn("pkgbrowser"), - }, - ) - - xcompmgr = widget.GenPollText( - fmt="{}", - foreground=backgroundColor, - background=colorScheme[11], - func=lambda: subprocess.check_output( - expanduser("~/.config/qtile/scripts/xcompmgr.sh") - ).decode("utf-8"), - mouse_callbacks={ - "Button1": lambda: subprocess.run( - expanduser("~/.config/qtile/scripts/xcompmgr-toggle.sh") - ), - }, - update_interval=1, - padding=10, - ) - - github = widget.WidgetBox( - foreground=backgroundColor, - background=colorScheme[12], - widgets=[ - widget.GenPollText( - fmt="{}", - foreground=backgroundColor, - background=colorScheme[13], - func=lambda: subprocess.check_output( - expanduser("~/.config/qtile/scripts/github/notifications") - ).decode("utf-8"), - update_interval=10, - padding=10, - ), - widget.GenPollText( - fmt="{}", - foreground=backgroundColor, - background=colorScheme[13], - func=lambda: subprocess.check_output( - expanduser("~/.config/qtile/scripts/github/gists") - ).decode("utf-8"), - update_interval=10, - padding=10, - ), - widget.GenPollText( - fmt="{}", - foreground=backgroundColor, - background=colorScheme[13], - func=lambda: subprocess.check_output( - expanduser("~/.config/qtile/scripts/github/repositories") - ).decode("utf-8"), - update_interval=10, - padding=10, - ), - ], - text_closed=" [Github <] ", - text_open=" [Github >] ", - )