init
This commit is contained in:
Executable
+692
@@ -0,0 +1,692 @@
|
||||
dwl - dwm for Wayland
|
||||
|
||||
Copyright © 2020 dwl team
|
||||
|
||||
See also the files LICENSE.tinywl, LICENSE.dwm and LICENSE.sway.
|
||||
|
||||
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.
|
||||
|
||||
----
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
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
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
Portions of dwl based on dwm code are used under the following license:
|
||||
|
||||
MIT/X Consortium License
|
||||
|
||||
© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
|
||||
© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
|
||||
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
|
||||
© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com>
|
||||
© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com>
|
||||
© 2007-2009 Christof Musik <christof at sendfax dot de>
|
||||
© 2007-2009 Premysl Hruby <dfenze at gmail dot com>
|
||||
© 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
|
||||
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
|
||||
© 2008 Neale Pickett <neale dot woozle dot org>
|
||||
© 2009 Mate Nagy <mnagy at port70 dot net>
|
||||
© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
|
||||
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
|
||||
© 2011 Christoph Lohmann <20h@r-36.net>
|
||||
© 2015-2016 Quentin Rameau <quinq@fifth.space>
|
||||
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
|
||||
© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
|
||||
|
||||
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.
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2016-2017 Drew DeVault
|
||||
|
||||
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.
|
||||
Executable
+127
@@ -0,0 +1,127 @@
|
||||
dwl is originally based on TinyWL, which is used under the following license:
|
||||
|
||||
This work is licensed under CC0, which effectively puts it in the public domain.
|
||||
|
||||
---
|
||||
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
# dwl-patches
|
||||
* A general [dwl wiki](https://codeberg.org/dwl/dwl/wiki) is available at the main [dwl] repository.
|
||||
* This repository is exclusively for dwl PATCHES.
|
||||
|
||||
*Note: All patches are user-submitted content. The authors of dwl do not continually monitor them. You are responsible for downloading and reviewing a patch before using it!*
|
||||
|
||||
## Reporting Issues
|
||||
- Issues with existing patches can be generated here in the dwl-patches [issues]. Please be sure to "@" reference the patch author in your issue.
|
||||
|
||||
## Contributing Patches to `dwl-patches`
|
||||
Since dwl follows [suckless](https://suckless.org/) philosophy, it doesn't provide every feature under the sun. To broaden dwl's functionality, one needs to get familiar with the concept of patching. To get your feet wet, consult [the hacking page](https://suckless.org/hacking/) of the suckless website.
|
||||
|
||||
Patches should normally target the latest dwl [release].
|
||||
If you target an older release, specify that in the `Download` link on your `README.md` page.
|
||||
If you target the unstable `main` branch, specify that in the `Download` link on your `README.md` page.
|
||||
|
||||
0. Starting from a local clone of [dwl] (not dwl-patches)
|
||||
1. If you do not have it already, add the remote for the main dwl repository in your local copy and fetch it:
|
||||
`git remote add --fetch upstream https://codeberg.org/dwl/dwl`
|
||||
2. Use git to create a branch for your new patch and hack away creating your patched version of [dwl].
|
||||
3. In your local clone of dwl, create a .patch file
|
||||
`git format-patch upstream/main...<branch-name> --stdout > PATCHNAME.patch`
|
||||
4. Now fork [dwl-patches] (not dwl) in Codeberg and clone it locally
|
||||
5. Configure your `dwl-patches` local clone
|
||||
`git config --local pull.rebase true`
|
||||
6. In your local `dwl-patches` clone, add a directory called `patches/PATCHNAME`. Place the `PATCHNAME.patch` you created in step (2) into the `patches/PATCHNAME` directory.
|
||||
7. Add a `README.md` page to the `PATCHNAME` directory using this template (add/remove sections as you like):
|
||||
```markdown
|
||||
### Description
|
||||
Insert a short summary of changes that your patch implements.
|
||||
|
||||
### Download
|
||||
- [git branch](/USERNAME/dwl/src/branch/PATCHNAME)
|
||||
^^^^^^^^^^ OPTIONAL: Patchers are no longer obligated to maintain public `dwl` branches devoted to their patches
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/PATCHNAME/PATCHNAME.patch)
|
||||
Use the ^RAW^ patch link here
|
||||
^^^ "0.7" is an example. Use the release that your patch targets
|
||||
- [main YYYY-MM-DD](/dwl/dwl-patches/raw/branch/main/patches/PATCHNAME/PATCHNAME.patch)
|
||||
^^^^^^^^^^ Patches targeting the unstable "main" branch include a YYYY-MM-DD indicator
|
||||
### Authors - latest at top [Codeberg nick is mandatory; other contact methods optional]
|
||||
- [YOUR_NICK](https://codeberg.org/USERNAME)
|
||||
your_email@if_you_wish_to.share.it
|
||||
your_irc_nick at [Libera IRC dwl channel](https://web.libera.chat/?channels=#dwl)
|
||||
your_discord_handle at [dwl Discord](https://discord.gg/jJxZnrGPWN)
|
||||
```
|
||||
You may choose to include screenshots (hosted in your patch's subdirectory) in your `README.md`. The process is described [here](https://docs.codeberg.org/markdown/using-images/).
|
||||
|
||||
8. Use the Codeberg web interface to send a pull request to [dwl-patches] (NOT to [dwl])
|
||||
9. WHEN YOUR PULL REQUEST IS APPROVED, your Codeberg account will also be granted commit access to [dwl-patches]. Once you have write access, you can make direct modifications/upates to your patches and you are free to create new patches rather than creating pull requests.
|
||||
|
||||
Individuals who have made known that they no longer intend to maintain their patches will have commit access to the [dwl-pathces] repository removed.
|
||||
|
||||
A returning user who formerly had commit access is welcome to open an issue on [dwl-patches] requesting commit access be reinstated. When doing so, please link to the original issue opened that granted commit access.
|
||||
|
||||
## Updating/Modifying/Adopting Existing Patches
|
||||
- If the existing patch is already being maintained by another author, do not make modifications to it.
|
||||
- Create an issue at [issues] @mentioning the current maintainer.
|
||||
- If you receive no reply for seven days, you may assume the patch abandoned and you may adopt the patch.
|
||||
- Modify the `README.md` with new links for your raw patch and for your git branch.
|
||||
- **LEAVE PREVIOUS AUTHOR(S)' NICKS/LINKS INTACT UNDER THE "Authors" HEADING!**
|
||||
- Add your own nick/link to the top of the "Authors" list.
|
||||
|
||||
## Deprecating Existing Patches
|
||||
- Patches will not be removed from this archive but may instead be deprecated if the author(s)/maintainer(s) of a patch so desire.
|
||||
- Please do not open issues or contact maintainers to request deprecation of a patch.
|
||||
- Deprecation of a patch will only occur if *all* authors or current maintainers of the patch agree to the decision to deprecate.
|
||||
- In such a circumstance the author(s)/maintainer(s):
|
||||
- Will create a commit moving the patch to the `stale-patches` directory
|
||||
- May explain in the associated `README.md` any relevant details of the decision to deprecate the patch.
|
||||
- This process allows current or future users of the patch the option to adopt, modify, or integrate stale/historical code or portions thereof.
|
||||
|
||||
## stale-patches
|
||||
Deprecated or unmaintained patches are held in the [stale-patches] directory.
|
||||
Currently, this directory also contains `.md` description files from ancient patches predating the move to Codeberg.
|
||||
|
||||
If you have the inclination to revive one of these, please follow the same procedures outlined below for contributing new patches.
|
||||
|
||||
In your initial pull request (or in the commit that revives the stale patch if you already have write access), remove the corresponding `.md` file or the patch directory from [stale-patches].
|
||||
|
||||
[stale-patches]: https://codeberg.org/dwl/dwl-patches/src/branch/main/stale-patches
|
||||
[dwl]: https://codeberg.org/dwl/dwl
|
||||
[dwl-patches]: https://codeberg.org/dwl/dwl-patches
|
||||
[issues]: https://codeberg.org/dwl/dwl-patches/issues
|
||||
[release]: https://codeberg.org/dwl/dwl/releases
|
||||
[Codeberg]: https://codeberg.org
|
||||
|
||||
##
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
### Description
|
||||
Port of dwm's accessnthmon. Adds functions to tag and focus monitor by index.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/Rutherther/dwl/src/branch/patch/accessnthmonitor)
|
||||
- [2024-05-10](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/accessnthmon/accessnthmon.patch)
|
||||
### Authors
|
||||
- [Rutherther](https://codeberg.org/Rutherther)
|
||||
- [Palanix](https://codeberg.org/Palanix)
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
From 5f531bfb1387ded7b8817faf7df760d3b998742b Mon Sep 17 00:00:00 2001
|
||||
From: Rutherther <rutherther@proton.me>
|
||||
Date: Sat, 27 Apr 2024 21:25:16 +0200
|
||||
Subject: [PATCH] feat: access nth monitor
|
||||
|
||||
---
|
||||
config.def.h | 4 +++-
|
||||
dwl.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 49 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8847e58..4709c5d 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -108,7 +108,9 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
|
||||
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \
|
||||
- { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }, \
|
||||
+ { WLR_MODIFIER_ALT, KEY, focusnthmon, {.ui = TAG} }, \
|
||||
+ { WLR_MODIFIER_ALT|WLR_MODIFIER_SHIFT, SKEY, tagnthmon, {.ui = TAG} }
|
||||
|
||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763df..1d42caf 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server-core.h>
|
||||
+#include <wayland-util.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/backend/libinput.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
@@ -278,8 +279,10 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data);
|
||||
static void destroysessionlock(struct wl_listener *listener, void *data);
|
||||
static void destroysessionmgr(struct wl_listener *listener, void *data);
|
||||
static Monitor *dirtomon(enum wlr_direction dir);
|
||||
+static Monitor *numtomon(int num);
|
||||
static void focusclient(Client *c, int lift);
|
||||
static void focusmon(const Arg *arg);
|
||||
+static void focusnthmon(const Arg *arg);
|
||||
static void focusstack(const Arg *arg);
|
||||
static Client *focustop(Monitor *m);
|
||||
static void fullscreennotify(struct wl_listener *listener, void *data);
|
||||
@@ -329,6 +332,7 @@ static void spawn(const Arg *arg);
|
||||
static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
+static void tagnthmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
@@ -1233,6 +1237,25 @@ dirtomon(enum wlr_direction dir)
|
||||
return selmon;
|
||||
}
|
||||
|
||||
+Monitor *
|
||||
+numtomon(int num)
|
||||
+{
|
||||
+ Monitor *m = NULL;
|
||||
+ int found = 0;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ wl_list_for_each(m, &mons, link) {
|
||||
+ if (!m->wlr_output->enabled)
|
||||
+ i--;
|
||||
+ else if (i == num) {
|
||||
+ found = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ i++;
|
||||
+ }
|
||||
+ return found ? m : NULL;
|
||||
+}
|
||||
+
|
||||
void
|
||||
focusclient(Client *c, int lift)
|
||||
{
|
||||
@@ -1320,6 +1343,16 @@ focusmon(const Arg *arg)
|
||||
focusclient(focustop(selmon), 1);
|
||||
}
|
||||
|
||||
+void
|
||||
+focusnthmon(const Arg *arg)
|
||||
+{
|
||||
+ Monitor *m = numtomon(arg->i);
|
||||
+ if (!m || m == selmon)
|
||||
+ return;
|
||||
+ selmon = m;
|
||||
+ focusclient(focustop(selmon), 1);
|
||||
+}
|
||||
+
|
||||
void
|
||||
focusstack(const Arg *arg)
|
||||
{
|
||||
@@ -2569,6 +2602,19 @@ tagmon(const Arg *arg)
|
||||
setmon(sel, dirtomon(arg->i), 0);
|
||||
}
|
||||
|
||||
+void
|
||||
+tagnthmon(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ Monitor *m = numtomon(arg->i);
|
||||
+ if (!m || !sel)
|
||||
+ return;
|
||||
+ setmon(sel, m, 0);
|
||||
+
|
||||
+ arrange(selmon);
|
||||
+ arrange(m);
|
||||
+}
|
||||
+
|
||||
void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
--
|
||||
2.44.0
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
### Description
|
||||
Automatically center floating windows.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/guidocella/dwl/src/branch/alwayscenter)
|
||||
- [2024-06-05](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/alwayscenter/alwayscenter.patch)
|
||||
|
||||
### Authors
|
||||
- [Guido Cella](https://codeberg.org/guidocella)
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
From f43a49324c2ddd21100d6308d1adde9d894746e2 Mon Sep 17 00:00:00 2001
|
||||
From: Guido Cella <guido@guidocella.xyz>
|
||||
Date: Wed, 5 Jun 2024 12:05:16 +0200
|
||||
Subject: [PATCH] center floating windows
|
||||
|
||||
---
|
||||
dwl.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 12f441e..c377c67 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -499,6 +499,11 @@ applyrules(Client *c)
|
||||
}
|
||||
}
|
||||
|
||||
+ if (mon) {
|
||||
+ c->geom.x = (mon->w.width - c->geom.width) / 2 + mon->m.x;
|
||||
+ c->geom.y = (mon->w.height - c->geom.height) / 2 + mon->m.y;
|
||||
+ }
|
||||
+
|
||||
c->isfloating |= client_is_float_type(c);
|
||||
setmon(c, mon, newtags);
|
||||
}
|
||||
@@ -1787,6 +1792,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
* If there is no parent, apply rules */
|
||||
if ((p = client_get_parent(c))) {
|
||||
c->isfloating = 1;
|
||||
+ if (p->mon) {
|
||||
+ c->geom.x = (p->mon->w.width - c->geom.width) / 2 + p->mon->m.x;
|
||||
+ c->geom.y = (p->mon->w.height - c->geom.height) / 2 + p->mon->m.y;
|
||||
+ }
|
||||
setmon(c, p->mon, p->tags);
|
||||
} else {
|
||||
applyrules(c);
|
||||
--
|
||||
2.49.0
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
### Description
|
||||
Newly created windows are placed at the bottom of the client tile stack.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/bencc/dwl/src/branch/attachbottom)
|
||||
- [2024-05-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/attachbottom/attachbottom.patch)
|
||||
|
||||
### Authors
|
||||
- [Ben Collerson](https://codeberg.org/bencc)
|
||||
- [Aurel Weinhold](https://github.com/AurelWeinhold)
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
From 0dda3ed8634154fd3887b71133b451d66a11b61d Mon Sep 17 00:00:00 2001
|
||||
From: Ben Collerson <benc@benc.cc>
|
||||
Date: Thu, 4 Jan 2024 23:31:41 +1000
|
||||
Subject: [PATCH] attachbottom
|
||||
|
||||
---
|
||||
dwl.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763dfc..12e08e2b 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1605,7 +1605,11 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->geom.height += 2 * c->bw;
|
||||
|
||||
/* Insert this client into client lists. */
|
||||
- wl_list_insert(&clients, &c->link);
|
||||
+ if (clients.prev)
|
||||
+ // tile at the bottom
|
||||
+ wl_list_insert(clients.prev, &c->link);
|
||||
+ else
|
||||
+ wl_list_insert(&clients, &c->link);
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
|
||||
/* Set initial monitor, tags, floating status, and focus:
|
||||
--
|
||||
2.43.0
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
### Description
|
||||
Makes windows attach below the currently active window.
|
||||
|
||||
KNOWN ISSUES: Upon closing the last client when using multiple monitors, the last client will briefly flash on all
|
||||
monitors before closing.
|
||||
|
||||
### Download
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/attachfocused/attachfocused.patch)
|
||||
|
||||
### Authors
|
||||
- [MayOrMayNotBeACat](https://codeberg.org/MayOrMayNotBeACat)
|
||||
@@ -0,0 +1,29 @@
|
||||
From d03851c14073874f5b3d19a095e184dc24d219cd Mon Sep 17 00:00:00 2001
|
||||
From: MayOrMayNotBeACat <maybeacat804@gmail.com>
|
||||
Date: Sun, 11 May 2025 20:24:51 -0400
|
||||
Subject: [PATCH] Make new windows attach to active client
|
||||
|
||||
---
|
||||
dwl.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index cf3ef70..1907c5f 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1726,7 +1726,11 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->geom.height += 2 * c->bw;
|
||||
|
||||
/* Insert this client into client lists. */
|
||||
- wl_list_insert(&clients, &c->link);
|
||||
+ Client* focused = focustop(selmon);
|
||||
+ if (focused)
|
||||
+ wl_list_insert(&focused->link, &c->link);
|
||||
+ else
|
||||
+ wl_list_insert(&clients, &c->link);
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
|
||||
/* Set initial monitor, tags, floating status, and focus:
|
||||
--
|
||||
2.49.0
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
### Description
|
||||
This is a port of attachtop patch for dwm: https://dwm.suckless.org/patches/attachtop
|
||||
|
||||
New client attaches below the last master/on top of the stack.
|
||||
|
||||
Behavior feels very intuitive as it doesn't disrupt existing masters no matter the amount of them, it only pushes the clients in stack down.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/nikitaivanov/dwl/src/branch/attachtop)
|
||||
- [2025-06-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/attachtop/attachtop.patch)
|
||||
|
||||
### Authors
|
||||
- [Nikita Ivanov](https://codeberg.org/nikitaivanov)
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
From 29e6a4bef02c473cc5bd04804fe508bda265077d Mon Sep 17 00:00:00 2001
|
||||
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
|
||||
Date: Sun, 7 Apr 2024 21:10:17 +0200
|
||||
Subject: [PATCH] New client are attached on top of the stack
|
||||
|
||||
---
|
||||
dwl.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763df..02e3d07 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1605,7 +1605,18 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->geom.height += 2 * c->bw;
|
||||
|
||||
/* Insert this client into client lists. */
|
||||
- wl_list_insert(&clients, &c->link);
|
||||
+ i = 0;
|
||||
+ wl_list_for_each(w, &clients, link) {
|
||||
+ if (!VISIBLEON(w, selmon) || w->isfloating)
|
||||
+ continue;
|
||||
+ p = w;
|
||||
+ if (++i >= selmon->nmaster)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (i > 0)
|
||||
+ wl_list_insert(&p->link, &c->link);
|
||||
+ else
|
||||
+ wl_list_insert(&clients, &c->link);
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
|
||||
/* Set initial monitor, tags, floating status, and focus:
|
||||
--
|
||||
2.49.0
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
### Description
|
||||
Allow dwl to execute commands from autostart array in your config.h file. And when you exit dwl all processes from autostart array will be killed.
|
||||
|
||||
Note: Commands from array are executed using execvp(). So if you need to execute shell command you need to prefix it with "sh", "-c" (change sh to any shell you like).
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/sevz/dwl/src/branch/autostart)
|
||||
- [2025-01-20](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/autostart/autostart.patch)
|
||||
- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/autostart/autostart-0.7.patch)
|
||||
|
||||
### Authors
|
||||
- [sevz](https://codeberg.org/sevz)
|
||||
- [Rayan Nakib](https://nakibrayan2.pages.dev/)
|
||||
- [NFVblog](https://github.com/nf02)
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
From 787f7252d63945996f009828aff3c44afd0f7781 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||
<leohdz172@proton.me>
|
||||
Date: Sat, 8 Jul 2023 17:11:36 -0600
|
||||
Subject: [PATCH] port autostart patch from dwm
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
https://dwm.suckless.org/patches/cool_autostart/
|
||||
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
|
||||
---
|
||||
config.def.h | 7 +++++++
|
||||
dwl.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
2 files changed, 61 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..8dc6502 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -20,6 +20,13 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
|
||||
/* logging */
|
||||
static int log_level = WLR_ERROR;
|
||||
|
||||
+/* Autostart */
|
||||
+static const char *const autostart[] = {
|
||||
+ "wbg", "/path/to/your/image", NULL,
|
||||
+ NULL /* terminate */
|
||||
+};
|
||||
+
|
||||
+
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
/* app_id title tags mask isfloating monitor */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 5bf995e..e8b8727 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -249,6 +249,7 @@ static void arrange(Monitor *m);
|
||||
static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||
struct wlr_box *usable_area, int exclusive);
|
||||
static void arrangelayers(Monitor *m);
|
||||
+static void autostartexec(void);
|
||||
static void axisnotify(struct wl_listener *listener, void *data);
|
||||
static void buttonpress(struct wl_listener *listener, void *data);
|
||||
static void chvt(const Arg *arg);
|
||||
@@ -432,6 +433,9 @@ static xcb_atom_t netatom[NetLast];
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
|
||||
+static pid_t *autostart_pids;
|
||||
+static size_t autostart_len;
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
@@ -580,6 +584,27 @@ arrangelayers(Monitor *m)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+autostartexec(void) {
|
||||
+ const char *const *p;
|
||||
+ size_t i = 0;
|
||||
+
|
||||
+ /* count entries */
|
||||
+ for (p = autostart; *p; autostart_len++, p++)
|
||||
+ while (*++p);
|
||||
+
|
||||
+ autostart_pids = calloc(autostart_len, sizeof(pid_t));
|
||||
+ for (p = autostart; *p; i++, p++) {
|
||||
+ if ((autostart_pids[i] = fork()) == 0) {
|
||||
+ setsid();
|
||||
+ execvp(*p, (char *const *)p);
|
||||
+ die("dwl: execvp %s:", *p);
|
||||
+ }
|
||||
+ /* skip arguments */
|
||||
+ while (*++p);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void
|
||||
axisnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -676,11 +701,21 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
||||
void
|
||||
cleanup(void)
|
||||
{
|
||||
+ size_t i;
|
||||
#ifdef XWAYLAND
|
||||
wlr_xwayland_destroy(xwayland);
|
||||
xwayland = NULL;
|
||||
#endif
|
||||
wl_display_destroy_clients(dpy);
|
||||
+
|
||||
+ /* kill child processes */
|
||||
+ for (i = 0; i < autostart_len; i++) {
|
||||
+ if (0 < autostart_pids[i]) {
|
||||
+ kill(autostart_pids[i], SIGTERM);
|
||||
+ waitpid(autostart_pids[i], NULL, 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (child_pid > 0) {
|
||||
kill(-child_pid, SIGTERM);
|
||||
waitpid(child_pid, NULL, 0);
|
||||
@@ -1497,18 +1532,31 @@ void
|
||||
handlesig(int signo)
|
||||
{
|
||||
if (signo == SIGCHLD) {
|
||||
-#ifdef XWAYLAND
|
||||
siginfo_t in;
|
||||
/* wlroots expects to reap the XWayland process itself, so we
|
||||
* use WNOWAIT to keep the child waitable until we know it's not
|
||||
* XWayland.
|
||||
*/
|
||||
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
|
||||
- && (!xwayland || in.si_pid != xwayland->server->pid))
|
||||
- waitpid(in.si_pid, NULL, 0);
|
||||
-#else
|
||||
- while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
+#ifdef XWAYLAND
|
||||
+ && (!xwayland || in.si_pid != xwayland->server->pid)
|
||||
#endif
|
||||
+ ) {
|
||||
+ pid_t *p, *lim;
|
||||
+ waitpid(in.si_pid, NULL, 0);
|
||||
+ if (in.si_pid == child_pid)
|
||||
+ child_pid = -1;
|
||||
+ if (!(p = autostart_pids))
|
||||
+ continue;
|
||||
+ lim = &p[autostart_len];
|
||||
+
|
||||
+ for (; p < lim; p++) {
|
||||
+ if (*p == in.si_pid) {
|
||||
+ *p = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
} else if (signo == SIGINT || signo == SIGTERM) {
|
||||
quit(NULL);
|
||||
}
|
||||
@@ -2224,6 +2272,7 @@ run(char *startup_cmd)
|
||||
die("startup: backend_start");
|
||||
|
||||
/* Now that the socket exists and the backend is started, run the startup command */
|
||||
+ autostartexec();
|
||||
if (startup_cmd) {
|
||||
int piperw[2];
|
||||
if (pipe(piperw) < 0)
|
||||
--
|
||||
2.45.2
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
From 3b0b0249d900121a90528616f4d11f733c7a5ca2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||
<leohdz172@proton.me>
|
||||
Date: Sat, 8 Jul 2023 17:11:36 -0600
|
||||
Subject: [PATCH] port autostart patch from dwm
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
https://dwm.suckless.org/patches/cool_autostart/
|
||||
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
|
||||
---
|
||||
config.def.h | 7 +++++++
|
||||
dwl.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 62 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171d..8dc6502c 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -20,6 +20,13 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
|
||||
/* logging */
|
||||
static int log_level = WLR_ERROR;
|
||||
|
||||
+/* Autostart */
|
||||
+static const char *const autostart[] = {
|
||||
+ "wbg", "/path/to/your/image", NULL,
|
||||
+ NULL /* terminate */
|
||||
+};
|
||||
+
|
||||
+
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
/* app_id title tags mask isfloating monitor */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ad21e1ba..3118e07f 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -246,6 +246,7 @@ static void arrange(Monitor *m);
|
||||
static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||
struct wlr_box *usable_area, int exclusive);
|
||||
static void arrangelayers(Monitor *m);
|
||||
+static void autostartexec(void);
|
||||
static void axisnotify(struct wl_listener *listener, void *data);
|
||||
static void buttonpress(struct wl_listener *listener, void *data);
|
||||
static void chvt(const Arg *arg);
|
||||
@@ -455,6 +456,9 @@ static struct wlr_xwayland *xwayland;
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
|
||||
+static pid_t *autostart_pids;
|
||||
+static size_t autostart_len;
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
@@ -599,6 +603,27 @@ arrangelayers(Monitor *m)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+autostartexec(void) {
|
||||
+ const char *const *p;
|
||||
+ size_t i = 0;
|
||||
+
|
||||
+ /* count entries */
|
||||
+ for (p = autostart; *p; autostart_len++, p++)
|
||||
+ while (*++p);
|
||||
+
|
||||
+ autostart_pids = calloc(autostart_len, sizeof(pid_t));
|
||||
+ for (p = autostart; *p; i++, p++) {
|
||||
+ if ((autostart_pids[i] = fork()) == 0) {
|
||||
+ setsid();
|
||||
+ execvp(*p, (char *const *)p);
|
||||
+ die("dwl: execvp %s:", *p);
|
||||
+ }
|
||||
+ /* skip arguments */
|
||||
+ while (*++p);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void
|
||||
axisnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -695,12 +720,23 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
||||
void
|
||||
cleanup(void)
|
||||
{
|
||||
+ size_t i;
|
||||
+
|
||||
cleanuplisteners();
|
||||
#ifdef XWAYLAND
|
||||
wlr_xwayland_destroy(xwayland);
|
||||
xwayland = NULL;
|
||||
#endif
|
||||
wl_display_destroy_clients(dpy);
|
||||
+
|
||||
+ /* kill child processes */
|
||||
+ for (i = 0; i < autostart_len; i++) {
|
||||
+ if (0 < autostart_pids[i]) {
|
||||
+ kill(autostart_pids[i], SIGTERM);
|
||||
+ waitpid(autostart_pids[i], NULL, 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (child_pid > 0) {
|
||||
kill(-child_pid, SIGTERM);
|
||||
waitpid(child_pid, NULL, 0);
|
||||
@@ -1551,10 +1587,25 @@ gpureset(struct wl_listener *listener, void *data)
|
||||
void
|
||||
handlesig(int signo)
|
||||
{
|
||||
- if (signo == SIGCHLD)
|
||||
- while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
- else if (signo == SIGINT || signo == SIGTERM)
|
||||
+ if (signo == SIGCHLD) {
|
||||
+ pid_t pid, *p, *lim;
|
||||
+ while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
|
||||
+ if (pid == child_pid)
|
||||
+ child_pid = -1;
|
||||
+ if (!(p = autostart_pids))
|
||||
+ continue;
|
||||
+ lim = &p[autostart_len];
|
||||
+
|
||||
+ for (; p < lim; p++) {
|
||||
+ if (*p == pid) {
|
||||
+ *p = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } else if (signo == SIGINT || signo == SIGTERM) {
|
||||
quit(NULL);
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2241,6 +2292,7 @@ run(char *startup_cmd)
|
||||
die("startup: backend_start");
|
||||
|
||||
/* Now that the socket exists and the backend is started, run the startup command */
|
||||
+ autostartexec();
|
||||
if (startup_cmd) {
|
||||
int piperw[2];
|
||||
if (pipe(piperw) < 0)
|
||||
--
|
||||
2.48.0
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
### Description
|
||||
Add a system tray to the [bar](/dwl/dwl-patches/src/branch/main/patches/bar).
|
||||
|
||||
To keep dependencies to minimum, icon(svg) loading from the filesystem is not
|
||||
supported. Applications that expect this will show the initial letter of the
|
||||
program name, instead of a real icon.
|
||||
|
||||
Menus for the icons are handled by a dmenu-like program of the user's choice.
|
||||
|
||||
### Dependencies
|
||||
- [bar.patch](/dwl/dwl-patches/src/branch/main/patches/bar)
|
||||
- [libdbus](https://gitlab.freedesktop.org/dbus/dbus)
|
||||
|
||||
### Download
|
||||
- [git branch](/janetski/dwl/src/branch/0.7-bar-systray)
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/bar-systray/bar-systray-0.7.patch)
|
||||
|
||||
### Authors
|
||||
- [janetski](https://codeberg.org/janetski) ([.vetu](https://discordapp.com/users/355488216469471242) on discord)
|
||||
+3023
File diff suppressed because it is too large
Load Diff
Executable
+34
@@ -0,0 +1,34 @@
|
||||
### Description
|
||||
|
||||
Add a bar identical to dwm's bar.
|
||||
|
||||
To use a status-bar, you can pass in status text via stdin:
|
||||
```
|
||||
slstatus -s | dwl
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
* tllist (build dependency, required & pulled automatically by fcft)
|
||||
* fcft
|
||||
* pixman
|
||||
|
||||
### Download
|
||||
- [main 2025-07-29](/dwl/dwl-patches/raw/branch/main/patches/bar/bar.patch)
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/bar/bar-0.7.patch)
|
||||
- [0.6](/dwl/dwl-patches/raw/branch/main/patches/bar/bar-0.6.patch)
|
||||
|
||||
It is required to remove, regenerate or update `config.h` after applying the patch,
|
||||
since it makes changes to the configuration structure.
|
||||
For example, in the `pertag` patch, `TAGCOUNT` must be replaced with `LENGTH(tags)`.
|
||||
|
||||
Below is a preview of the patch.
|
||||
|
||||

|
||||
|
||||
### Authors
|
||||
- [sewn](https://codeberg.org/sewn)
|
||||
|
||||
### Credits
|
||||
- [MadcowOG](https://github.com/MadcowOG)
|
||||
- [kolumni](https://github.com/kolunmi/dwlb)
|
||||
|
||||
Executable
+1245
File diff suppressed because it is too large
Load Diff
Executable
+1245
File diff suppressed because it is too large
Load Diff
Executable
+1266
File diff suppressed because it is too large
Load Diff
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
Executable
+10
@@ -0,0 +1,10 @@
|
||||
### Description
|
||||
|
||||
Add a border around the [bar](/dwl/dwl-patches/wiki/bar) similar to how a client is given a border.
|
||||
|
||||
### Download
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/barborder/barborder.patch)
|
||||
|
||||
### Authors
|
||||
- [sewn](https://codeberg.org/sewn)
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
From 7d95ce0fba8f172748bbd71b4c03ce12acd54eea Mon Sep 17 00:00:00 2001
|
||||
From: sewn <sewn@disroot.org>
|
||||
Date: Fri, 23 Aug 2024 14:11:37 +0300
|
||||
Subject: [PATCH] add border to bar
|
||||
|
||||
---
|
||||
config.def.h | 3 ++-
|
||||
dwl.c | 32 +++++++++++++++++++-------------
|
||||
2 files changed, 21 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 5d1dc2b..4763482 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -6,7 +6,7 @@
|
||||
/* appearance */
|
||||
static const int sloppyfocus = 1; /* focus follows mouse */
|
||||
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||
-static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
+static const unsigned int borderpx = 1; /* border pixel of windows & bar */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
static const char *fonts[] = {"monospace:size=10"};
|
||||
@@ -18,6 +18,7 @@ static uint32_t colors[][3] = {
|
||||
[SchemeNorm] = { 0xbbbbbbff, 0x222222ff, 0x444444ff },
|
||||
[SchemeSel] = { 0xeeeeeeff, 0x005577ff, 0x005577ff },
|
||||
[SchemeUrg] = { 0, 0, 0x770000ff },
|
||||
+ [SchemeBar] = { 0, 0, 0x557700ff },
|
||||
};
|
||||
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ece537a..c637da4 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -85,7 +85,7 @@
|
||||
#define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad)
|
||||
|
||||
/* enums */
|
||||
-enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */
|
||||
+enum { SchemeNorm, SchemeSel, SchemeUrg, SchemeBar }; /* color schemes */
|
||||
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||
enum { XDGShell, LayerShell, X11 }; /* client types */
|
||||
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
|
||||
@@ -750,7 +750,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
if (!c && !exclusive_focus &&
|
||||
(node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) &&
|
||||
(buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) {
|
||||
- cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale;
|
||||
+ cx = (cursor->x - selmon->m.x - borderpx) * selmon->wlr_output->scale;
|
||||
do
|
||||
x += TEXTW(selmon, tags[i]);
|
||||
while (cx >= x && ++i < LENGTH(tags));
|
||||
@@ -1506,10 +1506,12 @@ dirtomon(enum wlr_direction dir)
|
||||
void
|
||||
drawbar(Monitor *m)
|
||||
{
|
||||
- int x, w, tw = 0;
|
||||
+ int x, y = borderpx, w, tw = 0;
|
||||
+ int mh = m->b.height - borderpx * 2, mw = m->b.width - borderpx * 2;
|
||||
int boxs = m->drw->font->height / 9;
|
||||
int boxw = m->drw->font->height / 6 + 2;
|
||||
uint32_t i, occ = 0, urg = 0;
|
||||
+ uint32_t borderscm[] = { colors[SchemeBar][ColBorder] };
|
||||
Client *c;
|
||||
Buffer *buf;
|
||||
|
||||
@@ -1518,11 +1520,15 @@ drawbar(Monitor *m)
|
||||
if (!(buf = bufmon(m)))
|
||||
return;
|
||||
|
||||
+ drwl_setscheme(m->drw, borderscm);
|
||||
+ drwl_rect(m->drw, 0, 0, m->b.width, m->b.height, 1, 0);
|
||||
+ drwl_setscheme(m->drw, colors[SchemeNorm]);
|
||||
+
|
||||
/* draw status first so it can be overdrawn by tags later */
|
||||
if (m == selmon) { /* status is only drawn on selected monitor */
|
||||
drwl_setscheme(m->drw, colors[SchemeNorm]);
|
||||
tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */
|
||||
- drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0);
|
||||
+ drwl_text(m->drw, borderpx + mw - tw, y, tw, mh, 0, stext, 0);
|
||||
}
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
@@ -1532,31 +1538,31 @@ drawbar(Monitor *m)
|
||||
if (c->isurgent)
|
||||
urg |= c->tags;
|
||||
}
|
||||
- x = 0;
|
||||
+ x = borderpx;
|
||||
c = focustop(m);
|
||||
for (i = 0; i < LENGTH(tags); i++) {
|
||||
w = TEXTW(m, tags[i]);
|
||||
drwl_setscheme(m->drw, colors[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
|
||||
- drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, tags[i], urg & 1 << i);
|
||||
+ drwl_text(m->drw, x, y, w, mh, m->lrpad / 2, tags[i], urg & 1 << i);
|
||||
if (occ & 1 << i)
|
||||
- drwl_rect(m->drw, x + boxs, boxs, boxw, boxw,
|
||||
+ drwl_rect(m->drw, x + boxs, y + boxs, boxw, boxw,
|
||||
m == selmon && c && c->tags & 1 << i,
|
||||
urg & 1 << i);
|
||||
x += w;
|
||||
}
|
||||
w = TEXTW(m, m->ltsymbol);
|
||||
drwl_setscheme(m->drw, colors[SchemeNorm]);
|
||||
- x = drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, m->ltsymbol, 0);
|
||||
+ x = drwl_text(m->drw, x, y, w, mh, m->lrpad / 2, m->ltsymbol, 0);
|
||||
|
||||
- if ((w = m->b.width - tw - x) > m->b.height) {
|
||||
+ if ((w = mw - tw - x + borderpx) > mh) {
|
||||
if (c) {
|
||||
drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]);
|
||||
- drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0);
|
||||
+ drwl_text(m->drw, x, y, w, mh, m->lrpad / 2, client_get_title(c), 0);
|
||||
if (c && c->isfloating)
|
||||
- drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0);
|
||||
+ drwl_rect(m->drw, x + boxs, y + boxs, boxw, boxw, 0, 0);
|
||||
} else {
|
||||
drwl_setscheme(m->drw, colors[SchemeNorm]);
|
||||
- drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1);
|
||||
+ drwl_rect(m->drw, x, y, w, mh, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3183,7 +3189,7 @@ updatebar(Monitor *m)
|
||||
|
||||
m->b.scale = m->wlr_output->scale;
|
||||
m->lrpad = m->drw->font->height;
|
||||
- m->b.height = m->drw->font->height + 2;
|
||||
+ m->b.height = m->drw->font->height + 2 + borderpx * 2;
|
||||
m->b.real_height = (int)((float)m->b.height / m->wlr_output->scale);
|
||||
}
|
||||
|
||||
--
|
||||
2.46.0
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
### Description
|
||||
Add support for colored status text to the [bar](/dwl/dwl-patches/src/branch/main/patches/bar). Text can be colored in the same manner as with dwlb, namely by wrapping it between `^fg(color)` and `^fg()` or `^bg(color)` and `^bg()`, where `color` is a 6-digit hexadecimal value.
|
||||
|
||||
### Download
|
||||
- [git branch](/kerberoge/dwl/src/branch/barcolors)
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/barcolors/barcolors.patch)
|
||||
|
||||
### Authors
|
||||
- [kerberoge](https://codeberg.org/kerberoge)
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
From d2b529d9ebee6b2e625afd5c89c2ede5bb0ca91b Mon Sep 17 00:00:00 2001
|
||||
From: Kerberoge <sjoerdenjh@gmail.com>
|
||||
Date: Sun, 25 Aug 2024 22:41:55 +0200
|
||||
Subject: [PATCH 1/1] updated barcolors
|
||||
|
||||
---
|
||||
dwl.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 87 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ece537a..6663399 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -83,6 +83,7 @@
|
||||
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
|
||||
#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
|
||||
#define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad)
|
||||
+#define PREFIX(str, prefix) !strncmp(str, prefix, strlen(prefix))
|
||||
|
||||
/* enums */
|
||||
enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */
|
||||
@@ -318,6 +319,7 @@ static void destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||
static Monitor *dirtomon(enum wlr_direction dir);
|
||||
static void drawbar(Monitor *m);
|
||||
static void drawbars(void);
|
||||
+static int drawstatus(Monitor *m);
|
||||
static void focusclient(Client *c, int lift);
|
||||
static void focusmon(const Arg *arg);
|
||||
static void focusstack(const Arg *arg);
|
||||
@@ -448,7 +450,7 @@ static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
|
||||
-static char stext[256];
|
||||
+static char stext[512];
|
||||
static struct wl_event_source *status_event_source;
|
||||
|
||||
static const struct wlr_buffer_impl buffer_impl = {
|
||||
@@ -1519,11 +1521,8 @@ drawbar(Monitor *m)
|
||||
return;
|
||||
|
||||
/* draw status first so it can be overdrawn by tags later */
|
||||
- if (m == selmon) { /* status is only drawn on selected monitor */
|
||||
- drwl_setscheme(m->drw, colors[SchemeNorm]);
|
||||
- tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */
|
||||
- drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0);
|
||||
- }
|
||||
+ if (m == selmon) /* status is only drawn on selected monitor */
|
||||
+ tw = drawstatus(m);
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon != m)
|
||||
@@ -1577,6 +1576,88 @@ drawbars(void)
|
||||
drawbar(m);
|
||||
}
|
||||
|
||||
+int
|
||||
+drawstatus(Monitor *m)
|
||||
+{
|
||||
+ int x, tw, iw;
|
||||
+ char rstext[512] = "";
|
||||
+ char *p, *argstart, *argend, *itext;
|
||||
+ uint32_t scheme[3], *color;
|
||||
+
|
||||
+ /* calculate real width of stext */
|
||||
+ for (p = stext; *p; p++) {
|
||||
+ if (PREFIX(p, "^^")) {
|
||||
+ strncat(rstext, p, 2);
|
||||
+ p++;
|
||||
+ } else if (PREFIX(p, "^fg(") || PREFIX(p, "^bg(")) {
|
||||
+ argend = strchr(p, ')');
|
||||
+ if (!argend) { /* ignore this command */
|
||||
+ argstart = strchr(p, '(') + 1;
|
||||
+ strncat(rstext, p, argstart - p);
|
||||
+ p = argstart - 1;
|
||||
+ } else {
|
||||
+ p = argend;
|
||||
+ }
|
||||
+ } else {
|
||||
+ strncat(rstext, p, 1);
|
||||
+ }
|
||||
+ }
|
||||
+ tw = TEXTW(m, rstext) - m->lrpad;
|
||||
+
|
||||
+ x = m->b.width - tw;
|
||||
+ itext = stext;
|
||||
+ scheme[0] = colors[SchemeNorm][0];
|
||||
+ scheme[1] = colors[SchemeNorm][1];
|
||||
+ drwl_setscheme(m->drw, scheme);
|
||||
+ for (p = stext; *p; p++) {
|
||||
+ if (PREFIX(p, "^^")) {
|
||||
+ p++;
|
||||
+ } else if (PREFIX(p, "^fg(") || PREFIX(p, "^bg(")) {
|
||||
+ argstart = strchr(p, '(') + 1;
|
||||
+ argend = strchr(argstart, ')');
|
||||
+ if (!argend) { /* ignore this command */
|
||||
+ p = argstart - 1;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ *p = '\0';
|
||||
+ iw = TEXTW(m, itext) - m->lrpad;
|
||||
+ if (*itext) /* only draw text if there is something to draw */
|
||||
+ x = drwl_text(m->drw, x, 0, iw, m->b.height, 0, itext, 0);
|
||||
+ *p = '^';
|
||||
+
|
||||
+ if (PREFIX(p, "^fg("))
|
||||
+ color = &scheme[0];
|
||||
+ else
|
||||
+ color = &scheme[1];
|
||||
+
|
||||
+ if (argend != argstart) {
|
||||
+ *argend = '\0';
|
||||
+ *color = strtoul(argstart, NULL, 16);
|
||||
+ *color = *color << 8 | 0xff; /* add alpha channel */
|
||||
+ *argend = ')';
|
||||
+ } else {
|
||||
+ *color = 0; /* reset */
|
||||
+ }
|
||||
+
|
||||
+ /* reset color back to normal if none was provided */
|
||||
+ if (!scheme[0])
|
||||
+ scheme[0] = colors[SchemeNorm][0];
|
||||
+ if (!scheme[1])
|
||||
+ scheme[1] = colors[SchemeNorm][1];
|
||||
+
|
||||
+ itext = argend + 1;
|
||||
+ drwl_setscheme(m->drw, scheme);
|
||||
+ p = argend;
|
||||
+ }
|
||||
+ }
|
||||
+ iw = TEXTW(m, itext) - m->lrpad;
|
||||
+ if (*itext)
|
||||
+ drwl_text(m->drw, x, 0, iw, m->b.height, 0, itext, 0);
|
||||
+
|
||||
+ return tw;
|
||||
+}
|
||||
+
|
||||
void
|
||||
focusclient(Client *c, int lift)
|
||||
{
|
||||
--
|
||||
2.48.1
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
### Description
|
||||
|
||||
Add vertical and horizontal space between the [bar](/dwl/dwl-patches/wiki/bar) and the edge of the screen.
|
||||
|
||||
### Download
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/barpadding/barpadding.patch)
|
||||
|
||||
### Authors
|
||||
- [sewn](https://codeberg.org/sewn)
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
From f01cea73042155e856b2f41452724fe5c895eee4 Mon Sep 17 00:00:00 2001
|
||||
From: sewn <sewn@disroot.org>
|
||||
Date: Fri, 23 Aug 2024 09:59:03 +0300
|
||||
Subject: [PATCH] add vertical and horizontal spacing to bar
|
||||
|
||||
https://dwm.suckless.org/patches/barpadding/
|
||||
---
|
||||
config.def.h | 2 ++
|
||||
dwl.c | 14 +++++++-------
|
||||
2 files changed, 9 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 5d1dc2b..756b1ae 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -9,6 +9,8 @@ static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
+static const int vertpad = 10; /* vertical padding of bar */
|
||||
+static const int sidepad = 10; /* horizontal padding of bar */
|
||||
static const char *fonts[] = {"monospace:size=10"};
|
||||
static const float rootcolor[] = COLOR(0x000000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ece537a..380549a 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -598,8 +598,8 @@ arrangelayers(Monitor *m)
|
||||
return;
|
||||
|
||||
if (m->scene_buffer->node.enabled) {
|
||||
- usable_area.height -= m->b.real_height;
|
||||
- usable_area.y += topbar ? m->b.real_height : 0;
|
||||
+ usable_area.height -= m->b.real_height + vertpad;
|
||||
+ usable_area.y += topbar ? m->b.real_height + vertpad : 0;
|
||||
}
|
||||
|
||||
/* Arrange exclusive surfaces from top->bottom */
|
||||
@@ -750,7 +750,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
if (!c && !exclusive_focus &&
|
||||
(node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) &&
|
||||
(buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer) {
|
||||
- cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale;
|
||||
+ cx = (cursor->x - selmon->m.x - sidepad) * selmon->wlr_output->scale;
|
||||
do
|
||||
x += TEXTW(selmon, tags[i]);
|
||||
while (cx >= x && ++i < LENGTH(tags));
|
||||
@@ -1562,8 +1562,8 @@ drawbar(Monitor *m)
|
||||
|
||||
wlr_scene_buffer_set_dest_size(m->scene_buffer,
|
||||
m->b.real_width, m->b.real_height);
|
||||
- wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x,
|
||||
- m->m.y + (topbar ? 0 : m->m.height - m->b.real_height));
|
||||
+ wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x + sidepad,
|
||||
+ m->m.y + (topbar ? vertpad : m->m.height - m->b.real_height - vertpad));
|
||||
wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base);
|
||||
wlr_buffer_unlock(&buf->base);
|
||||
}
|
||||
@@ -3162,8 +3162,8 @@ updatebar(Monitor *m)
|
||||
char fontattrs[12];
|
||||
|
||||
wlr_output_transformed_resolution(m->wlr_output, &rw, &rh);
|
||||
- m->b.width = rw;
|
||||
- m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale);
|
||||
+ m->b.width = rw - (2 * sidepad);
|
||||
+ m->b.real_width = (int)((float)rw / m->wlr_output->scale) - (2 * sidepad);
|
||||
|
||||
wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0);
|
||||
|
||||
--
|
||||
2.46.0
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
### Description
|
||||
A homegrown port of dwm's _truecenteredtitle_ patch, with the addition of a config option to toggle its effects.<br>Requires [the bar patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/bar) to be applied beforehand.
|
||||
|
||||

|
||||
|
||||
### Download
|
||||
- [v0.7/v0.6](/dwl/dwl-patches/raw/branch/main/patches/bartruecenteredtitle/bartruecenteredtitle.patch)<br>Works on both v0.7 and v0.6.
|
||||
|
||||
### Author
|
||||
- [moonsabre](https://codeberg.org/moonsabre)
|
||||
- [sewn](https://codeberg.org/sewn)
|
||||
@@ -0,0 +1,46 @@
|
||||
From 17501c9f28226b1f332d6842be0d7f50ba618a29 Mon Sep 17 00:00:00 2001
|
||||
From: moonsabre <moonsabre@tuta.io>
|
||||
Date: Fri, 14 Mar 2025 16:04:25 -0700
|
||||
Subject: [PATCH] Bar title centering parameter.
|
||||
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 9 +++++++--
|
||||
2 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 5d1dc2b..8ac3a8b 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -9,6 +9,7 @@ static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
+static const int centeredtitle = 1; /* 1 means centered title */
|
||||
static const char *fonts[] = {"monospace:size=10"};
|
||||
static const float rootcolor[] = COLOR(0x000000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ece537a..9eb816b 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1551,9 +1551,14 @@ drawbar(Monitor *m)
|
||||
if ((w = m->b.width - tw - x) > m->b.height) {
|
||||
if (c) {
|
||||
drwl_setscheme(m->drw, colors[m == selmon ? SchemeSel : SchemeNorm]);
|
||||
- drwl_text(m->drw, x, 0, w, m->b.height, m->lrpad / 2, client_get_title(c), 0);
|
||||
+ tw = TEXTW(selmon, client_get_title(c));
|
||||
+ drwl_text(m->drw, x, 0, w, m->b.height,
|
||||
+ !centeredtitle || tw > w ? m->lrpad / 2 : (w - tw) / 2,
|
||||
+ client_get_title(c), 0);
|
||||
if (c && c->isfloating)
|
||||
- drwl_rect(m->drw, x + boxs, boxs, boxw, boxw, 0, 0);
|
||||
+ drwl_rect(m->drw,
|
||||
+ !centeredtitle || tw > w ? x + boxs : x + ((w - tw) / 2 - boxs * 8),
|
||||
+ boxs, boxw, boxw, 0, 0);
|
||||
} else {
|
||||
drwl_setscheme(m->drw, colors[SchemeNorm]);
|
||||
drwl_rect(m->drw, x, 0, w, m->b.height, 1, 1);
|
||||
--
|
||||
2.48.1
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
+48
@@ -0,0 +1,48 @@
|
||||
### Description
|
||||
This patch allows you to configure window resizing more flexibly.
|
||||
It introduces three options with the following possible values:
|
||||
|
||||
- warp_cursor:
|
||||
```
|
||||
0 - the mouse cursor remains in its original position at the start of the resize.
|
||||
1 - the cursor is automatically warped to the selected corner before resizing begins.
|
||||
```
|
||||
|
||||
- lock_cursor:
|
||||
```
|
||||
0 - the cursor can move freely during the resize.
|
||||
1 - the cursor position is completely frozen for the entire duration of the resize.
|
||||
```
|
||||
|
||||
- resize_corner:
|
||||
```
|
||||
0: top-left
|
||||
1: top-right
|
||||
2: bottom-left
|
||||
3: bottom-right
|
||||
4: selects the corner based on the current mouse quadrant
|
||||
```
|
||||
|
||||
### Demos
|
||||
All demos below use resize_corner = 4:
|
||||
| no warp + no lock | warp + lock |
|
||||
|-|-|
|
||||
|  |  |
|
||||
|
||||
| no warp + lock | warp + no lock |
|
||||
|-|-|
|
||||
|  |  |
|
||||
|
||||
### Known Issues (warp + lock)
|
||||
The combination of warp_cursor and lock_cursor is not recommended without outer gaps.
|
||||
If the selected resize corner aligns exactly with a screen corner, the cursor gets locked there and cannot be moved outward, so resizing only works inward.
|
||||
To resize outward, you must restart the resize operation with the cursor positioned somewhere away from the screen corner.
|
||||
This happens because the locked cursor cannot move past the screen edge, and therefore cannot generate a non-zero delta to resize outward.
|
||||
|
||||
On multihead setups, if the resize corner is near another screen, the window may switch monitors upon completion of the resize.
|
||||
|
||||
### Download
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/better-resize/better-resize-0.7.patch)
|
||||
|
||||
### Authors
|
||||
- [mmistika](https://codeberg.org/mmistika)
|
||||
@@ -0,0 +1,107 @@
|
||||
From f109808140cd6323b3a100663a10e048ae32e3a0 Mon Sep 17 00:00:00 2001
|
||||
From: mmistika <mistikasoft@gmail.com>
|
||||
Date: Thu, 17 Jul 2025 11:59:18 +0200
|
||||
Subject: [PATCH] Add configurable window resize
|
||||
|
||||
Signed-off-by: mmistika <mistikasoft@gmail.com>
|
||||
---
|
||||
config.def.h | 12 ++++++++++++
|
||||
dwl.c | 45 +++++++++++++++++++++++++++++++++++++--------
|
||||
2 files changed, 49 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..e404549 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -20,6 +20,18 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
|
||||
/* logging */
|
||||
static int log_level = WLR_ERROR;
|
||||
|
||||
+/* window resizing */
|
||||
+/* resize_corner:
|
||||
+ * 0: top-left
|
||||
+ * 1: top-right
|
||||
+ * 2: bottom-left
|
||||
+ * 3: bottom-right
|
||||
+ * 4: closest to the cursor
|
||||
+ */
|
||||
+static const int resize_corner = 4;
|
||||
+static const int warp_cursor = 1; /* 1: warp to corner, 0: don’t warp */
|
||||
+static const int lock_cursor = 0; /* 1: lock cursor, 0: don't lock */
|
||||
+
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
/* app_id title tags mask isfloating monitor */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index c717c1d..aacd074 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -407,6 +407,7 @@ static KeyboardGroup *kb_group;
|
||||
static unsigned int cursor_mode;
|
||||
static Client *grabc;
|
||||
static int grabcx, grabcy; /* client-relative */
|
||||
+static int rzcorner;
|
||||
|
||||
static struct wlr_output_layout *output_layout;
|
||||
static struct wlr_box sgeom;
|
||||
@@ -1873,8 +1874,24 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
.width = grabc->geom.width, .height = grabc->geom.height}, 1);
|
||||
return;
|
||||
} else if (cursor_mode == CurResize) {
|
||||
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
+ int cdx = (int)round(cursor->x) - grabcx;
|
||||
+ int cdy = (int)round(cursor->y) - grabcy;
|
||||
+
|
||||
+ const struct wlr_box box = {
|
||||
+ .x = grabc->geom.x + (rzcorner & 1 ? 0 : cdx),
|
||||
+ .y = grabc->geom.y + (rzcorner & 2 ? 0 : cdy),
|
||||
+ .width = grabc->geom.width + (rzcorner & 1 ? cdx : -cdx),
|
||||
+ .height = grabc->geom.height + (rzcorner & 2 ? cdy : -cdy)
|
||||
+ };
|
||||
+ resize(grabc, box, 1);
|
||||
+
|
||||
+ if (!lock_cursor) {
|
||||
+ grabcx += cdx;
|
||||
+ grabcy += cdy;
|
||||
+ } else {
|
||||
+ wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy);
|
||||
+ }
|
||||
+
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1920,12 +1937,24 @@ moveresize(const Arg *arg)
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
break;
|
||||
case CurResize:
|
||||
- /* Doesn't work for X11 output - the next absolute motion event
|
||||
- * returns the cursor to where it started */
|
||||
- wlr_cursor_warp_closest(cursor, NULL,
|
||||
- grabc->geom.x + grabc->geom.width,
|
||||
- grabc->geom.y + grabc->geom.height);
|
||||
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ const char *cursors[] = { "nw-resize", "ne-resize", "sw-resize", "se-resize" };
|
||||
+
|
||||
+ rzcorner = resize_corner;
|
||||
+ grabcx = (int)round(cursor->x);
|
||||
+ grabcy = (int)round(cursor->y);
|
||||
+
|
||||
+ if (rzcorner == 4)
|
||||
+ /* identify the closest corner index */
|
||||
+ rzcorner = (grabcx - grabc->geom.x < grabc->geom.x + grabc->geom.width - grabcx ? 0 : 1)
|
||||
+ + (grabcy - grabc->geom.y < grabc->geom.y + grabc->geom.height - grabcy ? 0 : 2);
|
||||
+
|
||||
+ if (warp_cursor) {
|
||||
+ grabcx = rzcorner & 1 ? grabc->geom.x + grabc->geom.width : grabc->geom.x;
|
||||
+ grabcy = rzcorner & 2 ? grabc->geom.y + grabc->geom.height : grabc->geom.y;
|
||||
+ wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy);
|
||||
+ }
|
||||
+
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, cursors[rzcorner]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.50.1
|
||||
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
### Description
|
||||
Adds 2 more borders to each side (top, bottom, left, right) of every window.
|
||||
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Preview</summary>
|
||||
<pre>
|
||||
With the following config:
|
||||
|
||||
```c
|
||||
static const unsigned int borderpx = 9; /* border pixel of windows */
|
||||
static const unsigned int borderspx = 3; /* width of the border that start from outside the windows */
|
||||
static const unsigned int borderepx = 3; /* width of the border that start from inside the windows */
|
||||
```
|
||||
|
||||
and `border_color_type` set to `BrdOriginal`:
|
||||
<img src="https://i.imgur.com/msead2K.png"/>
|
||||
|
||||
and `border_color_type` set to `BrdStart`:
|
||||
<img src="https://i.imgur.com/ssgPG36.png"/>
|
||||
|
||||
and `border_color_type` set to `BrdEnd`:
|
||||
<img src="https://i.imgur.com/i2Xtjy6.png"/>
|
||||
|
||||
and `border_color_type` set to `BrdStartEnd`:
|
||||
<img src="https://i.imgur.com/fnkitdR.png"/>
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/borders)
|
||||
- [2024-06-04](https://codeberg.org/dwl/dwl-patches/raw/commit/1a6825f2b8cd23044312c8040d0bf63ee7f85bc5/patches/borders/borders.patch)
|
||||
- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/borders/borders.patch)
|
||||
|
||||
### Authors
|
||||
- [wochap](https://codeberg.org/wochap)
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
From b12cfff672f0705d8259cf26b3a574faa5ca43ae Mon Sep 17 00:00:00 2001
|
||||
From: wochap <gean.marroquin@gmail.com>
|
||||
Date: Tue, 4 Jun 2024 16:02:25 -0500
|
||||
Subject: [PATCH] implement borders patch
|
||||
|
||||
tihs patch adds 2 extra borders relative to the client, they don't
|
||||
change the size of the client
|
||||
---
|
||||
client.h | 16 +++++++++++++---
|
||||
config.def.h | 8 ++++++++
|
||||
dwl.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
3 files changed, 70 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/client.h b/client.h
|
||||
index 800b867..33fd579 100644
|
||||
--- a/client.h
|
||||
+++ b/client.h
|
||||
@@ -325,11 +325,21 @@ client_send_close(Client *c)
|
||||
}
|
||||
|
||||
static inline void
|
||||
-client_set_border_color(Client *c, const float color[static 4])
|
||||
+client_set_border_color(Client *c, const float color[static 4], const float colors[static 4], const float colore[static 4])
|
||||
{
|
||||
int i;
|
||||
- for (i = 0; i < 4; i++)
|
||||
- wlr_scene_rect_set_color(c->border[i], color);
|
||||
+ for (i = 0; i < 4; i++) {
|
||||
+ if (border_color_type == BrdOriginal) {
|
||||
+ wlr_scene_rect_set_color(c->border[i], color);
|
||||
+ } else if (border_color_type == BrdStart) {
|
||||
+ wlr_scene_rect_set_color(c->borders[i], colors);
|
||||
+ } else if (border_color_type == BrdEnd) {
|
||||
+ wlr_scene_rect_set_color(c->bordere[i], colore);
|
||||
+ } else if (border_color_type == BrdStartEnd) {
|
||||
+ wlr_scene_rect_set_color(c->borders[i], colors);
|
||||
+ wlr_scene_rect_set_color(c->bordere[i], colore);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
static inline void
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8847e58..2d6bbe5 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -7,8 +7,16 @@
|
||||
static const int sloppyfocus = 1; /* focus follows mouse */
|
||||
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
+static const unsigned int borderspx = 0; /* width of the border that start from outside the windows */
|
||||
+static const unsigned int borderepx = 0; /* width of the border that start from inside the windows */
|
||||
+static const unsigned int borderspx_offset = 0; /* offset of the border that start from outside the windows */
|
||||
+static const unsigned int borderepx_negative_offset = 0; /* offset of the border that start from inside the windows */
|
||||
static const float rootcolor[] = COLOR(0x222222ff);
|
||||
static const float bordercolor[] = COLOR(0x444444ff);
|
||||
+static const float borderscolor[] = COLOR(0x444444ff); /* color of the border that start from outside the windows */
|
||||
+static const float borderecolor[] = COLOR(0x444444ff); /* color of the border that start from inside the windows */
|
||||
+static const int border_color_type = BrdOriginal; /* borders to be colored (focuscolor, urgentcolor) */
|
||||
+static const int borders_only_floating = 0;
|
||||
static const float focuscolor[] = COLOR(0x005577ff);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763df..303832a 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -86,6 +86,7 @@ enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock,
|
||||
enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
|
||||
NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
|
||||
#endif
|
||||
+enum { BrdOriginal, BrdStart, BrdEnd, BrdStartEnd };
|
||||
|
||||
typedef union {
|
||||
int i;
|
||||
@@ -109,6 +110,8 @@ typedef struct {
|
||||
Monitor *mon;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
+ struct wlr_scene_rect *borders[4]; /* top, bottom, left, right */
|
||||
+ struct wlr_scene_rect *bordere[4]; /* top, bottom, left, right */
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
@@ -136,6 +139,8 @@ typedef struct {
|
||||
struct wl_listener set_hints;
|
||||
#endif
|
||||
unsigned int bw;
|
||||
+ unsigned int bws;
|
||||
+ unsigned int bwe;
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
@@ -973,6 +978,8 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
c = xdg_surface->data = ecalloc(1, sizeof(*c));
|
||||
c->surface.xdg = xdg_surface;
|
||||
c->bw = borderpx;
|
||||
+ c->bws = borders_only_floating ? 0 : borderspx;
|
||||
+ c->bwe = borders_only_floating ? 0 : borderepx;
|
||||
|
||||
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
@@ -1268,7 +1275,7 @@ focusclient(Client *c, int lift)
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
if (!exclusive_focus && !seat->drag)
|
||||
- client_set_border_color(c, focuscolor);
|
||||
+ client_set_border_color(c, focuscolor, focuscolor, focuscolor);
|
||||
}
|
||||
|
||||
/* Deactivate old client if focus is changing */
|
||||
@@ -1285,7 +1292,7 @@ focusclient(Client *c, int lift)
|
||||
/* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg
|
||||
* and probably other clients */
|
||||
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
||||
- client_set_border_color(old_c, bordercolor);
|
||||
+ client_set_border_color(old_c, bordercolor, borderscolor, borderecolor);
|
||||
|
||||
client_activate_surface(old, 0);
|
||||
}
|
||||
@@ -1597,6 +1604,12 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->border[i] = wlr_scene_rect_create(c->scene, 0, 0,
|
||||
c->isurgent ? urgentcolor : bordercolor);
|
||||
c->border[i]->node.data = c;
|
||||
+
|
||||
+ c->borders[i] = wlr_scene_rect_create(c->scene, 0, 0, borderscolor);
|
||||
+ c->borders[i]->node.data = c;
|
||||
+
|
||||
+ c->bordere[i] = wlr_scene_rect_create(c->scene, 0, 0, borderecolor);
|
||||
+ c->bordere[i]->node.data = c;
|
||||
}
|
||||
|
||||
/* Initialize client geometry with room for border */
|
||||
@@ -1618,6 +1631,12 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
} else {
|
||||
applyrules(c);
|
||||
}
|
||||
+
|
||||
+ if (borders_only_floating) {
|
||||
+ c->bws = c->isfloating ? borderspx : 0;
|
||||
+ c->bwe = c->isfloating ? borderepx : 0;
|
||||
+ }
|
||||
+
|
||||
printstatus();
|
||||
|
||||
unset_fullscreen:
|
||||
@@ -2051,6 +2070,24 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
|
||||
+ wlr_scene_rect_set_size(c->borders[0], c->geom.width - 2 * borderspx_offset, c->bws);
|
||||
+ wlr_scene_rect_set_size(c->borders[1], c->geom.width - 2 * borderspx_offset, c->bws);
|
||||
+ wlr_scene_rect_set_size(c->borders[2], c->bws, c->geom.height - 2 * c->bws - 2 * borderspx_offset);
|
||||
+ wlr_scene_rect_set_size(c->borders[3], c->bws, c->geom.height - 2 * c->bws - 2 * borderspx_offset);
|
||||
+ wlr_scene_node_set_position(&c->borders[0]->node, borderspx_offset, borderspx_offset);
|
||||
+ wlr_scene_node_set_position(&c->borders[1]->node, borderspx_offset, c->geom.height - c->bws - borderspx_offset);
|
||||
+ wlr_scene_node_set_position(&c->borders[2]->node, borderspx_offset, c->bws + borderspx_offset);
|
||||
+ wlr_scene_node_set_position(&c->borders[3]->node, c->geom.width - c->bws - borderspx_offset, c->bws + borderspx_offset);
|
||||
+
|
||||
+ wlr_scene_rect_set_size(c->bordere[0], c->geom.width - (c->bw - c->bwe) * 2 + borderepx_negative_offset * 2, c->bwe);
|
||||
+ wlr_scene_rect_set_size(c->bordere[1], c->geom.width - (c->bw - c->bwe) * 2 + borderepx_negative_offset * 2, c->bwe);
|
||||
+ wlr_scene_rect_set_size(c->bordere[2], c->bwe, c->geom.height - 2 * c->bw + 2 * borderepx_negative_offset);
|
||||
+ wlr_scene_rect_set_size(c->bordere[3], c->bwe, c->geom.height - 2 * c->bw + 2 * borderepx_negative_offset);
|
||||
+ wlr_scene_node_set_position(&c->bordere[0]->node, c->bw - c->bwe - borderepx_negative_offset, c->bw - c->bwe - borderepx_negative_offset);
|
||||
+ wlr_scene_node_set_position(&c->bordere[1]->node, c->bw - c->bwe - borderepx_negative_offset, c->geom.height - c->bw + borderepx_negative_offset);
|
||||
+ wlr_scene_node_set_position(&c->bordere[2]->node, c->bw - c->bwe - borderepx_negative_offset, c->bw - borderepx_negative_offset);
|
||||
+ wlr_scene_node_set_position(&c->bordere[3]->node, c->geom.width - c->bw + borderepx_negative_offset, c->bw - borderepx_negative_offset);
|
||||
+
|
||||
/* this is a no-op if size hasn't changed */
|
||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
c->geom.height - 2 * c->bw);
|
||||
@@ -2151,6 +2188,12 @@ setfloating(Client *c, int floating)
|
||||
c->isfloating = floating;
|
||||
if (!c->mon)
|
||||
return;
|
||||
+
|
||||
+ if (borders_only_floating) {
|
||||
+ c->bws = c->isfloating ? borderspx : 0;
|
||||
+ c->bwe = c->isfloating ? borderepx : 0;
|
||||
+ }
|
||||
+
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen ||
|
||||
(p && p->isfullscreen) ? LyrFS
|
||||
: c->isfloating ? LyrFloat : LyrTile]);
|
||||
@@ -2165,6 +2208,8 @@ setfullscreen(Client *c, int fullscreen)
|
||||
if (!c->mon)
|
||||
return;
|
||||
c->bw = fullscreen ? 0 : borderpx;
|
||||
+ c->bws = fullscreen ? 0 : borderspx;
|
||||
+ c->bwe = fullscreen ? 0 : borderepx;
|
||||
client_set_fullscreen(c, fullscreen);
|
||||
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen
|
||||
? LyrFS : c->isfloating ? LyrFloat : LyrTile]);
|
||||
@@ -2819,7 +2864,7 @@ urgent(struct wl_listener *listener, void *data)
|
||||
printstatus();
|
||||
|
||||
if (client_surface(c)->mapped)
|
||||
- client_set_border_color(c, urgentcolor);
|
||||
+ client_set_border_color(c, urgentcolor, urgentcolor, urgentcolor);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3023,7 +3068,7 @@ sethints(struct wl_listener *listener, void *data)
|
||||
printstatus();
|
||||
|
||||
if (c->isurgent && surface && surface->mapped)
|
||||
- client_set_border_color(c, urgentcolor);
|
||||
+ client_set_border_color(c, urgentcolor, urgentcolor, urgentcolor);
|
||||
}
|
||||
|
||||
void
|
||||
--
|
||||
2.44.1
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
### Description
|
||||
bstack and bstackhoriz are two stack layouts for dwl.
|
||||
### Scheme
|
||||
```
|
||||
bstack (TTT) bstackhoriz (===)
|
||||
+-----------------+ +-----------------+
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
+-----+-----+-----+ +-----------------+
|
||||
| | | | +-----------------+
|
||||
| | | | +-----------------+
|
||||
+-----+-----+-----+ +-----------------+
|
||||
```
|
||||
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.6-b/bottomstack)
|
||||
- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/20de07dc8759200c8a4c9651475acb331d245890/patches/bottomstack/bottomstack.patch)
|
||||
- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/0f4e40fee49d1b8b430778e241b29496ae3b3b70/bottomstack/bottomstack.patch)
|
||||
- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/5368aa392c7ebf8d7d24c232b80cfae1be457d41/bottomstack/bottomstack.patch)
|
||||
|
||||
### Authors
|
||||
- [wochap](https://codeberg.org/wochap)
|
||||
- [DanielMowitz](https://github.com/DanielMowitz)
|
||||
- [Abanoub8](https://github.com/Abanoub8)
|
||||
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
From b352fb08f40b1ee2d8c4748be4922df711e3aaa9 Mon Sep 17 00:00:00 2001
|
||||
From: wochap <gean.marroquin@gmail.com>
|
||||
Date: Fri, 5 Jul 2024 10:44:29 -0500
|
||||
Subject: [PATCH] implement bottomstack
|
||||
|
||||
---
|
||||
config.def.h | 4 +++
|
||||
dwl.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 88 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..5aac3e9 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -34,6 +34,8 @@ static const Layout layouts[] = {
|
||||
{ "[]=", tile },
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
+ { "TTT", bstack },
|
||||
+ { "===", bstackhoriz },
|
||||
};
|
||||
|
||||
/* monitors */
|
||||
@@ -139,6 +141,8 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
+ { MODKEY, XKB_KEY_u, setlayout, {.v = &layouts[3]} },
|
||||
+ { MODKEY, XKB_KEY_o, setlayout, {.v = &layouts[4]} },
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index dc0437e..5648d5f 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -57,6 +57,7 @@
|
||||
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||
#include <wlr/types/wlr_xdg_output_v1.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
+#include <wlr/util/box.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/util/region.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
@@ -351,6 +352,8 @@ static Monitor *xytomon(double x, double y);
|
||||
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||
static void zoom(const Arg *arg);
|
||||
+static void bstack(Monitor *m);
|
||||
+static void bstackhoriz(Monitor *m);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
@@ -3160,3 +3163,84 @@ main(int argc, char *argv[])
|
||||
usage:
|
||||
die("Usage: %s [-v] [-d] [-s startup command]", argv[0]);
|
||||
}
|
||||
+
|
||||
+static void
|
||||
+bstack(Monitor *m)
|
||||
+{
|
||||
+ int w, h, mh, mx, tx, ty, tw;
|
||||
+ int i, n = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating)
|
||||
+ n++;
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (n > m->nmaster) {
|
||||
+ mh = (int)round(m->nmaster ? m->mfact * m->w.height : 0);
|
||||
+ tw = m->w.width / (n - m->nmaster);
|
||||
+ ty = m->w.y + mh;
|
||||
+ } else {
|
||||
+ mh = m->w.height;
|
||||
+ tw = m->w.width;
|
||||
+ ty = m->w.y;
|
||||
+ }
|
||||
+
|
||||
+ i = mx = 0;
|
||||
+ tx = m-> w.x;
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (!VISIBLEON(c, m) || c->isfloating)
|
||||
+ continue;
|
||||
+ if (i < m->nmaster) {
|
||||
+ w = (m->w.width - mx) / (MIN(n, m->nmaster) - i);
|
||||
+ resize(c, (struct wlr_box) { .x = m->w.x + mx, .y = m->w.y, .width = w, .height = mh }, 0);
|
||||
+ mx += c->geom.width;
|
||||
+ } else {
|
||||
+ h = m->w.height - mh;
|
||||
+ resize(c, (struct wlr_box) { .x = tx, .y = ty, .width = tw, .height = h }, 0);
|
||||
+ if (tw != m->w.width)
|
||||
+ tx += c->geom.width;
|
||||
+ }
|
||||
+ i++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+bstackhoriz(Monitor *m) {
|
||||
+ int w, mh, mx, tx, ty, th;
|
||||
+ int i, n = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating)
|
||||
+ n ++;
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (n > m->nmaster) {
|
||||
+ mh = (int)round(m->nmaster ? m->mfact * m->w.height : 0);
|
||||
+ th = (m->w.height - mh) / (n - m->nmaster);
|
||||
+ ty = m->w.y + mh;
|
||||
+ } else {
|
||||
+ th = mh = m->w.height;
|
||||
+ ty = m->w.y;
|
||||
+ }
|
||||
+
|
||||
+ i = mx = 0;
|
||||
+ tx = m-> w.x;
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (!VISIBLEON(c,m) || c->isfloating)
|
||||
+ continue;
|
||||
+ if (i < m->nmaster) {
|
||||
+ w = (m->w.width - mx) / (MIN(n, m->nmaster) - i);
|
||||
+ resize(c, (struct wlr_box) { .x = m->w.x + mx, .y = m->w.y, .width = w, .height = mh }, 0);
|
||||
+ mx += c->geom.width;
|
||||
+ } else {
|
||||
+ resize(c, (struct wlr_box) { .x = tx, .y = ty, .width = m->w.width, .height = th }, 0);
|
||||
+ if (th != m->w.height)
|
||||
+ ty += c->geom.height;
|
||||
+ }
|
||||
+ i++;
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.45.1
|
||||
Executable
+103
@@ -0,0 +1,103 @@
|
||||
### Description
|
||||
|
||||
# btrtile — A Focus-Driven Tiling Layout
|
||||
|
||||
It provides a focus-driven, mouse- and keyboard-friendly tiling layout that grants you granular control over how clients are placed and resized.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
# Why btrtile
|
||||
|
||||
While dwl’s patches folder is full of different layouts, I couldn't find suitable layout that would work well with my workflow and single ultrawide monitor setup. btrtile aims to solve that by introducing a layout strategy that splits clients according to user focus and pointer position.
|
||||
|
||||
---
|
||||
|
||||
# Features
|
||||
|
||||
- **Combined Tiling and Management**
|
||||
Combines tiling layout and management of clients under one patchset.
|
||||
|
||||
- **Focus-Driven Splits**
|
||||
When you add a new client, btrtile checks where your pointer is relative to the focused client’s geometry.
|
||||
- If the pointer is on the left half (for a horizontally large client), the new client spawns on the left side, and vice versa.
|
||||
- By default, new splits are 50/50.
|
||||
|
||||
- **Adaptive Splitting**
|
||||
- If the area to be split is wider than its height, btrtile does a vertical split.
|
||||
- Otherwise, it does a horizontal split.
|
||||
|
||||
- **Keyboard and Mouse Driven**
|
||||
- Supports keyboard-based commands for quick ratio adjustments and client swapping.
|
||||
- Mouse-based resizing and moving are integrated for more intuitive manipulation.
|
||||
|
||||
---
|
||||
|
||||
# How It Works
|
||||
|
||||
btrtile organizes clients using a binary tree data structure that represents splits either vertically or horizontally.
|
||||
|
||||
When a new client appears:
|
||||
1. **Focused Client Detection**
|
||||
btrtile checks your pointer location to find which client (if any) you’re interacting with.
|
||||
2. **Split Creation**
|
||||
- If there’s a focused client, btrtile creates a split node around it, placing the new client on the side where your pointer is.
|
||||
|
||||
3. **Ratio Management**
|
||||
Each split node has a `split_ratio` (defaulting to 0.5). This ratio defines how much space is allocated to each child node. You can adjust this ratio using keyboard or mouse actions.
|
||||
|
||||
---
|
||||
|
||||
# What It Doesn’t Handle
|
||||
|
||||
- **Suckless philosophy**
|
||||
- Yea, it's a bloat. I tried to hide the suck inside a single file as much I could. While this approach is not ideal, it's how it's at least for now.
|
||||
|
||||
---
|
||||
|
||||
# Configuring btrtile
|
||||
|
||||
btrtile adds couple variables to config.h to fine tune the mouse resizing of tiled clients.
|
||||
|
||||
1. **resize_factor**
|
||||
- A multiplier to transfer pointer movement to client weight ratio. Depends heavily on mouse sensivity.
|
||||
Defaults to 0.0002f.
|
||||
|
||||
2. **resize_interval_ms**
|
||||
- A time based resize call limiter. Depends on framerate and screen refresh rate.
|
||||
Defaults to 16ms. (~60 resize updates per second)
|
||||
|
||||
Fine tune these values to find the best values for your setup, smoother resizing can significally increase cpu overhead.
|
||||
If mouse resizing feels sluggish, you can try compiling dwl with more aggressive optimization flags like -O2/-O3.
|
||||
|
||||
---
|
||||
|
||||
# Patch recommendations
|
||||
|
||||
1. **Patches that I use with my btrtile**
|
||||
|
||||
- [focusdir](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/focusdir)
|
||||
Great patch to move focus between clients.
|
||||
|
||||
- [rotatetags](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/rotatetags)
|
||||
Good patch to rotate the view or shift clients between tags.
|
||||
|
||||
- [warpcursor](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/warpcursor)
|
||||
Moves cursor location to focused client.
|
||||
|
||||
- [pertag](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/pertag)
|
||||
Allows each tag to have individual layout setups.
|
||||
|
||||
- [gaps](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/gaps)
|
||||
Add gaps between clients.
|
||||
|
||||
---
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/julmajustus/dwl/src/branch/btrtile-dev)
|
||||
- [0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/btrtile/btrtile-v0.7.patch)
|
||||
- [0.7 WITH gaps](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/btrtile/btrtile-v0.7-gaps.patch)
|
||||
|
||||
### Authors
|
||||
- [julmajustus](https://codeberg.org/julmajustus)
|
||||
+922
@@ -0,0 +1,922 @@
|
||||
From 858ef20d36c2d5e6a23a69b3b5909a80fab05f97 Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Thu, 13 Feb 2025 23:25:20 +0200
|
||||
Subject: [PATCH] btrtile-gaps with multi-tag support
|
||||
|
||||
---
|
||||
btrtile.c | 582 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
config.def.h | 12 ++
|
||||
dwl.c | 152 +++++++++++---
|
||||
3 files changed, 717 insertions(+), 29 deletions(-)
|
||||
create mode 100644 btrtile.c
|
||||
|
||||
diff --git a/btrtile.c b/btrtile.c
|
||||
new file mode 100644
|
||||
index 0000000..650cab5
|
||||
--- /dev/null
|
||||
+++ b/btrtile.c
|
||||
@@ -0,0 +1,582 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* */
|
||||
+/* ::: :::::::: */
|
||||
+/* btrtile.c :+: :+: :+: */
|
||||
+/* +:+ +:+ +:+ */
|
||||
+/* By: jmakkone <jmakkone@student.hive.fi> +#+ +:+ +#+ */
|
||||
+/* +#+#+#+#+#+ +#+ */
|
||||
+/* Created: 2024/12/15 00:26:07 by jmakkone #+# #+# */
|
||||
+/* Updated: 2025/02/13 23:25:03 by jmakkone ### ########.fr */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
+typedef struct LayoutNode {
|
||||
+ unsigned int is_client_node;
|
||||
+ unsigned int is_split_vertically;
|
||||
+ float split_ratio;
|
||||
+ struct LayoutNode *left;
|
||||
+ struct LayoutNode *right;
|
||||
+ struct LayoutNode *split_node;
|
||||
+ Client *client;
|
||||
+} LayoutNode;
|
||||
+
|
||||
+static void apply_layout(Monitor *m, LayoutNode *node,
|
||||
+ struct wlr_box area, unsigned int is_root);
|
||||
+static void btrtile(Monitor *m);
|
||||
+static LayoutNode *create_client_node(Client *c);
|
||||
+static LayoutNode *create_split_node(unsigned int is_split_vertically,
|
||||
+ LayoutNode *left, LayoutNode *right);
|
||||
+static void destroy_node(LayoutNode *node);
|
||||
+static void destroy_tree(Monitor *m);
|
||||
+static LayoutNode *find_client_node(LayoutNode *node, Client *c);
|
||||
+static LayoutNode *find_suitable_split(LayoutNode *start, unsigned int need_vert);
|
||||
+static void init_tree(Monitor *m);
|
||||
+static void insert_client(Monitor *m, Client *focused_client, Client *new_client);
|
||||
+static LayoutNode *remove_client_node(LayoutNode *node, Client *c);
|
||||
+static void remove_client(Monitor *m, Client *c);
|
||||
+static void setratio_h(const Arg *arg);
|
||||
+static void setratio_v(const Arg *arg);
|
||||
+static void swapclients(const Arg *arg);
|
||||
+static unsigned int visible_count(LayoutNode *node, Monitor *m);
|
||||
+static Client *xytoclient(double x, double y);
|
||||
+
|
||||
+static int resizing_from_mouse = 0;
|
||||
+static double resize_last_update_x, resize_last_update_y;
|
||||
+static uint32_t last_resize_time = 0;
|
||||
+
|
||||
+void
|
||||
+apply_layout(Monitor *m, LayoutNode *node,
|
||||
+ struct wlr_box area, unsigned int is_root)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ float ratio;
|
||||
+ unsigned int left_count, right_count, mid, e = m->gaps;
|
||||
+ struct wlr_box left_area, right_area;
|
||||
+
|
||||
+ if (!node)
|
||||
+ return;
|
||||
+
|
||||
+ if (is_root && e) {
|
||||
+ area.x += gappx;
|
||||
+ area.y += gappx;
|
||||
+ area.width -= 2 * gappx;
|
||||
+ area.height -= 2 * gappx;
|
||||
+ }
|
||||
+
|
||||
+ /* If this node is a client node, check if it is visible. */
|
||||
+ if (node->is_client_node) {
|
||||
+ c = node->client;
|
||||
+ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ return;
|
||||
+ resize(c, area, 0);
|
||||
+ c->old_geom = area;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* For a split node, we see how many visible children are on each side: */
|
||||
+ left_count = visible_count(node->left, m);
|
||||
+ right_count = visible_count(node->right, m);
|
||||
+
|
||||
+ if (left_count == 0 && right_count == 0) {
|
||||
+ return;
|
||||
+ } else if (left_count > 0 && right_count == 0) {
|
||||
+ apply_layout(m, node->left, area, 0);
|
||||
+ return;
|
||||
+ } else if (left_count == 0 && right_count > 0) {
|
||||
+ apply_layout(m, node->right, area, 0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* If we’re here, we have visible clients in both subtrees. */
|
||||
+ ratio = node->split_ratio;
|
||||
+ if (ratio < 0.05f)
|
||||
+ ratio = 0.05f;
|
||||
+ if (ratio > 0.95f)
|
||||
+ ratio = 0.95f;
|
||||
+
|
||||
+ memset(&left_area, 0, sizeof(left_area));
|
||||
+ memset(&right_area, 0, sizeof(right_area));
|
||||
+
|
||||
+ if (node->is_split_vertically) {
|
||||
+ mid = (unsigned int)(area.width * ratio);
|
||||
+ left_area.x = area.x;
|
||||
+ left_area.y = area.y;
|
||||
+ left_area.width = mid;
|
||||
+ left_area.height = area.height;
|
||||
+
|
||||
+ right_area.x = area.x + mid;
|
||||
+ right_area.y = area.y;
|
||||
+ right_area.width = area.width - mid;
|
||||
+ right_area.height = area.height;
|
||||
+
|
||||
+ if (e) {
|
||||
+ left_area.width -= gappx / 2;
|
||||
+ right_area.x += gappx / 2;
|
||||
+ right_area.width -= gappx / 2;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* horizontal split */
|
||||
+ mid = (unsigned int)(area.height * ratio);
|
||||
+ left_area.x = area.x;
|
||||
+ left_area.y = area.y;
|
||||
+ left_area.width = area.width;
|
||||
+ left_area.height = mid;
|
||||
+
|
||||
+ right_area.x = area.x;
|
||||
+ right_area.y = area.y + mid;
|
||||
+ right_area.width = area.width;
|
||||
+ right_area.height= area.height - mid;
|
||||
+
|
||||
+ if (e) {
|
||||
+ left_area.height -= gappx / 2;
|
||||
+ right_area.y += gappx / 2;
|
||||
+ right_area.height -= gappx / 2;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ apply_layout(m, node->left, left_area, 0);
|
||||
+ apply_layout(m, node->right, right_area, 0);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+btrtile(Monitor *m)
|
||||
+{
|
||||
+ Client *c, *focused = NULL;
|
||||
+ int n = 0;
|
||||
+ LayoutNode *found;
|
||||
+ struct wlr_box full_area;
|
||||
+
|
||||
+ if (!m || !m->root)
|
||||
+ return;
|
||||
+
|
||||
+ /* Remove non tiled clients from tree. */
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (c->mon == m && !c->isfloating && !c->isfullscreen) {
|
||||
+ } else {
|
||||
+ remove_client(m, c);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If no client is found under cursor, fallback to focustop(m) */
|
||||
+ if (!(focused = xytoclient(cursor->x, cursor->y)))
|
||||
+ focused = focustop(m);
|
||||
+
|
||||
+ /* Insert visible clients that are not part of the tree. */
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen && c->mon == m) {
|
||||
+ found = find_client_node(m->root, c);
|
||||
+ if (!found) {
|
||||
+ insert_client(m, focused, c);
|
||||
+ }
|
||||
+ n++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ full_area = m->w;
|
||||
+ apply_layout(m, m->root, full_area, 1);
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+create_client_node(Client *c)
|
||||
+{
|
||||
+ LayoutNode *node = calloc(1, sizeof(LayoutNode));
|
||||
+
|
||||
+ if (!node)
|
||||
+ return NULL;
|
||||
+ node->is_client_node = 1;
|
||||
+ node->split_ratio = 0.5f;
|
||||
+ node->client = c;
|
||||
+ return node;
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+create_split_node(unsigned int is_split_vertically,
|
||||
+ LayoutNode *left, LayoutNode *right)
|
||||
+{
|
||||
+ LayoutNode *node = calloc(1, sizeof(LayoutNode));
|
||||
+
|
||||
+ if (!node)
|
||||
+ return NULL;
|
||||
+ node->is_client_node = 0;
|
||||
+ node->split_ratio = 0.5f;
|
||||
+ node->is_split_vertically = is_split_vertically;
|
||||
+ node->left = left;
|
||||
+ node->right = right;
|
||||
+ if (left)
|
||||
+ left->split_node = node;
|
||||
+ if (right)
|
||||
+ right->split_node = node;
|
||||
+ return node;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+destroy_node(LayoutNode *node)
|
||||
+{
|
||||
+ if (!node)
|
||||
+ return;
|
||||
+ if (!node->is_client_node) {
|
||||
+ destroy_node(node->left);
|
||||
+ destroy_node(node->right);
|
||||
+ }
|
||||
+ free(node);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+destroy_tree(Monitor *m)
|
||||
+{
|
||||
+ if (!m || !m->root)
|
||||
+ return;
|
||||
+ destroy_node(m->root);
|
||||
+ m->root = NULL;
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+find_client_node(LayoutNode *node, Client *c)
|
||||
+{
|
||||
+ LayoutNode *res;
|
||||
+
|
||||
+ if (!node || !c)
|
||||
+ return NULL;
|
||||
+ if (node->is_client_node) {
|
||||
+ return (node->client == c) ? node : NULL;
|
||||
+ }
|
||||
+ res = find_client_node(node->left, c);
|
||||
+ return res ? res : find_client_node(node->right, c);
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+find_suitable_split(LayoutNode *start_node, unsigned int need_vertical)
|
||||
+{
|
||||
+ LayoutNode *n = start_node;
|
||||
+ /* if we started from a client node, jump to its parent: */
|
||||
+ if (n && n->is_client_node)
|
||||
+ n = n->split_node;
|
||||
+
|
||||
+ while (n) {
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical &&
|
||||
+ visible_count(n->left, selmon) > 0 && visible_count(n->right, selmon) > 0)
|
||||
+ return n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+init_tree(Monitor *m)
|
||||
+{
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+ m->root = calloc(1, sizeof(LayoutNode));
|
||||
+ if (!m->root)
|
||||
+ m->root = NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+insert_client(Monitor *m, Client *focused_client, Client *new_client)
|
||||
+{
|
||||
+ Client *old_client;
|
||||
+ LayoutNode **root = &m->root, *old_root,
|
||||
+ *focused_node, *new_client_node, *old_client_node;
|
||||
+ unsigned int wider, mid_x, mid_y;
|
||||
+
|
||||
+ /* If no root , new client becomes the root. */
|
||||
+ if (!*root) {
|
||||
+ *root = create_client_node(new_client);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Find the focused_client node,
|
||||
+ * if not found split the root. */
|
||||
+ focused_node = focused_client ?
|
||||
+ find_client_node(*root, focused_client) : NULL;
|
||||
+ if (!focused_node) {
|
||||
+ old_root = *root;
|
||||
+ new_client_node = create_client_node(new_client);
|
||||
+ *root = create_split_node(1, old_root, new_client_node);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Turn focused node from a client node into a split node,
|
||||
+ * and attach old_client + new_client. */
|
||||
+ old_client = focused_node->client;
|
||||
+ old_client_node = create_client_node(old_client);
|
||||
+ new_client_node = create_client_node(new_client);
|
||||
+
|
||||
+ /* Decide split direction. */
|
||||
+ wider = (focused_client->geom.width >= focused_client->geom.height);
|
||||
+ focused_node->is_client_node = 0;
|
||||
+ focused_node->client = NULL;
|
||||
+ focused_node->is_split_vertically = (wider ? 1 : 0);
|
||||
+
|
||||
+ /* Pick new_client side depending on the cursor position. */
|
||||
+ mid_x = focused_client->geom.x + focused_client->geom.width / 2;
|
||||
+ mid_y = focused_client->geom.y + focused_client->geom.height / 2;
|
||||
+
|
||||
+ if (wider) {
|
||||
+ /* vertical split => left vs right */
|
||||
+ if (cursor->x <= mid_x) {
|
||||
+ focused_node->left = new_client_node;
|
||||
+ focused_node->right = old_client_node;
|
||||
+ } else {
|
||||
+ focused_node->left = old_client_node;
|
||||
+ focused_node->right = new_client_node;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* horizontal split => top vs bottom */
|
||||
+ if (cursor->y <= mid_y) {
|
||||
+ focused_node->left = new_client_node;
|
||||
+ focused_node->right = old_client_node;
|
||||
+ } else {
|
||||
+ focused_node->left = old_client_node;
|
||||
+ focused_node->right = new_client_node;
|
||||
+ }
|
||||
+ }
|
||||
+ old_client_node->split_node = focused_node;
|
||||
+ new_client_node->split_node = focused_node;
|
||||
+ focused_node->split_ratio = 0.5f;
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+remove_client_node(LayoutNode *node, Client *c)
|
||||
+{
|
||||
+ LayoutNode *tmp;
|
||||
+ if (!node)
|
||||
+ return NULL;
|
||||
+ if (node->is_client_node) {
|
||||
+ /* If this client_node is the client we're removing,
|
||||
+ * return NULL to remove it */
|
||||
+ if (node->client == c) {
|
||||
+ free(node);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ return node;
|
||||
+ }
|
||||
+
|
||||
+ node->left = remove_client_node(node->left, c);
|
||||
+ node->right = remove_client_node(node->right, c);
|
||||
+
|
||||
+ /* If one of the client node is NULL after removal and the other is not,
|
||||
+ * we "lift" the other client node up to replace this split node. */
|
||||
+ if (!node->left && node->right) {
|
||||
+ tmp = node->right;
|
||||
+
|
||||
+ /* Save pointer to split node */
|
||||
+ if (tmp)
|
||||
+ tmp->split_node = node->split_node;
|
||||
+
|
||||
+ free(node);
|
||||
+ return tmp;
|
||||
+ }
|
||||
+
|
||||
+ if (!node->right && node->left) {
|
||||
+ tmp = node->left;
|
||||
+
|
||||
+ /* Save pointer to split node */
|
||||
+ if (tmp)
|
||||
+ tmp->split_node = node->split_node;
|
||||
+
|
||||
+ free(node);
|
||||
+ return tmp;
|
||||
+ }
|
||||
+
|
||||
+ /* If both children exist or both are NULL (empty tree),
|
||||
+ * return node as is. */
|
||||
+ return node;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+remove_client(Monitor *m, Client *c)
|
||||
+{
|
||||
+ if (!m->root || !c)
|
||||
+ return;
|
||||
+ m->root = remove_client_node(m->root, c);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 1);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f;
|
||||
+ if (new_ratio < 0.05f)
|
||||
+ new_ratio = 0.05f;
|
||||
+ if (new_ratio > 0.95f)
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_v(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 0);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f;
|
||||
+ if (new_ratio < 0.05f)
|
||||
+ new_ratio = 0.05f;
|
||||
+ if (new_ratio > 0.95f)
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void swapclients(const Arg *arg) {
|
||||
+ Client *c, *tmp, *target = NULL, *sel = focustop(selmon);
|
||||
+ LayoutNode *sel_node, *target_node;
|
||||
+ int closest_dist = INT_MAX, dist, sel_center_x, sel_center_y,
|
||||
+ cand_center_x, cand_center_y;
|
||||
+
|
||||
+ if (!sel || sel->isfullscreen ||
|
||||
+ !selmon->root || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+
|
||||
+ /* Get the center coordinates of the selected client */
|
||||
+ sel_center_x = sel->geom.x + sel->geom.width / 2;
|
||||
+ sel_center_y = sel->geom.y + sel->geom.height / 2;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (!VISIBLEON(c, selmon) || c->isfloating || c->isfullscreen || c == sel)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Get the center of candidate client */
|
||||
+ cand_center_x = c->geom.x + c->geom.width / 2;
|
||||
+ cand_center_y = c->geom.y + c->geom.height / 2;
|
||||
+
|
||||
+ /* Check that the candidate lies in the requested direction. */
|
||||
+ switch (arg->ui) {
|
||||
+ case 0:
|
||||
+ if (cand_center_x >= sel_center_x)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ if (cand_center_x <= sel_center_x)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ if (cand_center_y >= sel_center_y)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ if (cand_center_y <= sel_center_y)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ default:
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Get distance between the centers */
|
||||
+ dist = abs(sel_center_x - cand_center_x) + abs(sel_center_y - cand_center_y);
|
||||
+ if (dist < closest_dist) {
|
||||
+ closest_dist = dist;
|
||||
+ target = c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If target is found, swap the two clients’ positions in the layout tree */
|
||||
+ if (target) {
|
||||
+ sel_node = find_client_node(selmon->root, sel);
|
||||
+ target_node = find_client_node(selmon->root, target);
|
||||
+ if (sel_node && target_node) {
|
||||
+ tmp = sel_node->client;
|
||||
+ sel_node->client = target_node->client;
|
||||
+ target_node->client = tmp;
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+unsigned int
|
||||
+visible_count(LayoutNode *node, Monitor *m)
|
||||
+{
|
||||
+ Client *c;
|
||||
+
|
||||
+ if (!node)
|
||||
+ return 0;
|
||||
+ /* Check if this client is visible. */
|
||||
+ if (node->is_client_node) {
|
||||
+ c = node->client;
|
||||
+ if (c && VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
|
||||
+ return 1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /* Else it’s a split node. */
|
||||
+ return visible_count(node->left, m) + visible_count(node->right, m);
|
||||
+}
|
||||
+
|
||||
+Client *
|
||||
+xytoclient(double x, double y) {
|
||||
+ Client *c, *closest = NULL;
|
||||
+ double dist, mindist = INT_MAX, dx, dy;
|
||||
+
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen &&
|
||||
+ x >= c->geom.x && x <= (c->geom.x + c->geom.width) &&
|
||||
+ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If no client was found at cursor position fallback to closest. */
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) {
|
||||
+ dx = 0, dy = 0;
|
||||
+
|
||||
+ if (x < c->geom.x)
|
||||
+ dx = c->geom.x - x;
|
||||
+ else if (x > (c->geom.x + c->geom.width))
|
||||
+ dx = x - (c->geom.x + c->geom.width);
|
||||
+
|
||||
+ if (y < c->geom.y)
|
||||
+ dy = c->geom.y - y;
|
||||
+ else if (y > (c->geom.y + c->geom.height))
|
||||
+ dy = y - (c->geom.y + c->geom.height);
|
||||
+
|
||||
+ dist = sqrt(dx * dx + dy * dy);
|
||||
+ if (dist < mindist) {
|
||||
+ mindist = dist;
|
||||
+ closest = c;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return closest;
|
||||
+}
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..92f3ad6 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -13,7 +13,10 @@ static const float focuscolor[] = COLOR(0x005577ff);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
+static const float resize_factor = 0.0002f; /* Resize multiplier for mouse resizing, depends on mouse sensivity. */
|
||||
+static const uint32_t resize_interval_ms = 16; /* Resize interval depends on framerate and screen refresh rate. */
|
||||
|
||||
+enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN };
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
#define TAGCOUNT (9)
|
||||
|
||||
@@ -31,6 +34,7 @@ static const Rule rules[] = {
|
||||
/* layout(s) */
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
+ { "|w|", btrtile },
|
||||
{ "[]=", tile },
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
@@ -148,6 +152,14 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapclients, {.i = DIR_UP} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapclients, {.i = DIR_DOWN} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapclients, {.i = DIR_RIGHT} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapclients, {.i = DIR_LEFT} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, setratio_h, {.f = +0.025f} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, setratio_h, {.f = -0.025f} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Up, setratio_v, {.f = -0.025f} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Down, setratio_v, {.f = +0.025f} },
|
||||
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index a2711f6..e49a061 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* See LICENSE file for copyright and license details.
|
||||
*/
|
||||
+#include <limits.h>
|
||||
#include <getopt.h>
|
||||
#include <libinput.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
@@ -103,6 +104,7 @@ typedef struct {
|
||||
const Arg arg;
|
||||
} Button;
|
||||
|
||||
+typedef struct LayoutNode LayoutNode;
|
||||
typedef struct Monitor Monitor;
|
||||
typedef struct {
|
||||
/* Must keep these three elements in this order */
|
||||
@@ -139,8 +141,9 @@ typedef struct {
|
||||
#endif
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
- int isfloating, isurgent, isfullscreen;
|
||||
+ int isfloating, isurgent, isfullscreen, was_tiled;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ struct wlr_box old_geom;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -208,6 +211,7 @@ struct Monitor {
|
||||
int nmaster;
|
||||
char ltsymbol[16];
|
||||
int asleep;
|
||||
+ LayoutNode *root;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -250,6 +254,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||
struct wlr_box *usable_area, int exclusive);
|
||||
static void arrangelayers(Monitor *m);
|
||||
static void axisnotify(struct wl_listener *listener, void *data);
|
||||
+static void btrtile(Monitor *m);
|
||||
static void buttonpress(struct wl_listener *listener, void *data);
|
||||
static void chvt(const Arg *arg);
|
||||
static void checkidleinhibitor(struct wlr_surface *exclude);
|
||||
@@ -333,6 +338,9 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||
static void setpsel(struct wl_listener *listener, void *data);
|
||||
static void setsel(struct wl_listener *listener, void *data);
|
||||
static void setup(void);
|
||||
+static void setratio_h(const Arg *arg);
|
||||
+static void setratio_v(const Arg *arg);
|
||||
+static void swapclients(const Arg *arg);
|
||||
static void spawn(const Arg *arg);
|
||||
static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
@@ -431,6 +439,7 @@ static xcb_atom_t netatom[NetLast];
|
||||
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
+#include "btrtile.c"
|
||||
|
||||
/* function implementations */
|
||||
void
|
||||
@@ -601,7 +610,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
struct wlr_pointer_button_event *event = data;
|
||||
struct wlr_keyboard *keyboard;
|
||||
uint32_t mods;
|
||||
- Client *c;
|
||||
+ Client *c, *target = NULL;
|
||||
const Button *b;
|
||||
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
@@ -622,7 +631,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
||||
for (b = buttons; b < END(buttons); b++) {
|
||||
if (CLEANMASK(mods) == CLEANMASK(b->mod) &&
|
||||
- event->button == b->button && b->func) {
|
||||
+ event->button == b->button && b->func) {
|
||||
b->func(&b->arg);
|
||||
return;
|
||||
}
|
||||
@@ -632,15 +641,36 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
/* If you released any buttons, we exit interactive move/resize mode. */
|
||||
/* TODO should reset to the pointer focus's current setcursor */
|
||||
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
||||
+ c = grabc;
|
||||
+ if (c && c->was_tiled && !strcmp(selmon->ltsymbol, "|w|")) {
|
||||
+ if (cursor_mode == CurMove && c->isfloating) {
|
||||
+ target = xytoclient(cursor->x, cursor->y);
|
||||
+
|
||||
+ if (target && !target->isfloating && !target->isfullscreen)
|
||||
+ insert_client(selmon, target, c);
|
||||
+ else
|
||||
+ selmon->root = create_client_node(c);
|
||||
+
|
||||
+ setfloating(c, 0);
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ } else if (cursor_mode == CurResize && !c->isfloating) {
|
||||
+ resizing_from_mouse = 0;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (cursor_mode == CurResize && resizing_from_mouse)
|
||||
+ resizing_from_mouse = 0;
|
||||
+ }
|
||||
+ /* Default behaviour */
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
cursor_mode = CurNormal;
|
||||
/* Drop the window off on its new monitor */
|
||||
selmon = xytomon(cursor->x, cursor->y);
|
||||
setmon(grabc, selmon, 0);
|
||||
+ grabc = NULL;
|
||||
return;
|
||||
- } else {
|
||||
- cursor_mode = CurNormal;
|
||||
}
|
||||
+ cursor_mode = CurNormal;
|
||||
break;
|
||||
}
|
||||
/* If the event wasn't handled by the compositor, notify the client with
|
||||
@@ -720,6 +750,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
wlr_output_layout_remove(output_layout, m->wlr_output);
|
||||
wlr_scene_output_destroy(m->scene_output);
|
||||
|
||||
+ destroy_tree(m);
|
||||
closemon(m);
|
||||
wlr_scene_node_destroy(&m->fullscreen_bg->node);
|
||||
free(m);
|
||||
@@ -1024,6 +1055,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
printstatus();
|
||||
+ init_tree(m);
|
||||
|
||||
/* The xdg-protocol specifies:
|
||||
*
|
||||
@@ -1263,6 +1295,10 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* We check if the destroyed client was part of any tiled_list, to catch
|
||||
+ * client removals even if they would not be currently managed by btrtile */
|
||||
+ if (selmon && selmon->root)
|
||||
+ remove_client(selmon, c);
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -1809,7 +1845,8 @@ void
|
||||
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
|
||||
double dx_unaccel, double dy_unaccel)
|
||||
{
|
||||
- double sx = 0, sy = 0, sx_confined, sy_confined;
|
||||
+ int tiled = 0;
|
||||
+ double sx = 0, sy = 0, sx_confined, sy_confined, dx_total, dy_total;
|
||||
Client *c = NULL, *w = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
struct wlr_surface *surface = NULL;
|
||||
@@ -1863,18 +1900,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
/* Update drag icon's position */
|
||||
wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
|
||||
|
||||
- /* If we are currently grabbing the mouse, handle and return */
|
||||
+ /* Skip if internal call or already resizing */
|
||||
+ if (time == 0 && resizing_from_mouse)
|
||||
+ goto focus;
|
||||
+
|
||||
+ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen;
|
||||
if (cursor_mode == CurMove) {
|
||||
/* Move the grabbed client to the new position. */
|
||||
- resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy,
|
||||
- .width = grabc->geom.width, .height = grabc->geom.height}, 1);
|
||||
- return;
|
||||
+ if (grabc && grabc->isfloating) {
|
||||
+ resize(grabc, (struct wlr_box){
|
||||
+ .x = (int)round(cursor->x) - grabcx,
|
||||
+ .y = (int)round(cursor->y) - grabcy,
|
||||
+ .width = grabc->geom.width,
|
||||
+ .height = grabc->geom.height
|
||||
+ }, 1);
|
||||
+ return;
|
||||
+ }
|
||||
} else if (cursor_mode == CurResize) {
|
||||
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
- return;
|
||||
+ if (tiled && resizing_from_mouse) {
|
||||
+ dx_total = cursor->x - resize_last_update_x;
|
||||
+ dy_total = cursor->y - resize_last_update_y;
|
||||
+
|
||||
+ if (time - last_resize_time >= resize_interval_ms) {
|
||||
+ Arg a = {0};
|
||||
+ if (fabs(dx_total) > fabs(dy_total)) {
|
||||
+ a.f = (float)(dx_total * resize_factor);
|
||||
+ setratio_h(&a);
|
||||
+ } else {
|
||||
+ a.f = (float)(dy_total * resize_factor);
|
||||
+ setratio_v(&a);
|
||||
+ }
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ last_resize_time = time;
|
||||
+ resize_last_update_x = cursor->x;
|
||||
+ resize_last_update_y = cursor->y;
|
||||
+ }
|
||||
+
|
||||
+ } else if (grabc && grabc->isfloating) {
|
||||
+ /* Floating resize as original */
|
||||
+ resize(grabc, (struct wlr_box){
|
||||
+ .x = grabc->geom.x,
|
||||
+ .y = grabc->geom.y,
|
||||
+ .width = (int)round(cursor->x) - grabc->geom.x,
|
||||
+ .height = (int)round(cursor->y) - grabc->geom.y
|
||||
+ }, 1);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
|
||||
+focus:
|
||||
/* If there's no client surface under the cursor, set the cursor image to a
|
||||
* default. This is what makes the cursor image appear when you move it
|
||||
* off of a client or over its border. */
|
||||
@@ -1908,22 +1983,41 @@ moveresize(const Arg *arg)
|
||||
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
|
||||
return;
|
||||
|
||||
- /* Float the window and tell motionnotify to grab it */
|
||||
- setfloating(grabc, 1);
|
||||
- switch (cursor_mode = arg->ui) {
|
||||
- case CurMove:
|
||||
- grabcx = (int)round(cursor->x) - grabc->geom.x;
|
||||
- grabcy = (int)round(cursor->y) - grabc->geom.y;
|
||||
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
- break;
|
||||
- case CurResize:
|
||||
- /* Doesn't work for X11 output - the next absolute motion event
|
||||
- * returns the cursor to where it started */
|
||||
- wlr_cursor_warp_closest(cursor, NULL,
|
||||
- grabc->geom.x + grabc->geom.width,
|
||||
- grabc->geom.y + grabc->geom.height);
|
||||
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
- break;
|
||||
+ cursor_mode = arg->ui;
|
||||
+ grabc->was_tiled = (!grabc->isfloating && !grabc->isfullscreen);
|
||||
+
|
||||
+ if (grabc->was_tiled) {
|
||||
+ switch (cursor_mode) {
|
||||
+ case CurMove:
|
||||
+ setfloating(grabc, 1);
|
||||
+ grabcx = (int)round(cursor->x) - grabc->geom.x;
|
||||
+ grabcy = (int)round(cursor->y) - grabc->geom.y;
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
+ break;
|
||||
+ case CurResize:
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ resize_last_update_x = cursor->x;
|
||||
+ resize_last_update_y = cursor->y;
|
||||
+ resizing_from_mouse = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Default floating logic */
|
||||
+ /* Float the window and tell motionnotify to grab it */
|
||||
+ setfloating(grabc, 1);
|
||||
+ switch (cursor_mode) {
|
||||
+ case CurMove:
|
||||
+ grabcx = (int)round(cursor->x) - grabc->geom.x;
|
||||
+ grabcy = (int)round(cursor->y) - grabc->geom.y;
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
+ break;
|
||||
+ case CurResize:
|
||||
+ wlr_cursor_warp_closest(cursor, NULL,
|
||||
+ grabc->geom.x + grabc->geom.width,
|
||||
+ grabc->geom.y + grabc->geom.height);
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.45.3
|
||||
|
||||
+903
@@ -0,0 +1,903 @@
|
||||
From b9789420f166c20579f29ecd171a8956c681848d Mon Sep 17 00:00:00 2001
|
||||
From: julmajustus <julmajustus@tutanota.com>
|
||||
Date: Thu, 13 Feb 2025 23:23:40 +0200
|
||||
Subject: [PATCH] btrtile with multi-tag support
|
||||
|
||||
---
|
||||
btrtile.c | 563 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
config.def.h | 12 ++
|
||||
dwl.c | 152 +++++++++++---
|
||||
3 files changed, 698 insertions(+), 29 deletions(-)
|
||||
create mode 100644 btrtile.c
|
||||
|
||||
diff --git a/btrtile.c b/btrtile.c
|
||||
new file mode 100644
|
||||
index 0000000..03f4680
|
||||
--- /dev/null
|
||||
+++ b/btrtile.c
|
||||
@@ -0,0 +1,563 @@
|
||||
+/* ************************************************************************** */
|
||||
+/* */
|
||||
+/* ::: :::::::: */
|
||||
+/* btrtile.c :+: :+: :+: */
|
||||
+/* +:+ +:+ +:+ */
|
||||
+/* By: jmakkone <jmakkone@student.hive.fi> +#+ +:+ +#+ */
|
||||
+/* +#+#+#+#+#+ +#+ */
|
||||
+/* Created: 2024/12/15 00:26:07 by jmakkone #+# #+# */
|
||||
+/* Updated: 2025/02/13 23:22:33 by jmakkone ### ########.fr */
|
||||
+/* */
|
||||
+/* ************************************************************************** */
|
||||
+
|
||||
+typedef struct LayoutNode {
|
||||
+ unsigned int is_client_node;
|
||||
+ unsigned int is_split_vertically;
|
||||
+ float split_ratio;
|
||||
+ struct LayoutNode *left;
|
||||
+ struct LayoutNode *right;
|
||||
+ struct LayoutNode *split_node;
|
||||
+ Client *client;
|
||||
+} LayoutNode;
|
||||
+
|
||||
+static void apply_layout(Monitor *m, LayoutNode *node,
|
||||
+ struct wlr_box area, unsigned int is_root);
|
||||
+static void btrtile(Monitor *m);
|
||||
+static LayoutNode *create_client_node(Client *c);
|
||||
+static LayoutNode *create_split_node(unsigned int is_split_vertically,
|
||||
+ LayoutNode *left, LayoutNode *right);
|
||||
+static void destroy_node(LayoutNode *node);
|
||||
+static void destroy_tree(Monitor *m);
|
||||
+static LayoutNode *find_client_node(LayoutNode *node, Client *c);
|
||||
+static LayoutNode *find_suitable_split(LayoutNode *start, unsigned int need_vert);
|
||||
+static void init_tree(Monitor *m);
|
||||
+static void insert_client(Monitor *m, Client *focused_client, Client *new_client);
|
||||
+static LayoutNode *remove_client_node(LayoutNode *node, Client *c);
|
||||
+static void remove_client(Monitor *m, Client *c);
|
||||
+static void setratio_h(const Arg *arg);
|
||||
+static void setratio_v(const Arg *arg);
|
||||
+static void swapclients(const Arg *arg);
|
||||
+static unsigned int visible_count(LayoutNode *node, Monitor *m);
|
||||
+static Client *xytoclient(double x, double y);
|
||||
+
|
||||
+static int resizing_from_mouse = 0;
|
||||
+static double resize_last_update_x, resize_last_update_y;
|
||||
+static uint32_t last_resize_time = 0;
|
||||
+
|
||||
+void
|
||||
+apply_layout(Monitor *m, LayoutNode *node,
|
||||
+ struct wlr_box area, unsigned int is_root)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ float ratio;
|
||||
+ unsigned int left_count, right_count, mid;
|
||||
+ struct wlr_box left_area, right_area;
|
||||
+
|
||||
+ if (!node)
|
||||
+ return;
|
||||
+
|
||||
+ /* If this node is a client node, check if it is visible. */
|
||||
+ if (node->is_client_node) {
|
||||
+ c = node->client;
|
||||
+ if (!c || !VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ return;
|
||||
+ resize(c, area, 0);
|
||||
+ c->old_geom = area;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* For a split node, we see how many visible children are on each side: */
|
||||
+ left_count = visible_count(node->left, m);
|
||||
+ right_count = visible_count(node->right, m);
|
||||
+
|
||||
+ if (left_count == 0 && right_count == 0) {
|
||||
+ return;
|
||||
+ } else if (left_count > 0 && right_count == 0) {
|
||||
+ apply_layout(m, node->left, area, 0);
|
||||
+ return;
|
||||
+ } else if (left_count == 0 && right_count > 0) {
|
||||
+ apply_layout(m, node->right, area, 0);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* If we’re here, we have visible clients in both subtrees. */
|
||||
+ ratio = node->split_ratio;
|
||||
+ if (ratio < 0.05f)
|
||||
+ ratio = 0.05f;
|
||||
+ if (ratio > 0.95f)
|
||||
+ ratio = 0.95f;
|
||||
+
|
||||
+ memset(&left_area, 0, sizeof(left_area));
|
||||
+ memset(&right_area, 0, sizeof(right_area));
|
||||
+
|
||||
+ if (node->is_split_vertically) {
|
||||
+ mid = (unsigned int)(area.width * ratio);
|
||||
+ left_area.x = area.x;
|
||||
+ left_area.y = area.y;
|
||||
+ left_area.width = mid;
|
||||
+ left_area.height = area.height;
|
||||
+
|
||||
+ right_area.x = area.x + mid;
|
||||
+ right_area.y = area.y;
|
||||
+ right_area.width = area.width - mid;
|
||||
+ right_area.height = area.height;
|
||||
+ } else {
|
||||
+ /* horizontal split */
|
||||
+ mid = (unsigned int)(area.height * ratio);
|
||||
+ left_area.x = area.x;
|
||||
+ left_area.y = area.y;
|
||||
+ left_area.width = area.width;
|
||||
+ left_area.height = mid;
|
||||
+
|
||||
+ right_area.x = area.x;
|
||||
+ right_area.y = area.y + mid;
|
||||
+ right_area.width = area.width;
|
||||
+ right_area.height= area.height - mid;
|
||||
+ }
|
||||
+
|
||||
+ apply_layout(m, node->left, left_area, 0);
|
||||
+ apply_layout(m, node->right, right_area, 0);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+btrtile(Monitor *m)
|
||||
+{
|
||||
+ Client *c, *focused = NULL;
|
||||
+ int n = 0;
|
||||
+ LayoutNode *found;
|
||||
+ struct wlr_box full_area;
|
||||
+
|
||||
+ if (!m || !m->root)
|
||||
+ return;
|
||||
+
|
||||
+ /* Remove non tiled clients from tree. */
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (c->mon == m && !c->isfloating && !c->isfullscreen) {
|
||||
+ } else {
|
||||
+ remove_client(m, c);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If no client is found under cursor, fallback to focustop(m) */
|
||||
+ if (!(focused = xytoclient(cursor->x, cursor->y)))
|
||||
+ focused = focustop(m);
|
||||
+
|
||||
+ /* Insert visible clients that are not part of the tree. */
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen && c->mon == m) {
|
||||
+ found = find_client_node(m->root, c);
|
||||
+ if (!found) {
|
||||
+ insert_client(m, focused, c);
|
||||
+ }
|
||||
+ n++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ full_area = m->w;
|
||||
+ apply_layout(m, m->root, full_area, 1);
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+create_client_node(Client *c)
|
||||
+{
|
||||
+ LayoutNode *node = calloc(1, sizeof(LayoutNode));
|
||||
+
|
||||
+ if (!node)
|
||||
+ return NULL;
|
||||
+ node->is_client_node = 1;
|
||||
+ node->split_ratio = 0.5f;
|
||||
+ node->client = c;
|
||||
+ return node;
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+create_split_node(unsigned int is_split_vertically,
|
||||
+ LayoutNode *left, LayoutNode *right)
|
||||
+{
|
||||
+ LayoutNode *node = calloc(1, sizeof(LayoutNode));
|
||||
+
|
||||
+ if (!node)
|
||||
+ return NULL;
|
||||
+ node->is_client_node = 0;
|
||||
+ node->split_ratio = 0.5f;
|
||||
+ node->is_split_vertically = is_split_vertically;
|
||||
+ node->left = left;
|
||||
+ node->right = right;
|
||||
+ if (left)
|
||||
+ left->split_node = node;
|
||||
+ if (right)
|
||||
+ right->split_node = node;
|
||||
+ return node;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+destroy_node(LayoutNode *node)
|
||||
+{
|
||||
+ if (!node)
|
||||
+ return;
|
||||
+ if (!node->is_client_node) {
|
||||
+ destroy_node(node->left);
|
||||
+ destroy_node(node->right);
|
||||
+ }
|
||||
+ free(node);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+destroy_tree(Monitor *m)
|
||||
+{
|
||||
+ if (!m || !m->root)
|
||||
+ return;
|
||||
+ destroy_node(m->root);
|
||||
+ m->root = NULL;
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+find_client_node(LayoutNode *node, Client *c)
|
||||
+{
|
||||
+ LayoutNode *res;
|
||||
+
|
||||
+ if (!node || !c)
|
||||
+ return NULL;
|
||||
+ if (node->is_client_node) {
|
||||
+ return (node->client == c) ? node : NULL;
|
||||
+ }
|
||||
+ res = find_client_node(node->left, c);
|
||||
+ return res ? res : find_client_node(node->right, c);
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+find_suitable_split(LayoutNode *start_node, unsigned int need_vertical)
|
||||
+{
|
||||
+ LayoutNode *n = start_node;
|
||||
+ /* if we started from a client node, jump to its parent: */
|
||||
+ if (n && n->is_client_node)
|
||||
+ n = n->split_node;
|
||||
+
|
||||
+ while (n) {
|
||||
+ if (!n->is_client_node && n->is_split_vertically == need_vertical &&
|
||||
+ visible_count(n->left, selmon) > 0 && visible_count(n->right, selmon) > 0)
|
||||
+ return n;
|
||||
+ n = n->split_node;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+init_tree(Monitor *m)
|
||||
+{
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+ m->root = calloc(1, sizeof(LayoutNode));
|
||||
+ if (!m->root)
|
||||
+ m->root = NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+insert_client(Monitor *m, Client *focused_client, Client *new_client)
|
||||
+{
|
||||
+ Client *old_client;
|
||||
+ LayoutNode **root = &m->root, *old_root,
|
||||
+ *focused_node, *new_client_node, *old_client_node;
|
||||
+ unsigned int wider, mid_x, mid_y;
|
||||
+
|
||||
+ /* If no root , new client becomes the root. */
|
||||
+ if (!*root) {
|
||||
+ *root = create_client_node(new_client);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Find the focused_client node,
|
||||
+ * if not found split the root. */
|
||||
+ focused_node = focused_client ?
|
||||
+ find_client_node(*root, focused_client) : NULL;
|
||||
+ if (!focused_node) {
|
||||
+ old_root = *root;
|
||||
+ new_client_node = create_client_node(new_client);
|
||||
+ *root = create_split_node(1, old_root, new_client_node);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Turn focused node from a client node into a split node,
|
||||
+ * and attach old_client + new_client. */
|
||||
+ old_client = focused_node->client;
|
||||
+ old_client_node = create_client_node(old_client);
|
||||
+ new_client_node = create_client_node(new_client);
|
||||
+
|
||||
+ /* Decide split direction. */
|
||||
+ wider = (focused_client->geom.width >= focused_client->geom.height);
|
||||
+ focused_node->is_client_node = 0;
|
||||
+ focused_node->client = NULL;
|
||||
+ focused_node->is_split_vertically = (wider ? 1 : 0);
|
||||
+
|
||||
+ /* Pick new_client side depending on the cursor position. */
|
||||
+ mid_x = focused_client->geom.x + focused_client->geom.width / 2;
|
||||
+ mid_y = focused_client->geom.y + focused_client->geom.height / 2;
|
||||
+
|
||||
+ if (wider) {
|
||||
+ /* vertical split => left vs right */
|
||||
+ if (cursor->x <= mid_x) {
|
||||
+ focused_node->left = new_client_node;
|
||||
+ focused_node->right = old_client_node;
|
||||
+ } else {
|
||||
+ focused_node->left = old_client_node;
|
||||
+ focused_node->right = new_client_node;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* horizontal split => top vs bottom */
|
||||
+ if (cursor->y <= mid_y) {
|
||||
+ focused_node->left = new_client_node;
|
||||
+ focused_node->right = old_client_node;
|
||||
+ } else {
|
||||
+ focused_node->left = old_client_node;
|
||||
+ focused_node->right = new_client_node;
|
||||
+ }
|
||||
+ }
|
||||
+ old_client_node->split_node = focused_node;
|
||||
+ new_client_node->split_node = focused_node;
|
||||
+ focused_node->split_ratio = 0.5f;
|
||||
+}
|
||||
+
|
||||
+LayoutNode *
|
||||
+remove_client_node(LayoutNode *node, Client *c)
|
||||
+{
|
||||
+ LayoutNode *tmp;
|
||||
+ if (!node)
|
||||
+ return NULL;
|
||||
+ if (node->is_client_node) {
|
||||
+ /* If this client_node is the client we're removing,
|
||||
+ * return NULL to remove it */
|
||||
+ if (node->client == c) {
|
||||
+ free(node);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ return node;
|
||||
+ }
|
||||
+
|
||||
+ node->left = remove_client_node(node->left, c);
|
||||
+ node->right = remove_client_node(node->right, c);
|
||||
+
|
||||
+ /* If one of the client node is NULL after removal and the other is not,
|
||||
+ * we "lift" the other client node up to replace this split node. */
|
||||
+ if (!node->left && node->right) {
|
||||
+ tmp = node->right;
|
||||
+
|
||||
+ /* Save pointer to split node */
|
||||
+ if (tmp)
|
||||
+ tmp->split_node = node->split_node;
|
||||
+
|
||||
+ free(node);
|
||||
+ return tmp;
|
||||
+ }
|
||||
+
|
||||
+ if (!node->right && node->left) {
|
||||
+ tmp = node->left;
|
||||
+
|
||||
+ /* Save pointer to split node */
|
||||
+ if (tmp)
|
||||
+ tmp->split_node = node->split_node;
|
||||
+
|
||||
+ free(node);
|
||||
+ return tmp;
|
||||
+ }
|
||||
+
|
||||
+ /* If both children exist or both are NULL (empty tree),
|
||||
+ * return node as is. */
|
||||
+ return node;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+remove_client(Monitor *m, Client *c)
|
||||
+{
|
||||
+ if (!m->root || !c)
|
||||
+ return;
|
||||
+ m->root = remove_client_node(m->root, c);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_h(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 1);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f;
|
||||
+ if (new_ratio < 0.05f)
|
||||
+ new_ratio = 0.05f;
|
||||
+ if (new_ratio > 0.95f)
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+setratio_v(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ LayoutNode *client_node, *split_node;
|
||||
+ float new_ratio;
|
||||
+
|
||||
+ if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+ client_node = find_client_node(selmon->root, sel);
|
||||
+ if (!client_node)
|
||||
+ return;
|
||||
+
|
||||
+ split_node = find_suitable_split(client_node, 0);
|
||||
+ if (!split_node)
|
||||
+ return;
|
||||
+
|
||||
+ new_ratio = (arg->f != 0.0f) ? (split_node->split_ratio + arg->f) : 0.5f;
|
||||
+ if (new_ratio < 0.05f)
|
||||
+ new_ratio = 0.05f;
|
||||
+ if (new_ratio > 0.95f)
|
||||
+ new_ratio = 0.95f;
|
||||
+ split_node->split_ratio = new_ratio;
|
||||
+
|
||||
+ /* Skip the arrange if done resizing by mouse,
|
||||
+ * we call arrange from motionotify */
|
||||
+ if (!resizing_from_mouse) {
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void swapclients(const Arg *arg) {
|
||||
+ Client *c, *tmp, *target = NULL, *sel = focustop(selmon);
|
||||
+ LayoutNode *sel_node, *target_node;
|
||||
+ int closest_dist = INT_MAX, dist, sel_center_x, sel_center_y,
|
||||
+ cand_center_x, cand_center_y;
|
||||
+
|
||||
+ if (!sel || sel->isfullscreen ||
|
||||
+ !selmon->root || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+
|
||||
+
|
||||
+ /* Get the center coordinates of the selected client */
|
||||
+ sel_center_x = sel->geom.x + sel->geom.width / 2;
|
||||
+ sel_center_y = sel->geom.y + sel->geom.height / 2;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (!VISIBLEON(c, selmon) || c->isfloating || c->isfullscreen || c == sel)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Get the center of candidate client */
|
||||
+ cand_center_x = c->geom.x + c->geom.width / 2;
|
||||
+ cand_center_y = c->geom.y + c->geom.height / 2;
|
||||
+
|
||||
+ /* Check that the candidate lies in the requested direction. */
|
||||
+ switch (arg->ui) {
|
||||
+ case 0:
|
||||
+ if (cand_center_x >= sel_center_x)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ if (cand_center_x <= sel_center_x)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ if (cand_center_y >= sel_center_y)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ if (cand_center_y <= sel_center_y)
|
||||
+ continue;
|
||||
+ break;
|
||||
+ default:
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Get distance between the centers */
|
||||
+ dist = abs(sel_center_x - cand_center_x) + abs(sel_center_y - cand_center_y);
|
||||
+ if (dist < closest_dist) {
|
||||
+ closest_dist = dist;
|
||||
+ target = c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If target is found, swap the two clients’ positions in the layout tree */
|
||||
+ if (target) {
|
||||
+ sel_node = find_client_node(selmon->root, sel);
|
||||
+ target_node = find_client_node(selmon->root, target);
|
||||
+ if (sel_node && target_node) {
|
||||
+ tmp = sel_node->client;
|
||||
+ sel_node->client = target_node->client;
|
||||
+ target_node->client = tmp;
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+unsigned int
|
||||
+visible_count(LayoutNode *node, Monitor *m)
|
||||
+{
|
||||
+ Client *c;
|
||||
+
|
||||
+ if (!node)
|
||||
+ return 0;
|
||||
+ /* Check if this client is visible. */
|
||||
+ if (node->is_client_node) {
|
||||
+ c = node->client;
|
||||
+ if (c && VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
|
||||
+ return 1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /* Else it’s a split node. */
|
||||
+ return visible_count(node->left, m) + visible_count(node->right, m);
|
||||
+}
|
||||
+
|
||||
+Client *
|
||||
+xytoclient(double x, double y) {
|
||||
+ Client *c, *closest = NULL;
|
||||
+ double dist, mindist = INT_MAX, dx, dy;
|
||||
+
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen &&
|
||||
+ x >= c->geom.x && x <= (c->geom.x + c->geom.width) &&
|
||||
+ y >= c->geom.y && y <= (c->geom.y + c->geom.height)){
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If no client was found at cursor position fallback to closest. */
|
||||
+ wl_list_for_each_reverse(c, &clients, link) {
|
||||
+ if (VISIBLEON(c, selmon) && !c->isfloating && !c->isfullscreen) {
|
||||
+ dx = 0, dy = 0;
|
||||
+
|
||||
+ if (x < c->geom.x)
|
||||
+ dx = c->geom.x - x;
|
||||
+ else if (x > (c->geom.x + c->geom.width))
|
||||
+ dx = x - (c->geom.x + c->geom.width);
|
||||
+
|
||||
+ if (y < c->geom.y)
|
||||
+ dy = c->geom.y - y;
|
||||
+ else if (y > (c->geom.y + c->geom.height))
|
||||
+ dy = y - (c->geom.y + c->geom.height);
|
||||
+
|
||||
+ dist = sqrt(dx * dx + dy * dy);
|
||||
+ if (dist < mindist) {
|
||||
+ mindist = dist;
|
||||
+ closest = c;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return closest;
|
||||
+}
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..92f3ad6 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -13,7 +13,10 @@ static const float focuscolor[] = COLOR(0x005577ff);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
+static const float resize_factor = 0.0002f; /* Resize multiplier for mouse resizing, depends on mouse sensivity. */
|
||||
+static const uint32_t resize_interval_ms = 16; /* Resize interval depends on framerate and screen refresh rate. */
|
||||
|
||||
+enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN };
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
#define TAGCOUNT (9)
|
||||
|
||||
@@ -31,6 +34,7 @@ static const Rule rules[] = {
|
||||
/* layout(s) */
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
+ { "|w|", btrtile },
|
||||
{ "[]=", tile },
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
@@ -148,6 +152,14 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapclients, {.i = DIR_UP} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapclients, {.i = DIR_DOWN} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapclients, {.i = DIR_RIGHT} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapclients, {.i = DIR_LEFT} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, setratio_h, {.f = +0.025f} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, setratio_h, {.f = -0.025f} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Up, setratio_v, {.f = -0.025f} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Down, setratio_v, {.f = +0.025f} },
|
||||
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index a2711f6..e49a061 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* See LICENSE file for copyright and license details.
|
||||
*/
|
||||
+#include <limits.h>
|
||||
#include <getopt.h>
|
||||
#include <libinput.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
@@ -103,6 +104,7 @@ typedef struct {
|
||||
const Arg arg;
|
||||
} Button;
|
||||
|
||||
+typedef struct LayoutNode LayoutNode;
|
||||
typedef struct Monitor Monitor;
|
||||
typedef struct {
|
||||
/* Must keep these three elements in this order */
|
||||
@@ -139,8 +141,9 @@ typedef struct {
|
||||
#endif
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
- int isfloating, isurgent, isfullscreen;
|
||||
+ int isfloating, isurgent, isfullscreen, was_tiled;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ struct wlr_box old_geom;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -208,6 +211,7 @@ struct Monitor {
|
||||
int nmaster;
|
||||
char ltsymbol[16];
|
||||
int asleep;
|
||||
+ LayoutNode *root;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -250,6 +254,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||
struct wlr_box *usable_area, int exclusive);
|
||||
static void arrangelayers(Monitor *m);
|
||||
static void axisnotify(struct wl_listener *listener, void *data);
|
||||
+static void btrtile(Monitor *m);
|
||||
static void buttonpress(struct wl_listener *listener, void *data);
|
||||
static void chvt(const Arg *arg);
|
||||
static void checkidleinhibitor(struct wlr_surface *exclude);
|
||||
@@ -333,6 +338,9 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||
static void setpsel(struct wl_listener *listener, void *data);
|
||||
static void setsel(struct wl_listener *listener, void *data);
|
||||
static void setup(void);
|
||||
+static void setratio_h(const Arg *arg);
|
||||
+static void setratio_v(const Arg *arg);
|
||||
+static void swapclients(const Arg *arg);
|
||||
static void spawn(const Arg *arg);
|
||||
static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
@@ -431,6 +439,7 @@ static xcb_atom_t netatom[NetLast];
|
||||
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
+#include "btrtile.c"
|
||||
|
||||
/* function implementations */
|
||||
void
|
||||
@@ -601,7 +610,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
struct wlr_pointer_button_event *event = data;
|
||||
struct wlr_keyboard *keyboard;
|
||||
uint32_t mods;
|
||||
- Client *c;
|
||||
+ Client *c, *target = NULL;
|
||||
const Button *b;
|
||||
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
@@ -622,7 +631,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
||||
for (b = buttons; b < END(buttons); b++) {
|
||||
if (CLEANMASK(mods) == CLEANMASK(b->mod) &&
|
||||
- event->button == b->button && b->func) {
|
||||
+ event->button == b->button && b->func) {
|
||||
b->func(&b->arg);
|
||||
return;
|
||||
}
|
||||
@@ -632,15 +641,36 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
/* If you released any buttons, we exit interactive move/resize mode. */
|
||||
/* TODO should reset to the pointer focus's current setcursor */
|
||||
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
||||
+ c = grabc;
|
||||
+ if (c && c->was_tiled && !strcmp(selmon->ltsymbol, "|w|")) {
|
||||
+ if (cursor_mode == CurMove && c->isfloating) {
|
||||
+ target = xytoclient(cursor->x, cursor->y);
|
||||
+
|
||||
+ if (target && !target->isfloating && !target->isfullscreen)
|
||||
+ insert_client(selmon, target, c);
|
||||
+ else
|
||||
+ selmon->root = create_client_node(c);
|
||||
+
|
||||
+ setfloating(c, 0);
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ } else if (cursor_mode == CurResize && !c->isfloating) {
|
||||
+ resizing_from_mouse = 0;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (cursor_mode == CurResize && resizing_from_mouse)
|
||||
+ resizing_from_mouse = 0;
|
||||
+ }
|
||||
+ /* Default behaviour */
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
cursor_mode = CurNormal;
|
||||
/* Drop the window off on its new monitor */
|
||||
selmon = xytomon(cursor->x, cursor->y);
|
||||
setmon(grabc, selmon, 0);
|
||||
+ grabc = NULL;
|
||||
return;
|
||||
- } else {
|
||||
- cursor_mode = CurNormal;
|
||||
}
|
||||
+ cursor_mode = CurNormal;
|
||||
break;
|
||||
}
|
||||
/* If the event wasn't handled by the compositor, notify the client with
|
||||
@@ -720,6 +750,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||
wlr_output_layout_remove(output_layout, m->wlr_output);
|
||||
wlr_scene_output_destroy(m->scene_output);
|
||||
|
||||
+ destroy_tree(m);
|
||||
closemon(m);
|
||||
wlr_scene_node_destroy(&m->fullscreen_bg->node);
|
||||
free(m);
|
||||
@@ -1024,6 +1055,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
printstatus();
|
||||
+ init_tree(m);
|
||||
|
||||
/* The xdg-protocol specifies:
|
||||
*
|
||||
@@ -1263,6 +1295,10 @@ destroynotify(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&c->destroy.link);
|
||||
wl_list_remove(&c->set_title.link);
|
||||
wl_list_remove(&c->fullscreen.link);
|
||||
+ /* We check if the destroyed client was part of any tiled_list, to catch
|
||||
+ * client removals even if they would not be currently managed by btrtile */
|
||||
+ if (selmon && selmon->root)
|
||||
+ remove_client(selmon, c);
|
||||
#ifdef XWAYLAND
|
||||
if (c->type != XDGShell) {
|
||||
wl_list_remove(&c->activate.link);
|
||||
@@ -1809,7 +1845,8 @@ void
|
||||
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
|
||||
double dx_unaccel, double dy_unaccel)
|
||||
{
|
||||
- double sx = 0, sy = 0, sx_confined, sy_confined;
|
||||
+ int tiled = 0;
|
||||
+ double sx = 0, sy = 0, sx_confined, sy_confined, dx_total, dy_total;
|
||||
Client *c = NULL, *w = NULL;
|
||||
LayerSurface *l = NULL;
|
||||
struct wlr_surface *surface = NULL;
|
||||
@@ -1863,18 +1900,56 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
/* Update drag icon's position */
|
||||
wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
|
||||
|
||||
- /* If we are currently grabbing the mouse, handle and return */
|
||||
+ /* Skip if internal call or already resizing */
|
||||
+ if (time == 0 && resizing_from_mouse)
|
||||
+ goto focus;
|
||||
+
|
||||
+ tiled = grabc && !grabc->isfloating && !grabc->isfullscreen;
|
||||
if (cursor_mode == CurMove) {
|
||||
/* Move the grabbed client to the new position. */
|
||||
- resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy,
|
||||
- .width = grabc->geom.width, .height = grabc->geom.height}, 1);
|
||||
- return;
|
||||
+ if (grabc && grabc->isfloating) {
|
||||
+ resize(grabc, (struct wlr_box){
|
||||
+ .x = (int)round(cursor->x) - grabcx,
|
||||
+ .y = (int)round(cursor->y) - grabcy,
|
||||
+ .width = grabc->geom.width,
|
||||
+ .height = grabc->geom.height
|
||||
+ }, 1);
|
||||
+ return;
|
||||
+ }
|
||||
} else if (cursor_mode == CurResize) {
|
||||
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
- return;
|
||||
+ if (tiled && resizing_from_mouse) {
|
||||
+ dx_total = cursor->x - resize_last_update_x;
|
||||
+ dy_total = cursor->y - resize_last_update_y;
|
||||
+
|
||||
+ if (time - last_resize_time >= resize_interval_ms) {
|
||||
+ Arg a = {0};
|
||||
+ if (fabs(dx_total) > fabs(dy_total)) {
|
||||
+ a.f = (float)(dx_total * resize_factor);
|
||||
+ setratio_h(&a);
|
||||
+ } else {
|
||||
+ a.f = (float)(dy_total * resize_factor);
|
||||
+ setratio_v(&a);
|
||||
+ }
|
||||
+ arrange(selmon);
|
||||
+
|
||||
+ last_resize_time = time;
|
||||
+ resize_last_update_x = cursor->x;
|
||||
+ resize_last_update_y = cursor->y;
|
||||
+ }
|
||||
+
|
||||
+ } else if (grabc && grabc->isfloating) {
|
||||
+ /* Floating resize as original */
|
||||
+ resize(grabc, (struct wlr_box){
|
||||
+ .x = grabc->geom.x,
|
||||
+ .y = grabc->geom.y,
|
||||
+ .width = (int)round(cursor->x) - grabc->geom.x,
|
||||
+ .height = (int)round(cursor->y) - grabc->geom.y
|
||||
+ }, 1);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
|
||||
+focus:
|
||||
/* If there's no client surface under the cursor, set the cursor image to a
|
||||
* default. This is what makes the cursor image appear when you move it
|
||||
* off of a client or over its border. */
|
||||
@@ -1908,22 +1983,41 @@ moveresize(const Arg *arg)
|
||||
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
|
||||
return;
|
||||
|
||||
- /* Float the window and tell motionnotify to grab it */
|
||||
- setfloating(grabc, 1);
|
||||
- switch (cursor_mode = arg->ui) {
|
||||
- case CurMove:
|
||||
- grabcx = (int)round(cursor->x) - grabc->geom.x;
|
||||
- grabcy = (int)round(cursor->y) - grabc->geom.y;
|
||||
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
- break;
|
||||
- case CurResize:
|
||||
- /* Doesn't work for X11 output - the next absolute motion event
|
||||
- * returns the cursor to where it started */
|
||||
- wlr_cursor_warp_closest(cursor, NULL,
|
||||
- grabc->geom.x + grabc->geom.width,
|
||||
- grabc->geom.y + grabc->geom.height);
|
||||
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
- break;
|
||||
+ cursor_mode = arg->ui;
|
||||
+ grabc->was_tiled = (!grabc->isfloating && !grabc->isfullscreen);
|
||||
+
|
||||
+ if (grabc->was_tiled) {
|
||||
+ switch (cursor_mode) {
|
||||
+ case CurMove:
|
||||
+ setfloating(grabc, 1);
|
||||
+ grabcx = (int)round(cursor->x) - grabc->geom.x;
|
||||
+ grabcy = (int)round(cursor->y) - grabc->geom.y;
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
+ break;
|
||||
+ case CurResize:
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ resize_last_update_x = cursor->x;
|
||||
+ resize_last_update_y = cursor->y;
|
||||
+ resizing_from_mouse = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Default floating logic */
|
||||
+ /* Float the window and tell motionnotify to grab it */
|
||||
+ setfloating(grabc, 1);
|
||||
+ switch (cursor_mode) {
|
||||
+ case CurMove:
|
||||
+ grabcx = (int)round(cursor->x) - grabc->geom.x;
|
||||
+ grabcy = (int)round(cursor->y) - grabc->geom.y;
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
+ break;
|
||||
+ case CurResize:
|
||||
+ wlr_cursor_warp_closest(cursor, NULL,
|
||||
+ grabc->geom.x + grabc->geom.width,
|
||||
+ grabc->geom.y + grabc->geom.height);
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.45.3
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
### Description
|
||||
Adds "state" (`enum wlr_button_state`) to configure a button action on either press or release.
|
||||
This basically enables release to be used for button actions.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/nullsystem/dwl/src/branch/main_buttonbystate)
|
||||
- [2024-04-06](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/buttonbystate/buttonbystate.patch)
|
||||
|
||||
### Authors
|
||||
- [nullsystem](https://codeberg.org/nullsystem)
|
||||
@@ -0,0 +1,78 @@
|
||||
From 4141aa9455e4b4a5b4a235475c70e8c100ec663e Mon Sep 17 00:00:00 2001
|
||||
From: nullsystem <nullsystem.aongp@slmail.me>
|
||||
Date: Sat, 6 Apr 2024 02:03:49 +0100
|
||||
Subject: [PATCH] buttonbystate - allow config for release (and press)
|
||||
|
||||
- Adds "state" (enum wlr_button_state) to configure a button action on
|
||||
either press or release. This basically enables release to be used
|
||||
for button actions.
|
||||
---
|
||||
config.def.h | 6 +++---
|
||||
dwl.c | 22 ++++++++++++----------
|
||||
2 files changed, 15 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8847e58..cc989cf 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -165,7 +165,7 @@ static const Key keys[] = {
|
||||
};
|
||||
|
||||
static const Button buttons[] = {
|
||||
- { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },
|
||||
- { MODKEY, BTN_MIDDLE, togglefloating, {0} },
|
||||
- { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
|
||||
+ { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove}, WLR_BUTTON_PRESSED },
|
||||
+ { MODKEY, BTN_MIDDLE, togglefloating, {0}, WLR_BUTTON_PRESSED },
|
||||
+ { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize}, WLR_BUTTON_PRESSED },
|
||||
};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763df..6b60ccf 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -99,6 +99,7 @@ typedef struct {
|
||||
unsigned int button;
|
||||
void (*func)(const Arg *);
|
||||
const Arg arg;
|
||||
+ enum wlr_button_state state;
|
||||
} Button;
|
||||
|
||||
typedef struct Monitor Monitor;
|
||||
@@ -595,16 +596,6 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
|
||||
if (c && (!client_is_unmanaged(c) || client_wants_focus(c)))
|
||||
focusclient(c, 1);
|
||||
-
|
||||
- keyboard = wlr_seat_get_keyboard(seat);
|
||||
- mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
||||
- for (b = buttons; b < END(buttons); b++) {
|
||||
- if (CLEANMASK(mods) == CLEANMASK(b->mod) &&
|
||||
- event->button == b->button && b->func) {
|
||||
- b->func(&b->arg);
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
break;
|
||||
case WLR_BUTTON_RELEASED:
|
||||
held_grab = NULL;
|
||||
@@ -622,6 +613,17 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
}
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ keyboard = wlr_seat_get_keyboard(seat);
|
||||
+ mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
||||
+ for (b = buttons; b < END(buttons); b++) {
|
||||
+ if (b->state == event->state && CLEANMASK(mods) == CLEANMASK(b->mod) &&
|
||||
+ event->button == b->button && b->func) {
|
||||
+ b->func(&b->arg);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* If the event wasn't handled by the compositor, notify the client with
|
||||
* pointer focus that a button press has occurred */
|
||||
wlr_seat_pointer_notify_button(seat,
|
||||
--
|
||||
2.44.0
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
### Description
|
||||
Add a keybinding that toggles centering the terminally horizontally when
|
||||
it's the only window, while still tiling multiple windows.
|
||||
|
||||
This limits the width of long text making it easier to read, and avoids
|
||||
covering the wallpaper more than necessary.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/guidocella/dwl/src/branch/center-terminal)
|
||||
- [2024-02-06](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/center-terminal/center-terminal.patch)
|
||||
|
||||
### Authors
|
||||
- [Guido Cella](https://codeberg.org/guidocella)
|
||||
@@ -0,0 +1,103 @@
|
||||
From 340cc5ef90dfcc495bdad045f3f76ae07405cffd Mon Sep 17 00:00:00 2001
|
||||
From: Guido Cella <guido@guidocella.xyz>
|
||||
Date: Tue, 6 Feb 2024 09:20:48 +0100
|
||||
Subject: [PATCH] add a keybinding to center the terminal
|
||||
|
||||
Add a keybinding that toggles centering the terminally horizontally when
|
||||
it's the only window, while still tiling multiple windows.
|
||||
|
||||
This limits the width of long text making it easier to read, and avoids
|
||||
covering the wallpaper more than necessary.
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 20 ++++++++++++++++++++
|
||||
2 files changed, 21 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..8229fcc 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -142,6 +142,7 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, XKB_KEY_v, togglecenter, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 12f441e..3b15748 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
+#include <strings.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
@@ -138,6 +139,7 @@ typedef struct {
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
+ bool centered;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -334,6 +336,7 @@ static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
+static void togglecenter(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
@@ -436,6 +439,8 @@ static struct wl_listener request_start_drag = {.notify = requeststartdrag};
|
||||
static struct wl_listener start_drag = {.notify = startdrag};
|
||||
static struct wl_listener new_session_lock = {.notify = locksession};
|
||||
|
||||
+static bool center;
|
||||
+
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
@@ -499,6 +504,9 @@ applyrules(Client *c)
|
||||
}
|
||||
}
|
||||
|
||||
+ if (!strcasecmp(appid, termcmd[0]))
|
||||
+ c->centered = true;
|
||||
+
|
||||
c->isfloating |= client_is_float_type(c);
|
||||
setmon(c, mon, newtags);
|
||||
}
|
||||
@@ -2730,6 +2738,11 @@ tile(Monitor *m)
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
+ if (n == 1 && center && c->centered) {
|
||||
+ resize(c, (struct wlr_box){.x = m->w.width / 4, .y = m->w.y,
|
||||
+ .width = m->w.width / 2, .height = m->w.height - 2 * c->bw}, 0);
|
||||
+ return;
|
||||
+ }
|
||||
resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
|
||||
.height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
|
||||
my += c->geom.height;
|
||||
@@ -2742,6 +2755,13 @@ tile(Monitor *m)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+togglecenter(const Arg *arg)
|
||||
+{
|
||||
+ center = !center;
|
||||
+ tile(selmon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
togglefloating(const Arg *arg)
|
||||
{
|
||||
--
|
||||
2.49.0
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
### Description
|
||||
This is a port of centeredmaster patch for dwm: <https://dwm.suckless.org/patches/centeredmaster>
|
||||
|
||||
centeredmaster centers the nmaster area on screen, using mfact * monitor
|
||||
width & height, with the stacked windows distributed to the left and
|
||||
right. It can be selected with `Alt+c`.
|
||||
|
||||
With one and two clients in master respectively this results in:
|
||||
|
||||
```
|
||||
+------------------------------+ +------------------------------+
|
||||
|+--------++--------++--------+| |+--------++--------++--------+|
|
||||
|| || || || || || || ||
|
||||
|| || || || || || M1 || ||
|
||||
|| || || || || || || ||
|
||||
|| S2 || M || S1 || || |+--------+| ||
|
||||
|| || || || || |+--------+| ||
|
||||
|| || || || || || || ||
|
||||
|| || || || || || M2 || ||
|
||||
|| || || || || || || ||
|
||||
|+--------++--------++--------+| |+--------++--------++--------+|
|
||||
+------------------------------+ +------------------------------+
|
||||
```
|
||||
|
||||
|
||||
### Download
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/centeredmaster/centeredmaster.patch)
|
||||
- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/b104a580a80ebaf9f7e8917fe574e3e97ddd019a/centeredmaster/centeredmaster.patch)
|
||||
- [0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/0f4e40fee49d1b8b430778e241b29496ae3b3b70/centeredmaster/centeredmaster.patch)
|
||||
|
||||
### Authors
|
||||
- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV))
|
||||
- [wochap](https://codeberg.org/wochap)
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
From b1ca46930756b59c1ebba0b8c7871b85ff84f62f Mon Sep 17 00:00:00 2001
|
||||
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
|
||||
Date: Sat, 8 Feb 2025 16:10:25 +0100
|
||||
Subject: [PATCH] Add centeredmaster layout
|
||||
|
||||
This is a port of centeredmaster patch for dwm:
|
||||
https://dwm.suckless.org/patches/centeredmaster
|
||||
|
||||
centeredmaster centers the nmaster area on screen, using mfact * monitor
|
||||
width & height, with the stacked windows distributed to the left and
|
||||
right. It can be selected with [Alt]+[c].
|
||||
|
||||
With one and two clients in master respectively this results in:
|
||||
|
||||
+------------------------------+ +------------------------------+
|
||||
|+--------++--------++--------+| |+--------++--------++--------+|
|
||||
|| || || || || || || ||
|
||||
|| || || || || || M1 || ||
|
||||
|| || || || || || || ||
|
||||
|| S2 || M || S1 || || |+--------+| ||
|
||||
|| || || || || |+--------+| ||
|
||||
|| || || || || || || ||
|
||||
|| || || || || || M2 || ||
|
||||
|| || || || || || || ||
|
||||
|+--------++--------++--------+| |+--------++--------++--------+|
|
||||
+------------------------------+ +------------------------------+
|
||||
---
|
||||
config.def.h | 2 ++
|
||||
dwl.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 65 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..9a3b0c5 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -34,6 +34,7 @@ static const Layout layouts[] = {
|
||||
{ "[]=", tile },
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
+ { "|M|", centeredmaster },
|
||||
};
|
||||
|
||||
/* monitors */
|
||||
@@ -139,6 +140,7 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
+ { MODKEY, XKB_KEY_c, setlayout, {.v = &layouts[3]} },
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index def2562..c2456dd 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -251,6 +251,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||
static void arrangelayers(Monitor *m);
|
||||
static void axisnotify(struct wl_listener *listener, void *data);
|
||||
static void buttonpress(struct wl_listener *listener, void *data);
|
||||
+static void centeredmaster(Monitor *m);
|
||||
static void chvt(const Arg *arg);
|
||||
static void checkidleinhibitor(struct wlr_surface *exclude);
|
||||
static void cleanup(void);
|
||||
@@ -649,6 +650,68 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
event->time_msec, event->button, event->state);
|
||||
}
|
||||
|
||||
+void
|
||||
+centeredmaster(Monitor *m)
|
||||
+{
|
||||
+ int i, n, h, mw, mx, my, oty, ety, tw;
|
||||
+ Client *c;
|
||||
+
|
||||
+ n = 0;
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
|
||||
+ n++;
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ /* initialize areas */
|
||||
+ mw = m->w.width;
|
||||
+ mx = 0;
|
||||
+ my = 0;
|
||||
+ tw = mw;
|
||||
+
|
||||
+ if (n > m->nmaster) {
|
||||
+ /* go mfact box in the center if more than nmaster clients */
|
||||
+ mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0;
|
||||
+ tw = m->w.width - mw;
|
||||
+
|
||||
+ if (n - m->nmaster > 1) {
|
||||
+ /* only one client */
|
||||
+ mx = (m->w.width - mw) / 2;
|
||||
+ tw = (m->w.width - mw) / 2;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ i = 0;
|
||||
+ oty = 0;
|
||||
+ ety = 0;
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ continue;
|
||||
+ if (i < m->nmaster) {
|
||||
+ /* nmaster clients are stacked vertically, in the center
|
||||
+ * of the screen */
|
||||
+ h = (m->w.height - my) / (MIN(n, m->nmaster) - i);
|
||||
+ resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y + my, .width = mw,
|
||||
+ .height = h}, 0);
|
||||
+ my += c->geom.height;
|
||||
+ } else {
|
||||
+ /* stack clients are stacked vertically */
|
||||
+ if ((i - m->nmaster) % 2) {
|
||||
+ h = (m->w.height - ety) / ( (1 + n - i) / 2);
|
||||
+ resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ety, .width = tw,
|
||||
+ .height = h}, 0);
|
||||
+ ety += c->geom.height;
|
||||
+ } else {
|
||||
+ h = (m->w.height - oty) / ((1 + n - i) / 2);
|
||||
+ resize(c, (struct wlr_box){.x = m->w.x + mx + mw, .y = m->w.y + oty, .width = tw,
|
||||
+ .height = h}, 0);
|
||||
+ oty += c->geom.height;
|
||||
+ }
|
||||
+ }
|
||||
+ i++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void
|
||||
chvt(const Arg *arg)
|
||||
{
|
||||
--
|
||||
2.48.1
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
### Description
|
||||
This patch implements [cfact][cfact] for [snail][snail] layout.
|
||||
This patch must be applied on top of cfact and snail patches.
|
||||
|
||||
[cfact]: /dwl/dwl-patches/src/branch/main/patches/cfact
|
||||
[snail]: /dwl/dwl-patches/src/branch/main/patches/snail
|
||||
|
||||
|
||||
### Download
|
||||
- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact-snail/cfact-snail.patch)
|
||||
|
||||
### Authors
|
||||
- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV))
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
From 9f8109182a7d173d2a2cb30c089a7e7b9ffe0a5e Mon Sep 17 00:00:00 2001
|
||||
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
|
||||
Date: Tue, 25 Mar 2025 02:24:32 +0100
|
||||
Subject: [PATCH] cfact patch for snail layout
|
||||
|
||||
---
|
||||
dwl.c | 24 ++++++++++++------------
|
||||
1 file changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 4f8c493..37aa935 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -2699,10 +2699,10 @@ snail(Monitor *m)
|
||||
* Split the previous horizontally and put the current window on the right
|
||||
*/
|
||||
} else if (dir == WLR_DIRECTION_RIGHT) {
|
||||
- c->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2, .y = prev->geom.y,
|
||||
- .width = prev->geom.width / 2, .height = prev->geom.height};
|
||||
+ c->geom = (struct wlr_box){.x = prev->geom.x + (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.width), .y = prev->geom.y,
|
||||
+ .width = (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.width), .height = prev->geom.height};
|
||||
prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y,
|
||||
- .width = prev->geom.width / 2, .height = prev->geom.height};
|
||||
+ .width = (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.width), .height = prev->geom.height};
|
||||
/*
|
||||
* If it's a stack window or the first narrow window in the master
|
||||
* area, put the next one below it
|
||||
@@ -2713,28 +2713,28 @@ snail(Monitor *m)
|
||||
* Split the previous vertically and put the current window below it
|
||||
*/
|
||||
} else if (dir == WLR_DIRECTION_DOWN) {
|
||||
- c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2,
|
||||
- .width = prev->geom.width, .height = prev->geom.height / 2};
|
||||
+ c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.height),
|
||||
+ .width = prev->geom.width, .height = (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.height)};
|
||||
prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y,
|
||||
- .width = prev->geom.width, .height = prev->geom.height / 2};
|
||||
+ .width = prev->geom.width, .height = (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.height)};
|
||||
dir = WLR_DIRECTION_LEFT;
|
||||
/*
|
||||
* Split the previous horizontally and put the current window on the left
|
||||
*/
|
||||
} else if (dir == WLR_DIRECTION_LEFT) {
|
||||
c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y,
|
||||
- .width = prev->geom.width / 2, .height = prev->geom.height};
|
||||
- prev->geom = (struct wlr_box){.x = prev->geom.x + prev->geom.width / 2, .y = prev->geom.y,
|
||||
- .width = prev->geom.width / 2, .height = prev->geom.height};
|
||||
+ .width = (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.width), .height = prev->geom.height};
|
||||
+ prev->geom = (struct wlr_box){.x = prev->geom.x + (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.width), .y = prev->geom.y,
|
||||
+ .width = (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.width), .height = prev->geom.height};
|
||||
dir = WLR_DIRECTION_UP;
|
||||
/*
|
||||
* Split the previous vertically and put the current window above it
|
||||
*/
|
||||
} else {
|
||||
c->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y,
|
||||
- .width = prev->geom.width, .height = prev->geom.height / 2};
|
||||
- prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + prev->geom.height / 2,
|
||||
- .width = prev->geom.width, .height = prev->geom.height / 2};
|
||||
+ .width = prev->geom.width, .height = (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.height)};
|
||||
+ prev->geom = (struct wlr_box){.x = prev->geom.x, .y = prev->geom.y + (int)(c->cweight / (c->cweight + prev->cweight) * prev->geom.height),
|
||||
+ .width = prev->geom.width, .height = (int)(prev->cweight / (prev->cweight + c->cweight) * prev->geom.height)};
|
||||
dir = WLR_DIRECTION_RIGHT;
|
||||
}
|
||||
i++;
|
||||
--
|
||||
2.49.0
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
### Description
|
||||
A port of the [dwm cfacts patch](https://dwm.suckless.org/patches/cfacts/) (with the limits removed)
|
||||
|
||||
Clients with higher weight are allocated more space!
|
||||
```
|
||||
+---------------------+
|
||||
| | 0.5 |
|
||||
| 1.0 +----------+
|
||||
+----------+ |
|
||||
| | 1.0 |
|
||||
| +----------+
|
||||
| 2.0 | |
|
||||
| | 1.0 |
|
||||
+----------+----------+`
|
||||
```
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/Palanix/dwl/src/branch/cfact)
|
||||
- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact/cfact-v0.7.patch)
|
||||
- [v0.7-gaps](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact/cfact-v0.7-gaps.patch)
|
||||
- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact/cfact-v0.6.patch)
|
||||
- [2024-02-15](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/cfact/cfact.patch)
|
||||
|
||||
### Authors
|
||||
- [dev-gm](https://codeberg.org/dev-gm)
|
||||
- [Palanix](https://codeberg.org/Palanix)
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
From 52d8ed5ece7c96ea02441faaa4da2b0f51c8ebc4 Mon Sep 17 00:00:00 2001
|
||||
From: Palanix <palanixyt@gmail.com>
|
||||
Date: Fri, 24 Nov 2023 21:16:56 +0100
|
||||
Subject: [PATCH] cweights to allow different size clients in normal layouts
|
||||
|
||||
---
|
||||
config.def.h | 3 +++
|
||||
dwl.c | 32 ++++++++++++++++++++++++++++++--
|
||||
2 files changed, 33 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..d1bc596 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -133,6 +133,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setcfact, {.f = +0.25f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, setcfact, {.f = -0.25f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, setcfact, {.f = 0.0f} },
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 145fd01..68e35d2 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -140,6 +140,7 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ float cweight;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -318,6 +319,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
static void resize(Client *c, struct wlr_box geo, int interact);
|
||||
static void run(char *startup_cmd);
|
||||
+static void setcfact(const Arg *arg);
|
||||
static void setcursor(struct wl_listener *listener, void *data);
|
||||
static void setcursorshape(struct wl_listener *listener, void *data);
|
||||
static void setfloating(Client *c, int floating);
|
||||
@@ -1041,6 +1043,7 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
c = xdg_surface->data = ecalloc(1, sizeof(*c));
|
||||
c->surface.xdg = xdg_surface;
|
||||
c->bw = borderpx;
|
||||
+ c->cweight = 1.0;
|
||||
|
||||
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
@@ -2218,6 +2221,19 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
+void
|
||||
+setcfact(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+
|
||||
+ if(!arg || !sel || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+ sel->cweight = (float) (arg->f ? sel->cweight + arg->f : 1.0);
|
||||
+ if (sel->cweight < 0)
|
||||
+ sel->cweight = 0;
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2637,6 +2653,7 @@ tile(Monitor *m)
|
||||
{
|
||||
unsigned int mw, my, ty;
|
||||
int i, n = 0;
|
||||
+ float mweight = 0, tweight = 0;
|
||||
Client *c;
|
||||
|
||||
wl_list_for_each(c, &clients, link)
|
||||
@@ -2649,17 +2666,27 @@ tile(Monitor *m)
|
||||
mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0;
|
||||
else
|
||||
mw = m->w.width;
|
||||
+ i = 0;
|
||||
+ wl_list_for_each(c, &clients, link){
|
||||
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ continue;
|
||||
+ if (i < m->nmaster)
|
||||
+ mweight += c->cweight;
|
||||
+ else
|
||||
+ tweight += c->cweight;
|
||||
+ i++;
|
||||
+ }
|
||||
i = my = ty = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
|
||||
- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
|
||||
+ .height = (int) ((c->cweight / mweight) * m->w.height)}, 0);
|
||||
my += c->geom.height;
|
||||
} else {
|
||||
resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
|
||||
- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
|
||||
+ .width = m->w.width - mw, .height = (int) ((c->cweight / tweight) * m->w.height) }, 0);
|
||||
ty += c->geom.height;
|
||||
}
|
||||
i++;
|
||||
@@ -3047,6 +3074,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
||||
c->surface.xwayland = xsurface;
|
||||
c->type = X11;
|
||||
c->bw = client_is_unmanaged(c) ? 0 : borderpx;
|
||||
+ c->cweight = 1.0;
|
||||
|
||||
/* Listen to the various events it can emit */
|
||||
LISTEN(&xsurface->events.associate, &c->associate, associatex11);
|
||||
--
|
||||
2.45.2
|
||||
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
From 31d0ceb3f7dea83282e61e556d71d06b7f43d753 Mon Sep 17 00:00:00 2001
|
||||
From: Gavin M <git@gavinm.us>
|
||||
Date: Sat, 16 Nov 2024 08:47:02 -0500
|
||||
Subject: [PATCH] Add cfact to gaps
|
||||
|
||||
---
|
||||
config.def.h | 3 +++
|
||||
dwl.c | 63 +++++++++++++++++++++++++++++++++++++++++-----------
|
||||
2 files changed, 53 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index b388b4e..a871364 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -136,6 +136,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setcfact, {.f = +0.25f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, setcfact, {.f = -0.25f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, setcfact, {.f = 0.0f} },
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY, XKB_KEY_g, togglegaps, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index dc851df..b5313c1 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -140,6 +140,7 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ float cweight;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -319,6 +320,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
static void resize(Client *c, struct wlr_box geo, int interact);
|
||||
static void run(char *startup_cmd);
|
||||
+static void setcfact(const Arg *arg);
|
||||
static void setcursor(struct wl_listener *listener, void *data);
|
||||
static void setcursorshape(struct wl_listener *listener, void *data);
|
||||
static void setfloating(Client *c, int floating);
|
||||
@@ -1045,6 +1047,7 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
c = xdg_surface->data = ecalloc(1, sizeof(*c));
|
||||
c->surface.xdg = xdg_surface;
|
||||
c->bw = borderpx;
|
||||
+ c->cweight = 1.0;
|
||||
|
||||
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
@@ -2223,6 +2226,19 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
+void
|
||||
+setcfact(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+
|
||||
+ if(!arg || !sel || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+ sel->cweight = (float) (arg->f ? sel->cweight + arg->f : 1.0);
|
||||
+ if (sel->cweight < 0)
|
||||
+ sel->cweight = 0;
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2642,38 +2658,58 @@ tagmon(const Arg *arg)
|
||||
void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
- unsigned int h, r, e = m->gaps, mw, my, ty;
|
||||
+ unsigned int e = m->gaps, mw, my, ty;
|
||||
int i, n = 0;
|
||||
- Client *c;
|
||||
+ float mweight = 0, tweight = 0;
|
||||
+ Client *c, *sel = NULL;
|
||||
+
|
||||
+ wl_list_for_each(c, &fstack, flink) {
|
||||
+ if (VISIBLEON(c, m) && !c->isfullscreen) {
|
||||
+ if (!sel)
|
||||
+ sel = c;
|
||||
+ if (!c->isfloating)
|
||||
+ n++;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- wl_list_for_each(c, &clients, link)
|
||||
- if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
|
||||
- n++;
|
||||
if (n == 0)
|
||||
return;
|
||||
+
|
||||
if (smartgaps == n)
|
||||
e = 0;
|
||||
|
||||
if (n > m->nmaster)
|
||||
mw = m->nmaster ? (int)roundf((m->w.width + gappx*e) * m->mfact) : 0;
|
||||
else
|
||||
- mw = m->w.width;
|
||||
+ mw = m->w.width - gappx*e;
|
||||
+
|
||||
+ i = 0;
|
||||
+ wl_list_for_each(c, &clients, link){
|
||||
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ continue;
|
||||
+ if (i < m->nmaster)
|
||||
+ mweight += c->cweight;
|
||||
+ else
|
||||
+ tweight += c->cweight;
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
i = 0;
|
||||
my = ty = gappx*e;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
- r = MIN(n, m->nmaster) - i;
|
||||
- h = (m->w.height - my - gappx*e - gappx*e * (r - 1)) / r;
|
||||
resize(c, (struct wlr_box){.x = m->w.x + gappx*e, .y = m->w.y + my,
|
||||
- .width = mw - 2*gappx*e, .height = h}, 0);
|
||||
+ .width = mw - gappx*e,
|
||||
+ .height = (int)((c->cweight / mweight) * (float)(m->w.height - gappx*e)) - gappx*e
|
||||
+ }, 0);
|
||||
my += c->geom.height + gappx*e;
|
||||
} else {
|
||||
- r = n - i;
|
||||
- h = (m->w.height - ty - gappx*e - gappx*e * (r - 1)) / r;
|
||||
- resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
|
||||
- .width = m->w.width - mw - gappx*e, .height = h}, 0);
|
||||
+ resize(c, (struct wlr_box){.x = m->w.x + mw + gappx*e, .y = m->w.y + ty,
|
||||
+ .width = m->w.width - mw - 2*gappx*e,
|
||||
+ .height = (int)((c->cweight / tweight) * (float)(m->w.height - gappx*e)) - gappx*e
|
||||
+ }, 0);
|
||||
ty += c->geom.height + gappx*e;
|
||||
}
|
||||
i++;
|
||||
@@ -3068,6 +3104,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
||||
c->surface.xwayland = xsurface;
|
||||
c->type = X11;
|
||||
c->bw = client_is_unmanaged(c) ? 0 : borderpx;
|
||||
+ c->cweight = 1.0;
|
||||
|
||||
/* Listen to the various events it can emit */
|
||||
LISTEN(&xsurface->events.associate, &c->associate, associatex11);
|
||||
--
|
||||
2.47.0
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
From e82e15860c36a70539625b8fe7b4bd54d0721705 Mon Sep 17 00:00:00 2001
|
||||
From: Palanix <palanixyt@gmail.com>
|
||||
Date: Fri, 24 Nov 2023 21:16:56 +0100
|
||||
Subject: [PATCH] cweights to allow different size clients in normal layouts
|
||||
|
||||
---
|
||||
config.def.h | 3 +++
|
||||
dwl.c | 32 ++++++++++++++++++++++++++++++--
|
||||
2 files changed, 33 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..d1bc596 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -133,6 +133,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setcfact, {.f = +0.25f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, setcfact, {.f = -0.25f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, setcfact, {.f = 0.0f} },
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 5bf995e..5a17343 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -141,6 +141,7 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ float cweight;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -322,6 +323,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
static void resize(Client *c, struct wlr_box geo, int interact);
|
||||
static void run(char *startup_cmd);
|
||||
+static void setcfact(const Arg *arg);
|
||||
static void setcursor(struct wl_listener *listener, void *data);
|
||||
static void setcursorshape(struct wl_listener *listener, void *data);
|
||||
static void setfloating(Client *c, int floating);
|
||||
@@ -1060,6 +1062,7 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
c = toplevel->base->data = ecalloc(1, sizeof(*c));
|
||||
c->surface.xdg = toplevel->base;
|
||||
c->bw = borderpx;
|
||||
+ c->cweight = 1.0;
|
||||
|
||||
LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify);
|
||||
LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify);
|
||||
@@ -2268,6 +2271,19 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
+void
|
||||
+setcfact(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+
|
||||
+ if(!arg || !sel || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+ sel->cweight = (float) (arg->f ? sel->cweight + arg->f : 1.0);
|
||||
+ if (sel->cweight < 0)
|
||||
+ sel->cweight = 0;
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2692,6 +2708,7 @@ tile(Monitor *m)
|
||||
{
|
||||
unsigned int mw, my, ty;
|
||||
int i, n = 0;
|
||||
+ float mweight = 0, tweight = 0;
|
||||
Client *c;
|
||||
|
||||
wl_list_for_each(c, &clients, link)
|
||||
@@ -2704,17 +2721,27 @@ tile(Monitor *m)
|
||||
mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0;
|
||||
else
|
||||
mw = m->w.width;
|
||||
+ i = 0;
|
||||
+ wl_list_for_each(c, &clients, link){
|
||||
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ continue;
|
||||
+ if (i < m->nmaster)
|
||||
+ mweight += c->cweight;
|
||||
+ else
|
||||
+ tweight += c->cweight;
|
||||
+ i++;
|
||||
+ }
|
||||
i = my = ty = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
|
||||
- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
|
||||
+ .height = (int) ((c->cweight / mweight) * m->w.height)}, 0);
|
||||
my += c->geom.height;
|
||||
} else {
|
||||
resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
|
||||
- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
|
||||
+ .width = m->w.width - mw, .height = (int) ((c->cweight / tweight) * m->w.height) }, 0);
|
||||
ty += c->geom.height;
|
||||
}
|
||||
i++;
|
||||
@@ -3102,6 +3129,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
||||
c->surface.xwayland = xsurface;
|
||||
c->type = X11;
|
||||
c->bw = client_is_unmanaged(c) ? 0 : borderpx;
|
||||
+ c->cweight = 1.0;
|
||||
|
||||
/* Listen to the various events it can emit */
|
||||
LISTEN(&xsurface->events.associate, &c->associate, associatex11);
|
||||
--
|
||||
2.45.2
|
||||
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
From 98fe302cd240b519c28c886250273854844ab2c7 Mon Sep 17 00:00:00 2001
|
||||
From: Palanix <palanixyt@gmail.com>
|
||||
Date: Fri, 24 Nov 2023 21:16:56 +0100
|
||||
Subject: [PATCH] cweights to allow different size clients in normal layouts
|
||||
|
||||
---
|
||||
config.def.h | 3 +++
|
||||
dwl.c | 32 ++++++++++++++++++++++++++++++--
|
||||
2 files changed, 33 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 9009517..27ff521 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -128,6 +128,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setcfact, {.f = +0.25f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, setcfact, {.f = -0.25f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, setcfact, {.f = 0.0f} },
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index fa76db2..9bdb438 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -136,6 +136,7 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
+ float cweight;
|
||||
} Client;
|
||||
|
||||
typedef struct {
|
||||
@@ -301,6 +302,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
static void resize(Client *c, struct wlr_box geo, int interact);
|
||||
static void run(char *startup_cmd);
|
||||
+static void setcfact(const Arg *arg);
|
||||
static void setcursor(struct wl_listener *listener, void *data);
|
||||
static void setcursorshape(struct wl_listener *listener, void *data);
|
||||
static void setfloating(Client *c, int floating);
|
||||
@@ -956,6 +958,7 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
c = xdg_surface->data = ecalloc(1, sizeof(*c));
|
||||
c->surface.xdg = xdg_surface;
|
||||
c->bw = borderpx;
|
||||
+ c->cweight = 1.0;
|
||||
|
||||
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
@@ -2009,6 +2012,19 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
+void
|
||||
+setcfact(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+
|
||||
+ if(!arg || !sel || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+ sel->cweight = (float) (arg->f ? sel->cweight + arg->f : 1.0);
|
||||
+ if (sel->cweight < 0)
|
||||
+ sel->cweight = 0;
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2468,6 +2484,7 @@ tile(Monitor *m)
|
||||
{
|
||||
unsigned int mw, my, ty;
|
||||
int i, n = 0;
|
||||
+ float mweight = 0, tweight = 0;
|
||||
Client *c;
|
||||
|
||||
wl_list_for_each(c, &clients, link)
|
||||
@@ -2480,17 +2497,27 @@ tile(Monitor *m)
|
||||
mw = m->nmaster ? ROUND(m->w.width * m->mfact) : 0;
|
||||
else
|
||||
mw = m->w.width;
|
||||
+ i = 0;
|
||||
+ wl_list_for_each(c, &clients, link){
|
||||
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ continue;
|
||||
+ if (i < m->nmaster)
|
||||
+ mweight += c->cweight;
|
||||
+ else
|
||||
+ tweight += c->cweight;
|
||||
+ i++;
|
||||
+ }
|
||||
i = my = ty = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (i < m->nmaster) {
|
||||
resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + my, .width = mw,
|
||||
- .height = (m->w.height - my) / (MIN(n, m->nmaster) - i)}, 0);
|
||||
+ .height = (int) ((c->cweight / mweight) * m->w.height)}, 0);
|
||||
my += c->geom.height;
|
||||
} else {
|
||||
resize(c, (struct wlr_box){.x = m->w.x + mw, .y = m->w.y + ty,
|
||||
- .width = m->w.width - mw, .height = (m->w.height - ty) / (n - i)}, 0);
|
||||
+ .width = m->w.width - mw, .height = (int) ((c->cweight / tweight) * m->w.height) }, 0);
|
||||
ty += c->geom.height;
|
||||
}
|
||||
i++;
|
||||
@@ -2872,6 +2899,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
||||
c->surface.xwayland = xsurface;
|
||||
c->type = X11;
|
||||
c->bw = borderpx;
|
||||
+ c->cweight = 1.0;
|
||||
|
||||
/* Listen to the various events it can emit */
|
||||
LISTEN(&xsurface->events.associate, &c->associate, associatex11);
|
||||
--
|
||||
2.43.1
|
||||
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
### Description
|
||||
Implements chained keybindings (like the dwm
|
||||
[keychain](https://dwm.suckless.org/patches/keychain/) patch).
|
||||
|
||||
Bindings can share a leading chain key. This chain key will be triggered when
|
||||
Mod+chain is pressed. A subsequent keypress will be matched against bindings
|
||||
for that chain key. If it is configured the action will be triggered, otherwise
|
||||
the keypress will be ignored.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/bencc/dwl/src/branch/chainkeys)
|
||||
- [2024-05-20](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/chainkeys/chainkeys.patch)
|
||||
|
||||
### Authors
|
||||
- [Ben Collerson](https://codeberg.org/bencc)
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
From 226e204ec7fb6d6840a984ef8e8ec1d2514e985f Mon Sep 17 00:00:00 2001
|
||||
From: Ben Collerson <benc@benc.cc>
|
||||
Date: Tue, 2 Jan 2024 10:33:59 +1000
|
||||
Subject: [PATCH] chainkeys
|
||||
|
||||
---
|
||||
config.def.h | 62 ++++++++++++++++++++++++++--------------------------
|
||||
dwl.c | 23 ++++++++++++++++++-
|
||||
2 files changed, 53 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8f498d2f..1c182547 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -105,10 +105,10 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
|
||||
#define MODKEY WLR_MODIFIER_ALT
|
||||
|
||||
#define TAGKEYS(KEY,SKEY,TAG) \
|
||||
- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||
- { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \
|
||||
- { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
|
||||
+ { MODKEY, -1, KEY, view, {.ui = 1 << TAG} }, \
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, -1, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, -1, SKEY, tag, {.ui = 1 << TAG} }, \
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,-1,SKEY,toggletag, {.ui = 1 << TAG} }
|
||||
|
||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||
@@ -119,30 +119,30 @@ static const char *menucmd[] = { "wmenu-run", NULL };
|
||||
|
||||
static const Key keys[] = {
|
||||
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
|
||||
- /* modifier key function argument */
|
||||
- { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||
- { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||
- { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||
- { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||
- { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
- { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
- { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} },
|
||||
- { MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
- { MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
|
||||
- { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
- { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
- { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
- { MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
- { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
- { MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
- { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
- { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
+ /* modifier chain, key function argument */
|
||||
+ { MODKEY, -1, XKB_KEY_p, spawn, {.v = menucmd} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||
+ { MODKEY, -1, XKB_KEY_j, focusstack, {.i = +1} },
|
||||
+ { MODKEY, -1, XKB_KEY_k, focusstack, {.i = -1} },
|
||||
+ { MODKEY, -1, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||
+ { MODKEY, -1, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
+ { MODKEY, -1, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
+ { MODKEY, -1, XKB_KEY_l, setmfact, {.f = +0.05f} },
|
||||
+ { MODKEY, -1, XKB_KEY_Return, zoom, {0} },
|
||||
+ { MODKEY, -1, XKB_KEY_Tab, view, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_C, killclient, {0} },
|
||||
+ { MODKEY, -1, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
+ { MODKEY, -1, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
+ { MODKEY, -1, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
+ { MODKEY, -1, XKB_KEY_space, setlayout, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_space, togglefloating, {0} },
|
||||
+ { MODKEY, -1, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, -1, XKB_KEY_0, view, {.ui = ~0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
+ { MODKEY, -1, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
+ { MODKEY, -1, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||
@@ -152,14 +152,14 @@ static const Key keys[] = {
|
||||
TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6),
|
||||
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
|
||||
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
|
||||
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, -1, XKB_KEY_Q, quit, {0} },
|
||||
|
||||
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
|
||||
- { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },
|
||||
+ { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,-1,XKB_KEY_Terminate_Server, quit, {0} },
|
||||
/* Ctrl-Alt-Fx is used to switch to another VT, if you don't know what a VT is
|
||||
* do not remove them.
|
||||
*/
|
||||
-#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} }
|
||||
+#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,-1,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} }
|
||||
CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6),
|
||||
CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12),
|
||||
};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763dfc..05e667f8 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -143,6 +143,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
uint32_t mod;
|
||||
+ int chain;
|
||||
xkb_keysym_t keysym;
|
||||
void (*func)(const Arg *);
|
||||
const Arg arg;
|
||||
@@ -353,6 +354,7 @@ static const char broken[] = "broken";
|
||||
static pid_t child_pid = -1;
|
||||
static int locked;
|
||||
static void *exclusive_focus;
|
||||
+static int chainkey = -1;
|
||||
static struct wl_display *dpy;
|
||||
static struct wlr_backend *backend;
|
||||
static struct wlr_scene *scene;
|
||||
@@ -1438,11 +1440,30 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
||||
const Key *k;
|
||||
for (k = keys; k < END(keys); k++) {
|
||||
if (CLEANMASK(mods) == CLEANMASK(k->mod)
|
||||
- && sym == k->keysym && k->func) {
|
||||
+ && sym == k->keysym
|
||||
+ && chainkey == -1
|
||||
+ && k->chain == -1
|
||||
+ && k->func) {
|
||||
k->func(&k->arg);
|
||||
return 1;
|
||||
}
|
||||
+ else if (sym == k->keysym
|
||||
+ && chainkey != -1
|
||||
+ && k->chain == chainkey
|
||||
+ && k->func) {
|
||||
+ k->func(&k->arg);
|
||||
+ chainkey = -1;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ else if (CLEANMASK(mods) == CLEANMASK(k->mod)
|
||||
+ && k->chain == (int)sym
|
||||
+ && chainkey == -1
|
||||
+ && k->func) {
|
||||
+ chainkey = sym;
|
||||
+ return 1;
|
||||
+ }
|
||||
}
|
||||
+ chainkey = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
### Description
|
||||
This patch adds default transparency parameters to config.h which specify the starting transparencies of all windows.
|
||||
|
||||
It also adds opacities to the ruleset, enabling override of the opacities on a per client basis.
|
||||
|
||||
Additionally, it adds some shortcuts:
|
||||
```
|
||||
[MODKEY]+[o] -> increase focus opacity of currently focused window
|
||||
[MODKEY]+[Shift]+[o] -> decrease focus opacity of currently focused window
|
||||
```
|
||||
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/sevz/dwl/src/branch/client-opacity)
|
||||
- [2025-01-20](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/client-opacity/client-opacity.patch)
|
||||
|
||||
### Authors
|
||||
- [sevz](https://codeberg.org/sevz)
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
From ba3172875d379ff4f2db69753f50067cecfc8293 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||
<leohdz172@proton.me>
|
||||
Date: Tue, 25 Jul 2023 12:48:22 -0600
|
||||
Subject: [PATCH] add default transparency for windows and rules for override
|
||||
the transparency
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
|
||||
---
|
||||
config.def.h | 9 ++++++---
|
||||
dwl.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 45 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171d..0eb86874 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
+static const float default_opacity = 0.75;
|
||||
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
#define TAGCOUNT (9)
|
||||
@@ -22,10 +23,10 @@ static int log_level = WLR_ERROR;
|
||||
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
- /* app_id title tags mask isfloating monitor */
|
||||
+ /* app_id title tags mask isfloating alpha monitor */
|
||||
/* examples: */
|
||||
- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
|
||||
+ { "Gimp_EXAMPLE", NULL, 0, 1, default_opacity, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
+ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 1.0, -1 }, /* Start on ONLY tag "9" */
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
@@ -133,6 +134,8 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} },
|
||||
+ { MODKEY, XKB_KEY_o, setopacity, {.f = +0.1f} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, setopacity, {.f = -0.1f} },
|
||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ad21e1ba..0554fcdf 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -138,6 +138,7 @@ typedef struct {
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
+ float opacity;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -227,6 +228,7 @@ typedef struct {
|
||||
const char *title;
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
+ float opacity;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -319,6 +321,7 @@ static void requeststartdrag(struct wl_listener *listener, void *data);
|
||||
static void requestmonstate(struct wl_listener *listener, void *data);
|
||||
static void resize(Client *c, struct wlr_box geo, int interact);
|
||||
static void run(char *startup_cmd);
|
||||
+static void scenebuffersetopacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data);
|
||||
static void setcursor(struct wl_listener *listener, void *data);
|
||||
static void setcursorshape(struct wl_listener *listener, void *data);
|
||||
static void setfloating(Client *c, int floating);
|
||||
@@ -326,6 +329,7 @@ static void setfullscreen(Client *c, int fullscreen);
|
||||
static void setlayout(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
static void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||
+static void setopacity(const Arg *arg);
|
||||
static void setpsel(struct wl_listener *listener, void *data);
|
||||
static void setsel(struct wl_listener *listener, void *data);
|
||||
static void setup(void);
|
||||
@@ -491,6 +495,7 @@ applyrules(Client *c)
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
c->isfloating = r->isfloating;
|
||||
+ c->opacity = r->opacity;
|
||||
newtags |= r->tags;
|
||||
i = 0;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
@@ -499,6 +504,8 @@ applyrules(Client *c)
|
||||
}
|
||||
}
|
||||
}
|
||||
+ if (c->scene_surface)
|
||||
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c);
|
||||
setmon(c, mon, newtags);
|
||||
}
|
||||
|
||||
@@ -874,6 +881,9 @@ commitnotify(struct wl_listener *listener, void *data)
|
||||
|
||||
resize(c, c->geom, (c->isfloating && !c->isfullscreen));
|
||||
|
||||
+ if (c->scene_surface)
|
||||
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c);
|
||||
+
|
||||
/* mark a pending resize as completed */
|
||||
if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
|
||||
c->resize = 0;
|
||||
@@ -1120,6 +1130,7 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
c = toplevel->base->data = ecalloc(1, sizeof(*c));
|
||||
c->surface.xdg = toplevel->base;
|
||||
c->bw = borderpx;
|
||||
+ c->opacity = default_opacity;
|
||||
|
||||
LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify);
|
||||
LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify);
|
||||
@@ -2285,6 +2296,15 @@ run(char *startup_cmd)
|
||||
wl_display_run(dpy);
|
||||
}
|
||||
|
||||
+void
|
||||
+scenebuffersetopacity(struct wlr_scene_buffer *buffer, int sx, int sy, void *data)
|
||||
+{
|
||||
+ Client *c = data;
|
||||
+ /* xdg-popups are children of Client.scene, we do not have to worry about
|
||||
+ messing with them. */
|
||||
+ wlr_scene_buffer_set_opacity(buffer, c->isfullscreen ? 1 : c->opacity);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setcursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2353,6 +2373,7 @@ setfullscreen(Client *c, int fullscreen)
|
||||
* client positions are set by the user and cannot be recalculated */
|
||||
resize(c, c->prev, 0);
|
||||
}
|
||||
+ wlr_scene_node_for_each_buffer(&c->scene_surface->node, scenebuffersetopacity, c);
|
||||
arrange(c->mon);
|
||||
printstatus();
|
||||
}
|
||||
@@ -2409,6 +2430,23 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
|
||||
focusclient(focustop(selmon), 1);
|
||||
}
|
||||
|
||||
+void
|
||||
+setopacity(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ if (!sel)
|
||||
+ return;
|
||||
+
|
||||
+ sel->opacity += arg->f;
|
||||
+ if (sel->opacity > 1.0)
|
||||
+ sel->opacity = 1.0f;
|
||||
+
|
||||
+ if (sel->opacity < 0.1)
|
||||
+ sel->opacity = 0.1f;
|
||||
+
|
||||
+ wlr_scene_node_for_each_buffer(&sel->scene_surface->node, scenebuffersetopacity, sel);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setpsel(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -3120,6 +3158,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
||||
c->surface.xwayland = xsurface;
|
||||
c->type = X11;
|
||||
c->bw = client_is_unmanaged(c) ? 0 : borderpx;
|
||||
+ c->opacity = default_opacity;
|
||||
|
||||
/* Listen to the various events it can emit */
|
||||
LISTEN(&xsurface->events.associate, &c->associate, associatex11);
|
||||
--
|
||||
2.48.0
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
### Description
|
||||
A column layout patch. This patch just puts the visible clients into equal-width columns on the screen.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/bencc/dwl/src/branch/column)
|
||||
- [2024-01-02](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/column/column.patch)
|
||||
|
||||
### Authors
|
||||
- [Ben Collerson](https://codeberg.org/bencc)
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
From d1eb2061c619d0bbd7a0ecda0fe77409f3a6c399 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Collerson <benc@benc.cc>
|
||||
Date: Fri, 29 Dec 2023 19:02:11 +1000
|
||||
Subject: [PATCH] column layout
|
||||
|
||||
---
|
||||
config.def.h | 2 ++
|
||||
dwl.c | 28 ++++++++++++++++++++++++++++
|
||||
2 files changed, 30 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index a8ed61d9..edb30cae 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -34,6 +34,7 @@ static const Layout layouts[] = {
|
||||
{ "[]=", tile },
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
+ { "||", col },
|
||||
};
|
||||
|
||||
/* monitors */
|
||||
@@ -134,6 +135,7 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
+ { MODKEY, XKB_KEY_c, setlayout, {.v = &layouts[3]} },
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 4d19357f..63d80da7 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -243,6 +243,7 @@ static void checkidleinhibitor(struct wlr_surface *exclude);
|
||||
static void cleanup(void);
|
||||
static void cleanupmon(struct wl_listener *listener, void *data);
|
||||
static void closemon(Monitor *m);
|
||||
+static void col(Monitor *m);
|
||||
static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
|
||||
static void commitnotify(struct wl_listener *listener, void *data);
|
||||
static void createdecoration(struct wl_listener *listener, void *data);
|
||||
@@ -704,6 +705,33 @@ closemon(Monitor *m)
|
||||
printstatus();
|
||||
}
|
||||
|
||||
+void
|
||||
+col(Monitor *m)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ unsigned int n = 0, i = 0;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
|
||||
+ n++;
|
||||
+
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
+ continue;
|
||||
+ resize(
|
||||
+ c,
|
||||
+ (struct wlr_box){
|
||||
+ .x = m->w.x + i * m->w.width / n,
|
||||
+ .y = m->w.y,
|
||||
+ .width = m->w.width / n,
|
||||
+ .height = m->w.height
|
||||
+ },
|
||||
+ 0
|
||||
+ );
|
||||
+ i++;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void
|
||||
commitlayersurfacenotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
--
|
||||
2.43.0
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
### Description
|
||||
Generate a coredump if dwl exited abnormally (to be more usefull you need to
|
||||
compile dwl and wlroots with debug symbols)
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/sevz/dwl/src/branch/coredump)
|
||||
- [main 2025-01-20](/dwl/dwl-patches/raw/branch/main/patches/coredump/coredump.patch)
|
||||
- [coredump-0.7.patch](/dwl/dwl-patches/raw/branch/main/patches/coredump/coredump-0.7.patch)
|
||||
|
||||
### Authors
|
||||
- [sevz](https://codeberg.org/sevz)
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
From 2abde87f9159ec3318a0489ac0ed512f166ef8c8 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||
<leohdz172@proton.me>
|
||||
Date: Wed, 5 Oct 2022 23:07:13 -0500
|
||||
Subject: [PATCH] increase RLIMIT_CORE (generate a coredump)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
|
||||
---
|
||||
dwl.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index a2711f67..cfbb0bb8 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
+#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
@@ -358,6 +359,8 @@ static void zoom(const Arg *arg);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
+static struct rlimit oldrlimit;
|
||||
+static struct rlimit newrlimit;
|
||||
static pid_t child_pid = -1;
|
||||
static int locked;
|
||||
static void *exclusive_focus;
|
||||
@@ -2232,6 +2235,7 @@ run(char *startup_cmd)
|
||||
if ((child_pid = fork()) < 0)
|
||||
die("startup: fork:");
|
||||
if (child_pid == 0) {
|
||||
+ setrlimit(RLIMIT_CORE, &oldrlimit);
|
||||
setsid();
|
||||
dup2(piperw[0], STDIN_FILENO);
|
||||
close(piperw[0]);
|
||||
@@ -2649,6 +2653,7 @@ void
|
||||
spawn(const Arg *arg)
|
||||
{
|
||||
if (fork() == 0) {
|
||||
+ setrlimit(RLIMIT_CORE, &oldrlimit);
|
||||
dup2(STDERR_FILENO, STDOUT_FILENO);
|
||||
setsid();
|
||||
execvp(((char **)arg->v)[0], (char **)arg->v);
|
||||
@@ -3189,6 +3194,10 @@ main(int argc, char *argv[])
|
||||
char *startup_cmd = NULL;
|
||||
int c;
|
||||
|
||||
+ getrlimit(RLIMIT_CORE, &oldrlimit);
|
||||
+ newrlimit.rlim_cur = newrlimit.rlim_max = oldrlimit.rlim_max;
|
||||
+ setrlimit(RLIMIT_CORE, &newrlimit);
|
||||
+
|
||||
while ((c = getopt(argc, argv, "s:hdv")) != -1) {
|
||||
if (c == 's')
|
||||
startup_cmd = optarg;
|
||||
--
|
||||
2.46.0
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
From 6d5017888891957615160fe7c015adf7a6f0fd45 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||
<leohdz172@proton.me>
|
||||
Date: Wed, 5 Oct 2022 23:07:13 -0500
|
||||
Subject: [PATCH] increase RLIMIT_CORE (generate a coredump)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
|
||||
---
|
||||
dwl.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ad21e1ba..940fbeff 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
+#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
@@ -353,6 +354,8 @@ static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||
static void zoom(const Arg *arg);
|
||||
|
||||
/* variables */
|
||||
+static struct rlimit oldrlimit;
|
||||
+static struct rlimit newrlimit;
|
||||
static pid_t child_pid = -1;
|
||||
static int locked;
|
||||
static void *exclusive_focus;
|
||||
@@ -2248,6 +2251,7 @@ run(char *startup_cmd)
|
||||
if ((child_pid = fork()) < 0)
|
||||
die("startup: fork:");
|
||||
if (child_pid == 0) {
|
||||
+ setrlimit(RLIMIT_CORE, &oldrlimit);
|
||||
setsid();
|
||||
dup2(piperw[0], STDIN_FILENO);
|
||||
close(piperw[0]);
|
||||
@@ -2659,6 +2663,7 @@ void
|
||||
spawn(const Arg *arg)
|
||||
{
|
||||
if (fork() == 0) {
|
||||
+ setrlimit(RLIMIT_CORE, &oldrlimit);
|
||||
dup2(STDERR_FILENO, STDOUT_FILENO);
|
||||
setsid();
|
||||
execvp(((char **)arg->v)[0], (char **)arg->v);
|
||||
@@ -3178,6 +3183,10 @@ main(int argc, char *argv[])
|
||||
char *startup_cmd = NULL;
|
||||
int c;
|
||||
|
||||
+ getrlimit(RLIMIT_CORE, &oldrlimit);
|
||||
+ newrlimit.rlim_cur = newrlimit.rlim_max = oldrlimit.rlim_max;
|
||||
+ setrlimit(RLIMIT_CORE, &newrlimit);
|
||||
+
|
||||
while ((c = getopt(argc, argv, "s:hdv")) != -1) {
|
||||
if (c == 's')
|
||||
startup_cmd = optarg;
|
||||
--
|
||||
2.48.0
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
### Description
|
||||
Adds ability to change cursor's theme and size.
|
||||
|
||||
```c
|
||||
static const char *cursor_theme = NULL;
|
||||
static const char cursor_size[] = "24"; /* Make sure it's a valid integer, otherwise things will break */
|
||||
```
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/cursortheme)
|
||||
- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/13d96b51b54500dd24544cf3a73c61b7a1414bc6/patches/cursortheme/cursortheme.patch)
|
||||
- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/b828e21717fa584affeb3245359c3ab615759fa4/cursortheme/cursortheme.patch)
|
||||
- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/c676de59d51e613bd52ac46c77a24b1cac9a61a1/cursortheme/cursortheme.patch)
|
||||
|
||||
### Authors
|
||||
- [wochap](https://codeberg.org/wochap)
|
||||
- [egorguslyan](https://github.com/egorguslyan)
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
From f08376a2a04929a3907612e6c1f980ad3cdf939f Mon Sep 17 00:00:00 2001
|
||||
From: wochap <gean.marroquin@gmail.com>
|
||||
Date: Fri, 5 Jul 2024 11:10:39 -0500
|
||||
Subject: [PATCH] implement cursortheme
|
||||
|
||||
---
|
||||
config.def.h | 2 ++
|
||||
dwl.c | 8 ++++++--
|
||||
2 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..1f9ff56 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -13,6 +13,8 @@ static const float focuscolor[] = COLOR(0x005577ff);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
+static const char *cursor_theme = NULL;
|
||||
+static const char cursor_size[] = "24"; /* Make sure it's a valid integer, otherwise things will break */
|
||||
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
#define TAGCOUNT (9)
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index dc0437e..a91d42b 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -2522,8 +2522,12 @@ setup(void)
|
||||
* Xcursor themes to source cursor images from and makes sure that cursor
|
||||
* images are available at all scale factors on the screen (necessary for
|
||||
* HiDPI support). Scaled cursors will be loaded with each output. */
|
||||
- cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
|
||||
- setenv("XCURSOR_SIZE", "24", 1);
|
||||
+ cursor_mgr = wlr_xcursor_manager_create(cursor_theme, atoi(cursor_size));
|
||||
+ setenv("XCURSOR_SIZE", cursor_size, 1);
|
||||
+ if (cursor_theme)
|
||||
+ setenv("XCURSOR_THEME", cursor_theme, 1);
|
||||
+ else
|
||||
+ unsetenv("XCURSOR_THEME");
|
||||
|
||||
/*
|
||||
* wlr_cursor *only* displays an image on screen. It does not move around
|
||||
--
|
||||
2.45.1
|
||||
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
### Description
|
||||
Rules for floating windows support default x, y, width, height. Defaults to the center of the screen and the client size.
|
||||
|
||||
If the width or height is less than or equal to 1, then the value will be interpreted as a percentage. For example, 0.5 represents 50%, 0.25 represents 25%, and 1 represents 100%. **NOTE**: Some clients, like Thunar, have minimum width/height
|
||||
|
||||
The variable `center_relative_to_monitor` allows the user to choose whether to center relative to the monitor or relative to the window area.
|
||||
|
||||
<details>
|
||||
<summary>Explanation of center_relative_to_monitor:</summary>
|
||||
<pre>
|
||||
The "Monitor area" refers to the space enclosed by the green rectangle, while the "Window area" refers to the space enclosed by the red rectangle.
|
||||
<img src="https://i.imgur.com/xhejzPh.png"/>
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.5/customfloat)
|
||||
- [2024-07-09](https://codeberg.org/dwl/dwl-patches/raw/commit/13d96b51b54500dd24544cf3a73c61b7a1414bc6/patches/customfloat/customfloat.patch)
|
||||
- [2024-04-11](https://codeberg.org/dwl/dwl-patches/raw/commit/98cba933c9f4099202e54f39acbf17e05bde828a/customfloat/customfloat.patch)
|
||||
- [v0.5](https://codeberg.org/dwl/dwl-patches/raw/commit/bf098459219e7a473d8edb4c0435aeb6a4b82e38/customfloat/customfloat.patch)
|
||||
|
||||
### Authors
|
||||
- [wochap](https://codeberg.org/wochap)
|
||||
- [Stivvo](https://github.com/Stivvo)
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
From 4f19f5499610d56f2616da5d44039403ac9d4c06 Mon Sep 17 00:00:00 2001
|
||||
From: wochap <gean.marroquin@gmail.com>
|
||||
Date: Tue, 9 Jul 2024 10:52:37 -0500
|
||||
Subject: [PATCH] implement customfloat and generate patches
|
||||
|
||||
---
|
||||
config.def.h | 7 ++++---
|
||||
dwl.c | 27 +++++++++++++++++++++++++++
|
||||
2 files changed, 31 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..dee53f4 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
+static const int respect_monitor_reserved_area = 0; /* 1 to monitor center while respecting the monitor's reserved area, 0 to monitor center */
|
||||
|
||||
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||
#define TAGCOUNT (9)
|
||||
@@ -22,10 +23,10 @@ static int log_level = WLR_ERROR;
|
||||
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
- /* app_id title tags mask isfloating monitor */
|
||||
+ /* app_id title tags mask isfloating monitor x y width height */
|
||||
/* examples: */
|
||||
- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
|
||||
+ { "Gimp_EXAMPLE", NULL, 0, 1, -1, 0, 0, 1000, 0.75 }, /* Start on currently visible tags floating, not tiled */
|
||||
+ { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1, 0, 0, 0, 0 },/* Start on ONLY tag "9" */
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index dc0437e..be0340f 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -230,6 +230,10 @@ typedef struct {
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
int monitor;
|
||||
+ int x;
|
||||
+ int y;
|
||||
+ float w;
|
||||
+ float h;
|
||||
} Rule;
|
||||
|
||||
typedef struct {
|
||||
@@ -454,6 +458,11 @@ applyrules(Client *c)
|
||||
int i;
|
||||
const Rule *r;
|
||||
Monitor *mon = selmon, *m;
|
||||
+ int newwidth;
|
||||
+ int newheight;
|
||||
+ int newx;
|
||||
+ int newy;
|
||||
+ int apply_resize = 0;
|
||||
|
||||
c->isfloating = client_is_float_type(c);
|
||||
if (!(appid = client_get_appid(c)))
|
||||
@@ -471,9 +480,27 @@ applyrules(Client *c)
|
||||
if (r->monitor == i++)
|
||||
mon = m;
|
||||
}
|
||||
+ if (c->isfloating || !mon->lt[mon->sellt]->arrange) {
|
||||
+ /* client is floating or in floating layout */
|
||||
+ struct wlr_box b = respect_monitor_reserved_area ? mon->w : mon->m;
|
||||
+ newwidth = (int)round(r->w ? (r->w <= 1 ? b.width * r->w : r->w) : c->geom.width);
|
||||
+ newheight = (int)round(r->h ? (r->h <= 1 ? b.height * r->h : r->h) : c->geom.height);
|
||||
+ newx = (int)round(r->x ? (r->x <= 1 ? b.width * r->x + b.x : r->x + b.x) : c->geom.x);
|
||||
+ newy = (int)round(r->y ? (r->y <= 1 ? b.height * r->y + b.y : r->y + b.y) : c->geom.y);
|
||||
+ apply_resize = 1;
|
||||
+
|
||||
+ }
|
||||
}
|
||||
}
|
||||
setmon(c, mon, newtags);
|
||||
+ if (apply_resize) {
|
||||
+ resize(c, (struct wlr_box){
|
||||
+ .x = newx,
|
||||
+ .y = newy,
|
||||
+ .width = newwidth,
|
||||
+ .height = newheight,
|
||||
+ }, 1);
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
--
|
||||
2.45.1
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
### Description
|
||||
Implements dimming of clients which are unfocused.
|
||||
|
||||
The code also allows any color dimming. There is also an additional option in `Rule`, which allows you to keep the client `neverdim`, that is, as if it is focused.
|
||||
|
||||
There are also two functions that can be bound to a `Key` or `Button`,
|
||||
1. `toggledimming`: Which toggles dimming for all windows (except for `Rule`s)
|
||||
2. `toggledimmingclient`: Which toggles dimming for the focused window, as if the client had `neverdim` applied to it. This overwrites an applied `Rule`.
|
||||
|
||||
### Download
|
||||
- [2024-09-18](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused.patch)
|
||||
- [2024-09-03](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused-20240903.patch)
|
||||
- [2024-07-14](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused-20240714.patch)
|
||||
- [2024-05-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused-20240516.patch)
|
||||
- [2024-04-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dim-unfocused/dim-unfocused-20240416.patch)
|
||||
- [git branch](https://codeberg.org/dhruva_sambrani/dwl/src/branch/dim-unfocused)
|
||||
|
||||
### Authors
|
||||
- [Dhruva Sambrani](https://codeberg.org/dhruva_sambrani)
|
||||
@@ -0,0 +1,213 @@
|
||||
From cd3b5580dbf38f54b54d5bfb6039e0039cbd6b21 Mon Sep 17 00:00:00 2001
|
||||
From: Dhruva Sambrani <44899822+DhruvaSambrani@users.noreply.github.com>
|
||||
Date: Thu, 16 May 2024 12:26:05 +0200
|
||||
Subject: [PATCH] clean git history
|
||||
|
||||
---
|
||||
client.h | 6 ++++++
|
||||
config.def.h | 13 ++++++++-----
|
||||
dwl.c | 40 +++++++++++++++++++++++++++++++++++-----
|
||||
3 files changed, 49 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/client.h b/client.h
|
||||
index 800b867..4d83248 100644
|
||||
--- a/client.h
|
||||
+++ b/client.h
|
||||
@@ -332,6 +332,12 @@ client_set_border_color(Client *c, const float color[static 4])
|
||||
wlr_scene_rect_set_color(c->border[i], color);
|
||||
}
|
||||
|
||||
+static inline void
|
||||
+client_set_dimmer_state(Client *c, const int dim)
|
||||
+{
|
||||
+ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim);
|
||||
+}
|
||||
+
|
||||
static inline void
|
||||
client_set_fullscreen(Client *c, int fullscreen)
|
||||
{
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8f498d2..d3950f9 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const float rootcolor[] = COLOR(0x222222ff);
|
||||
static const float bordercolor[] = COLOR(0x444444ff);
|
||||
static const float focuscolor[] = COLOR(0x005577ff);
|
||||
+static const float unfocuseddim[] = COLOR(0x00000088);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
@@ -21,10 +22,11 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
|
||||
static int log_level = WLR_ERROR;
|
||||
|
||||
static const Rule rules[] = {
|
||||
- /* app_id title tags mask isfloating monitor */
|
||||
- /* examples: */
|
||||
- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
|
||||
+ /* app_id title tags mask isfloating neverdim monitor */
|
||||
+ /* examples:
|
||||
+ { "Gimp_example", NULL, 0, 1, 0, -1 },
|
||||
+ */
|
||||
+ { "firefox_example", NULL, 1 << 8, 0, 1, -1 },
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
@@ -135,8 +137,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
+ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
- { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763df..ca88ad0 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -109,6 +109,7 @@ typedef struct {
|
||||
Monitor *mon;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
+ struct wlr_scene_rect *dimmer;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
@@ -137,7 +138,7 @@ typedef struct {
|
||||
#endif
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
- int isfloating, isurgent, isfullscreen;
|
||||
+ int isfloating, isurgent, isfullscreen, neverdim;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -227,6 +228,7 @@ typedef struct {
|
||||
const char *title;
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
+ int neverdim;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -330,6 +332,7 @@ static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
+static void toggledimming(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
@@ -404,6 +407,7 @@ static struct wlr_output_layout *output_layout;
|
||||
static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
+static int DIMOPT = 1;
|
||||
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
@@ -462,6 +466,7 @@ applyrules(Client *c)
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
c->isfloating = r->isfloating;
|
||||
+ c->neverdim = r-> neverdim;
|
||||
newtags |= r->tags;
|
||||
i = 0;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
@@ -1267,8 +1272,10 @@ focusclient(Client *c, int lift)
|
||||
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
- if (!exclusive_focus && !seat->drag)
|
||||
+ if (!exclusive_focus && !seat->drag) {
|
||||
client_set_border_color(c, focuscolor);
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Deactivate old client if focus is changing */
|
||||
@@ -1286,7 +1293,7 @@ focusclient(Client *c, int lift)
|
||||
* and probably other clients */
|
||||
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
||||
client_set_border_color(old_c, bordercolor);
|
||||
-
|
||||
+ client_set_dimmer_state(old_c, 1);
|
||||
client_activate_surface(old, 0);
|
||||
}
|
||||
}
|
||||
@@ -1566,7 +1573,7 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is mapped, or ready to display on-screen. */
|
||||
Client *p = NULL;
|
||||
- Client *w, *c = wl_container_of(listener, c, map);
|
||||
+ Client *w, *d, *c = wl_container_of(listener, c, map);
|
||||
Monitor *m;
|
||||
int i;
|
||||
|
||||
@@ -1599,6 +1606,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->border[i]->node.data = c;
|
||||
}
|
||||
|
||||
+ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim);
|
||||
+ c->dimmer->node.data = c;
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+
|
||||
/* Initialize client geometry with room for border */
|
||||
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
||||
c->geom.width += 2 * c->bw;
|
||||
@@ -1617,6 +1628,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
setmon(c, p->mon, p->tags);
|
||||
} else {
|
||||
applyrules(c);
|
||||
+ d = focustop(selmon);
|
||||
+ if (d) {
|
||||
+ client_set_dimmer_state(d, 0);
|
||||
+ }
|
||||
}
|
||||
printstatus();
|
||||
|
||||
@@ -2040,7 +2055,7 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
c->geom = geo;
|
||||
applybounds(c, bbox);
|
||||
|
||||
- /* Update scene-graph, including borders */
|
||||
+ /* Update scene-graph, including borders and dimmer*/
|
||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||
wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
|
||||
@@ -2050,6 +2065,8 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
|
||||
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
+ wlr_scene_rect_set_size(c->dimmer, c->geom.width, c-> geom.height);
|
||||
+ wlr_scene_node_set_position(&c->dimmer->node, 0, 0);
|
||||
|
||||
/* this is a no-op if size hasn't changed */
|
||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
@@ -2603,6 +2620,19 @@ tile(Monitor *m)
|
||||
}
|
||||
}
|
||||
|
||||
+void toggledimming(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ DIMOPT ^= 1;
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ {
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+ }
|
||||
+ c = focustop(selmon);
|
||||
+ if (c)
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+}
|
||||
+
|
||||
void
|
||||
togglefloating(const Arg *arg)
|
||||
{
|
||||
--
|
||||
2.45.1
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
diff --git a/client.h b/client.h
|
||||
index 800b867..4d83248 100644
|
||||
--- a/client.h
|
||||
+++ b/client.h
|
||||
@@ -332,6 +332,12 @@ client_set_border_color(Client *c, const float color[static 4])
|
||||
wlr_scene_rect_set_color(c->border[i], color);
|
||||
}
|
||||
|
||||
+static inline void
|
||||
+client_set_dimmer_state(Client *c, const int dim)
|
||||
+{
|
||||
+ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim);
|
||||
+}
|
||||
+
|
||||
static inline void
|
||||
client_set_fullscreen(Client *c, int fullscreen)
|
||||
{
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 8847e58..36ac2a1 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const float rootcolor[] = COLOR(0x222222ff);
|
||||
static const float bordercolor[] = COLOR(0x444444ff);
|
||||
static const float focuscolor[] = COLOR(0x005577ff);
|
||||
+static const float unfocuseddim[] = COLOR(0x00000088);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
@@ -21,10 +22,11 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
|
||||
static int log_level = WLR_ERROR;
|
||||
|
||||
static const Rule rules[] = {
|
||||
- /* app_id title tags mask isfloating monitor */
|
||||
- /* examples: */
|
||||
- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
|
||||
+ /* app_id title tags mask isfloating neverdim monitor */
|
||||
+ /* examples:
|
||||
+ { "Gimp_example", NULL, 0, 1, 0, -1 },
|
||||
+ */
|
||||
+ { "firefox_example", NULL, 1 << 8, 0, 1, -1 },
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
@@ -135,8 +137,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
+ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
- { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763df..abd7112 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -109,6 +109,7 @@ typedef struct {
|
||||
Monitor *mon;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
+ struct wlr_scene_rect *dimmer;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
@@ -137,7 +138,7 @@ typedef struct {
|
||||
#endif
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
- int isfloating, isurgent, isfullscreen;
|
||||
+ int isfloating, isurgent, isfullscreen, neverdim;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -227,6 +228,7 @@ typedef struct {
|
||||
const char *title;
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
+ int neverdim;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -330,6 +332,7 @@ static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
+static void toggledimming(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
@@ -404,6 +407,7 @@ static struct wlr_output_layout *output_layout;
|
||||
static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
+static int DIMOPT = 1;
|
||||
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
@@ -462,6 +466,7 @@ applyrules(Client *c)
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
c->isfloating = r->isfloating;
|
||||
+ c->neverdim = r-> neverdim;
|
||||
newtags |= r->tags;
|
||||
i = 0;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
@@ -1267,8 +1272,10 @@ focusclient(Client *c, int lift)
|
||||
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
- if (!exclusive_focus && !seat->drag)
|
||||
+ if (!exclusive_focus && !seat->drag) {
|
||||
client_set_border_color(c, focuscolor);
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Deactivate old client if focus is changing */
|
||||
@@ -1286,7 +1293,7 @@ focusclient(Client *c, int lift)
|
||||
* and probably other clients */
|
||||
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
||||
client_set_border_color(old_c, bordercolor);
|
||||
-
|
||||
+ client_set_dimmer_state(old_c, 1);
|
||||
client_activate_surface(old, 0);
|
||||
}
|
||||
}
|
||||
@@ -1599,6 +1606,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->border[i]->node.data = c;
|
||||
}
|
||||
|
||||
+ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim);
|
||||
+ c->dimmer->node.data = c;
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+
|
||||
/* Initialize client geometry with room for border */
|
||||
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
||||
c->geom.width += 2 * c->bw;
|
||||
@@ -2040,7 +2051,7 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
c->geom = geo;
|
||||
applybounds(c, bbox);
|
||||
|
||||
- /* Update scene-graph, including borders */
|
||||
+ /* Update scene-graph, including borders and dimmer*/
|
||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||
wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
|
||||
@@ -2050,6 +2061,8 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
|
||||
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
+ wlr_scene_rect_set_size(c->dimmer, c->geom.width, c-> geom.height);
|
||||
+ wlr_scene_node_set_position(&c->dimmer->node, 0, 0);
|
||||
|
||||
/* this is a no-op if size hasn't changed */
|
||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
@@ -2603,6 +2616,17 @@ tile(Monitor *m)
|
||||
}
|
||||
}
|
||||
|
||||
+void toggledimming(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ DIMOPT ^= 1;
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ {
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+ }
|
||||
+ client_set_dimmer_state(focustop(selmon), 0);
|
||||
+}
|
||||
+
|
||||
void
|
||||
togglefloating(const Arg *arg)
|
||||
{
|
||||
@@ -0,0 +1,199 @@
|
||||
diff --git a/client.h b/client.h
|
||||
index f0e5445..04b8d31 100644
|
||||
--- a/client.h
|
||||
+++ b/client.h
|
||||
@@ -320,6 +320,12 @@ client_set_border_color(Client *c, const float color[static 4])
|
||||
wlr_scene_rect_set_color(c->border[i], color);
|
||||
}
|
||||
|
||||
+static inline void
|
||||
+client_set_dimmer_state(Client *c, const int dim)
|
||||
+{
|
||||
+ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim);
|
||||
+}
|
||||
+
|
||||
static inline void
|
||||
client_set_fullscreen(Client *c, int fullscreen)
|
||||
{
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..e1b2bf0 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const float rootcolor[] = COLOR(0x222222ff);
|
||||
static const float bordercolor[] = COLOR(0x444444ff);
|
||||
static const float focuscolor[] = COLOR(0x005577ff);
|
||||
+static const float unfocuseddim[] = COLOR(0x00000088);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
@@ -22,10 +23,11 @@ static int log_level = WLR_ERROR;
|
||||
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
- /* app_id title tags mask isfloating monitor */
|
||||
- /* examples: */
|
||||
- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
|
||||
+ /* app_id title tags mask isfloating neverdim monitor */
|
||||
+ /* examples:
|
||||
+ { "Gimp_example", NULL, 0, 1, 0, -1 },
|
||||
+ */
|
||||
+ { "firefox_example", NULL, 1 << 8, 0, 1, -1 },
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
@@ -140,8 +142,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
+ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
- { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 145fd01..6c65860 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -110,6 +110,7 @@ typedef struct {
|
||||
Monitor *mon;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
+ struct wlr_scene_rect *dimmer;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
@@ -138,7 +139,7 @@ typedef struct {
|
||||
#endif
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
- int isfloating, isurgent, isfullscreen;
|
||||
+ int isfloating, isurgent, isfullscreen, neverdim;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -229,6 +230,7 @@ typedef struct {
|
||||
const char *title;
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
+ int neverdim;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -334,6 +336,7 @@ static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
+static void toggledimming(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
@@ -407,6 +410,7 @@ static struct wlr_output_layout *output_layout;
|
||||
static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
+static int DIMOPT = 1;
|
||||
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
@@ -465,6 +469,7 @@ applyrules(Client *c)
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
c->isfloating = r->isfloating;
|
||||
+ c->neverdim = r-> neverdim;
|
||||
newtags |= r->tags;
|
||||
i = 0;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
@@ -1346,8 +1351,10 @@ focusclient(Client *c, int lift)
|
||||
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
- if (!exclusive_focus && !seat->drag)
|
||||
+ if (!exclusive_focus && !seat->drag) {
|
||||
client_set_border_color(c, focuscolor);
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Deactivate old client if focus is changing */
|
||||
@@ -1365,7 +1372,7 @@ focusclient(Client *c, int lift)
|
||||
* and probably other clients */
|
||||
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
||||
client_set_border_color(old_c, bordercolor);
|
||||
-
|
||||
+ client_set_dimmer_state(old_c, 1);
|
||||
client_activate_surface(old, 0);
|
||||
}
|
||||
}
|
||||
@@ -1638,7 +1645,7 @@ void
|
||||
mapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is mapped, or ready to display on-screen. */
|
||||
- Client *p, *w, *c = wl_container_of(listener, c, map);
|
||||
+ Client *p, *w, *d, *c = wl_container_of(listener, c, map);
|
||||
Monitor *m;
|
||||
int i;
|
||||
|
||||
@@ -1670,6 +1677,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->border[i]->node.data = c;
|
||||
}
|
||||
|
||||
+ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim);
|
||||
+ c->dimmer->node.data = c;
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+
|
||||
/* Initialize client geometry with room for border */
|
||||
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
||||
c->geom.width += 2 * c->bw;
|
||||
@@ -1688,6 +1699,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
setmon(c, p->mon, p->tags);
|
||||
} else {
|
||||
applyrules(c);
|
||||
+ d = focustop(selmon);
|
||||
+ if (d) {
|
||||
+ client_set_dimmer_state(d, 0);
|
||||
+ }
|
||||
}
|
||||
printstatus();
|
||||
|
||||
@@ -2141,7 +2156,7 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
c->geom = geo;
|
||||
applybounds(c, bbox);
|
||||
|
||||
- /* Update scene-graph, including borders */
|
||||
+ /* Update scene-graph, including borders and dimmer*/
|
||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||
wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
|
||||
@@ -2151,6 +2166,8 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
|
||||
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
+ wlr_scene_rect_set_size(c->dimmer, c->geom.width - 2*c->bw, c-> geom.height - 2*c->bw);
|
||||
+ wlr_scene_node_set_position(&c->dimmer->node, c->bw, c->bw);
|
||||
|
||||
/* this is a no-op if size hasn't changed */
|
||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
@@ -2666,6 +2683,19 @@ tile(Monitor *m)
|
||||
}
|
||||
}
|
||||
|
||||
+void toggledimming(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ DIMOPT ^= 1;
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ {
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+ }
|
||||
+ c = focustop(selmon);
|
||||
+ if (c)
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+}
|
||||
+
|
||||
void
|
||||
togglefloating(const Arg *arg)
|
||||
{
|
||||
@@ -0,0 +1,216 @@
|
||||
diff --git a/client.h b/client.h
|
||||
index dabea35..3a31c25 100644
|
||||
--- a/client.h
|
||||
+++ b/client.h
|
||||
@@ -319,6 +319,12 @@ client_set_border_color(Client *c, const float color[static 4])
|
||||
wlr_scene_rect_set_color(c->border[i], color);
|
||||
}
|
||||
|
||||
+static inline void
|
||||
+client_set_dimmer_state(Client *c, const int dim)
|
||||
+{
|
||||
+ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim);
|
||||
+}
|
||||
+
|
||||
static inline void
|
||||
client_set_fullscreen(Client *c, int fullscreen)
|
||||
{
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..4ca21c9 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const float rootcolor[] = COLOR(0x222222ff);
|
||||
static const float bordercolor[] = COLOR(0x444444ff);
|
||||
static const float focuscolor[] = COLOR(0x005577ff);
|
||||
+static const float unfocuseddim[] = COLOR(0x00000088);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
@@ -22,10 +23,11 @@ static int log_level = WLR_ERROR;
|
||||
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
- /* app_id title tags mask isfloating monitor */
|
||||
- /* examples: */
|
||||
- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
|
||||
+ /* app_id title tags mask isfloating neverdim monitor */
|
||||
+ /* examples:
|
||||
+ { "Gimp_example", NULL, 0, 1, 0, -1 },
|
||||
+ */
|
||||
+ { "firefox_example", NULL, 1 << 8, 0, 1, -1 },
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
@@ -140,8 +142,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
+ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
- { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
@@ -172,5 +175,6 @@ static const Key keys[] = {
|
||||
static const Button buttons[] = {
|
||||
{ MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },
|
||||
{ MODKEY, BTN_MIDDLE, togglefloating, {0} },
|
||||
+ { MODKEY|ShiftMask, BTN_MIDDLE, toggledimmingclient, {0} },
|
||||
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
|
||||
};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 9021e44..e1f32e9 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -112,6 +112,7 @@ typedef struct {
|
||||
Monitor *mon;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
+ struct wlr_scene_rect *dimmer;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
@@ -141,7 +142,7 @@ typedef struct {
|
||||
#endif
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
- int isfloating, isurgent, isfullscreen;
|
||||
+ int isfloating, isurgent, isfullscreen, neverdim;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -231,6 +232,7 @@ typedef struct {
|
||||
const char *title;
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
+ int neverdim;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -338,6 +340,8 @@ static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
+static void toggledimming(const Arg *arg);
|
||||
+static void toggledimmingclient(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
@@ -410,6 +414,7 @@ static struct wlr_output_layout *output_layout;
|
||||
static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
+static int DIMOPT = 1;
|
||||
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
@@ -466,6 +471,7 @@ applyrules(Client *c)
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
c->isfloating = r->isfloating;
|
||||
+ c->neverdim = r-> neverdim;
|
||||
newtags |= r->tags;
|
||||
i = 0;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
@@ -1366,8 +1372,10 @@ focusclient(Client *c, int lift)
|
||||
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
- if (!exclusive_focus && !seat->drag)
|
||||
+ if (!exclusive_focus && !seat->drag) {
|
||||
client_set_border_color(c, focuscolor);
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Deactivate old client if focus is changing */
|
||||
@@ -1385,7 +1393,7 @@ focusclient(Client *c, int lift)
|
||||
* and probably other clients */
|
||||
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
||||
client_set_border_color(old_c, bordercolor);
|
||||
-
|
||||
+ client_set_dimmer_state(old_c, 1);
|
||||
client_activate_surface(old, 0);
|
||||
}
|
||||
}
|
||||
@@ -1682,8 +1690,7 @@ void
|
||||
mapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is mapped, or ready to display on-screen. */
|
||||
- Client *p = NULL;
|
||||
- Client *w, *c = wl_container_of(listener, c, map);
|
||||
+ Client *p, *w, *d, *c = wl_container_of(listener, c, map);
|
||||
Monitor *m;
|
||||
int i;
|
||||
|
||||
@@ -1717,6 +1724,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->border[i]->node.data = c;
|
||||
}
|
||||
|
||||
+ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim);
|
||||
+ c->dimmer->node.data = c;
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+
|
||||
/* Initialize client geometry with room for border */
|
||||
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
||||
c->geom.width += 2 * c->bw;
|
||||
@@ -1735,6 +1746,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
setmon(c, p->mon, p->tags);
|
||||
} else {
|
||||
applyrules(c);
|
||||
+ d = focustop(selmon);
|
||||
+ if (d) {
|
||||
+ client_set_dimmer_state(d, 0);
|
||||
+ }
|
||||
}
|
||||
printstatus();
|
||||
|
||||
@@ -2161,7 +2176,7 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
c->geom = geo;
|
||||
applybounds(c, bbox);
|
||||
|
||||
- /* Update scene-graph, including borders */
|
||||
+ /* Update scene-graph, including borders and dimmer*/
|
||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||
wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
|
||||
@@ -2171,6 +2186,8 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
|
||||
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
+ wlr_scene_rect_set_size(c->dimmer, c->geom.width - 2*c->bw, c-> geom.height - 2*c->bw);
|
||||
+ wlr_scene_node_set_position(&c->dimmer->node, c->bw, c->bw);
|
||||
|
||||
/* this is a no-op if size hasn't changed */
|
||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
@@ -2682,6 +2699,27 @@ tile(Monitor *m)
|
||||
}
|
||||
}
|
||||
|
||||
+void toggledimming(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ DIMOPT ^= 1;
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ {
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+ }
|
||||
+ c = focustop(selmon);
|
||||
+ if (c)
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+toggledimmingclient(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ if (sel)
|
||||
+ sel -> neverdim ^= 1;
|
||||
+}
|
||||
+
|
||||
void
|
||||
togglefloating(const Arg *arg)
|
||||
{
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
diff --git a/client.h b/client.h
|
||||
index dabea35..3a31c25 100644
|
||||
--- a/client.h
|
||||
+++ b/client.h
|
||||
@@ -319,6 +319,12 @@ client_set_border_color(Client *c, const float color[static 4])
|
||||
wlr_scene_rect_set_color(c->border[i], color);
|
||||
}
|
||||
|
||||
+static inline void
|
||||
+client_set_dimmer_state(Client *c, const int dim)
|
||||
+{
|
||||
+ wlr_scene_node_set_enabled(&c->dimmer->node, DIMOPT && !c->neverdim && dim);
|
||||
+}
|
||||
+
|
||||
static inline void
|
||||
client_set_fullscreen(Client *c, int fullscreen)
|
||||
{
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..4ca21c9 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -10,6 +10,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const float rootcolor[] = COLOR(0x222222ff);
|
||||
static const float bordercolor[] = COLOR(0x444444ff);
|
||||
static const float focuscolor[] = COLOR(0x005577ff);
|
||||
+static const float unfocuseddim[] = COLOR(0x00000088);
|
||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
@@ -22,10 +23,11 @@ static int log_level = WLR_ERROR;
|
||||
|
||||
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
|
||||
static const Rule rules[] = {
|
||||
- /* app_id title tags mask isfloating monitor */
|
||||
- /* examples: */
|
||||
- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
|
||||
- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
|
||||
+ /* app_id title tags mask isfloating neverdim monitor */
|
||||
+ /* examples:
|
||||
+ { "Gimp_example", NULL, 0, 1, 0, -1 },
|
||||
+ */
|
||||
+ { "firefox_example", NULL, 1 << 8, 0, 1, -1 },
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
@@ -140,8 +142,9 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
+ { MODKEY, XKB_KEY_apostrophe, toggledimming, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
- { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
@@ -172,5 +175,6 @@ static const Key keys[] = {
|
||||
static const Button buttons[] = {
|
||||
{ MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },
|
||||
{ MODKEY, BTN_MIDDLE, togglefloating, {0} },
|
||||
+ { MODKEY|ShiftMask, BTN_MIDDLE, toggledimmingclient, {0} },
|
||||
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
|
||||
};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index dc0c861..dcc3ece 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -112,6 +112,7 @@ typedef struct {
|
||||
Monitor *mon;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wlr_scene_rect *border[4]; /* top, bottom, left, right */
|
||||
+ struct wlr_scene_rect *dimmer;
|
||||
struct wlr_scene_tree *scene_surface;
|
||||
struct wl_list link;
|
||||
struct wl_list flink;
|
||||
@@ -141,7 +142,7 @@ typedef struct {
|
||||
#endif
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
- int isfloating, isurgent, isfullscreen;
|
||||
+ int isfloating, isurgent, isfullscreen, neverdim;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -231,6 +232,7 @@ typedef struct {
|
||||
const char *title;
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
+ int neverdim;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -338,6 +340,8 @@ static void startdrag(struct wl_listener *listener, void *data);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
+static void toggledimming(const Arg *arg);
|
||||
+static void toggledimmingclient(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
@@ -410,6 +414,7 @@ static struct wlr_output_layout *output_layout;
|
||||
static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
+static int DIMOPT = 1;
|
||||
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
@@ -466,6 +471,7 @@ applyrules(Client *c)
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
c->isfloating = r->isfloating;
|
||||
+ c->neverdim = r-> neverdim;
|
||||
newtags |= r->tags;
|
||||
i = 0;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
@@ -1365,8 +1371,10 @@ focusclient(Client *c, int lift)
|
||||
|
||||
/* Don't change border color if there is an exclusive focus or we are
|
||||
* handling a drag operation */
|
||||
- if (!exclusive_focus && !seat->drag)
|
||||
+ if (!exclusive_focus && !seat->drag) {
|
||||
client_set_border_color(c, focuscolor);
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Deactivate old client if focus is changing */
|
||||
@@ -1384,7 +1392,7 @@ focusclient(Client *c, int lift)
|
||||
* and probably other clients */
|
||||
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
||||
client_set_border_color(old_c, bordercolor);
|
||||
-
|
||||
+ client_set_dimmer_state(old_c, 1);
|
||||
client_activate_surface(old, 0);
|
||||
}
|
||||
}
|
||||
@@ -1681,8 +1689,7 @@ void
|
||||
mapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is mapped, or ready to display on-screen. */
|
||||
- Client *p = NULL;
|
||||
- Client *w, *c = wl_container_of(listener, c, map);
|
||||
+ Client *p, *w, *d, *c = wl_container_of(listener, c, map);
|
||||
Monitor *m;
|
||||
int i;
|
||||
|
||||
@@ -1716,6 +1723,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->border[i]->node.data = c;
|
||||
}
|
||||
|
||||
+ c->dimmer = wlr_scene_rect_create(c->scene, 0, 0, unfocuseddim);
|
||||
+ c->dimmer->node.data = c;
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+
|
||||
/* Initialize client geometry with room for border */
|
||||
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
||||
c->geom.width += 2 * c->bw;
|
||||
@@ -1734,6 +1745,10 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
setmon(c, p->mon, p->tags);
|
||||
} else {
|
||||
applyrules(c);
|
||||
+ d = focustop(selmon);
|
||||
+ if (d) {
|
||||
+ client_set_dimmer_state(d, 0);
|
||||
+ }
|
||||
}
|
||||
printstatus();
|
||||
|
||||
@@ -2160,7 +2175,7 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
c->geom = geo;
|
||||
applybounds(c, bbox);
|
||||
|
||||
- /* Update scene-graph, including borders */
|
||||
+ /* Update scene-graph, including borders and dimmer*/
|
||||
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
||||
wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw);
|
||||
wlr_scene_rect_set_size(c->border[0], c->geom.width, c->bw);
|
||||
@@ -2170,6 +2185,8 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
|
||||
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
+ wlr_scene_rect_set_size(c->dimmer, c->geom.width - 2*c->bw, c-> geom.height - 2*c->bw);
|
||||
+ wlr_scene_node_set_position(&c->dimmer->node, c->bw, c->bw);
|
||||
|
||||
/* this is a no-op if size hasn't changed */
|
||||
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
||||
@@ -2681,6 +2698,27 @@ tile(Monitor *m)
|
||||
}
|
||||
}
|
||||
|
||||
+void toggledimming(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ DIMOPT ^= 1;
|
||||
+ wl_list_for_each(c, &clients, link)
|
||||
+ {
|
||||
+ client_set_dimmer_state(c, 1);
|
||||
+ }
|
||||
+ c = focustop(selmon);
|
||||
+ if (c)
|
||||
+ client_set_dimmer_state(c, 0);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+toggledimmingclient(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ if (sel)
|
||||
+ sel -> neverdim ^= 1;
|
||||
+}
|
||||
+
|
||||
void
|
||||
togglefloating(const Arg *arg)
|
||||
{
|
||||
@@ -0,0 +1,11 @@
|
||||
### Description
|
||||
This patch changes the default behavior of the [disable-keybindings-on-fullscreen](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/disable-keybindings-on-fullscreen) patch by only taking effect when you explicitly toggle the functionality.
|
||||
You must apply that patch prior to applying this one.
|
||||
|
||||
### Download
|
||||
- [git branch](https://github.com/Shringe/dwl/tree/disable-keybindings-on-fullscreen-toggle)
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/disable-keybindings-on-fullscreen-toggle/disable-keybindings-on-fullscreen-toggle-0.7.patch)
|
||||
|
||||
### Authors
|
||||
- [Shringe](https://codeberg.org/Shringe)
|
||||
- shringe_ at [dwl Discord](https://discord.gg/jJxZnrGPWN)
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
From 71809cee0e27f1b3620773e1745afed8023f71c9 Mon Sep 17 00:00:00 2001
|
||||
From: Shringe <dashingkoso@gmail.com>
|
||||
Date: Mon, 23 Jun 2025 18:50:40 -0500
|
||||
Subject: [PATCH] Implemented functionality for patch
|
||||
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 14 ++++++++++++--
|
||||
2 files changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..dda4ad0 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -142,6 +142,7 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_G, togglefullscreenkeyinhibit, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index f11de4b..5deb9c7 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -341,6 +341,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
+static void togglefullscreenkeyinhibit(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -414,6 +415,8 @@ static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
|
||||
+static int fullscreen_key_inhibit_enabled = 0;
|
||||
+
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
@@ -1583,8 +1586,9 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
||||
for (k = keys; k < END(keys); k++) {
|
||||
if (CLEANMASK(mods) == CLEANMASK(k->mod)
|
||||
&& sym == k->keysym && k->func) {
|
||||
- if (c && c->isfullscreen) {
|
||||
- if (k->func == togglefullscreen) {
|
||||
+ if (fullscreen_key_inhibit_enabled
|
||||
+ && c && c->isfullscreen) {
|
||||
+ if (k->func == togglefullscreenkeyinhibit) {
|
||||
k->func(&k->arg);
|
||||
return 1;
|
||||
}
|
||||
@@ -2763,6 +2767,12 @@ togglefullscreen(const Arg *arg)
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
+void
|
||||
+togglefullscreenkeyinhibit(const Arg *arg)
|
||||
+{
|
||||
+ fullscreen_key_inhibit_enabled = !fullscreen_key_inhibit_enabled;
|
||||
+}
|
||||
+
|
||||
void
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
### Description
|
||||
This patch disables all keybindings except `togglefullscreen` when the focused window is fullscreen.
|
||||
Might help prevent fat-fingering.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/korei999/dwl/src/branch/disable-keybindings-on-fullscreen)
|
||||
- [2025-02-09](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/disable-keybindings-on-fullscreen/disable-keybindings-on-fullscreen.patch)
|
||||
### Authors
|
||||
- [korei999](https://codeberg.org/korei999)
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
From 2d6b845701091d3238774747c718df7fef135986 Mon Sep 17 00:00:00 2001
|
||||
From: korei999 <ju7t1xe@gmail.com>
|
||||
Date: Sun, 9 Feb 2025 14:59:33 +0200
|
||||
Subject: [PATCH] disable keybindings on fullscreen
|
||||
|
||||
---
|
||||
dwl.c | 23 ++++++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index ec4ca86..8c771e8 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -282,6 +282,7 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data);
|
||||
static void destroysessionlock(struct wl_listener *listener, void *data);
|
||||
static void destroykeyboardgroup(struct wl_listener *listener, void *data);
|
||||
static Monitor *dirtomon(enum wlr_direction dir);
|
||||
+static Client *firstfocused(void);
|
||||
static void focusclient(Client *c, int lift);
|
||||
static void focusmon(const Arg *arg);
|
||||
static void focusstack(const Arg *arg);
|
||||
@@ -620,11 +621,15 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
struct wlr_pointer_button_event *event = data;
|
||||
struct wlr_keyboard *keyboard;
|
||||
uint32_t mods;
|
||||
- Client *c;
|
||||
+ Client *c, *focused;
|
||||
const Button *b;
|
||||
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
|
||||
+ focused = firstfocused();
|
||||
+ if (focused && focused->isfullscreen)
|
||||
+ goto skip_click;
|
||||
+
|
||||
switch (event->state) {
|
||||
case WL_POINTER_BUTTON_STATE_PRESSED:
|
||||
cursor_mode = CurPressed;
|
||||
@@ -664,6 +669,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
}
|
||||
/* If the event wasn't handled by the compositor, notify the client with
|
||||
* pointer focus that a button press has occurred */
|
||||
+skip_click:
|
||||
wlr_seat_pointer_notify_button(seat,
|
||||
event->time_msec, event->button, event->state);
|
||||
}
|
||||
@@ -1393,6 +1399,13 @@ dirtomon(enum wlr_direction dir)
|
||||
return selmon;
|
||||
}
|
||||
|
||||
+Client *
|
||||
+firstfocused(void)
|
||||
+{
|
||||
+ Client *c = wl_container_of(fstack.next, c, flink);
|
||||
+ return c;
|
||||
+}
|
||||
+
|
||||
void
|
||||
focusclient(Client *c, int lift)
|
||||
{
|
||||
@@ -1607,10 +1620,18 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
||||
* processing keys, rather than passing them on to the client for its own
|
||||
* processing.
|
||||
*/
|
||||
+ Client *c = firstfocused();
|
||||
const Key *k;
|
||||
for (k = keys; k < END(keys); k++) {
|
||||
if (CLEANMASK(mods) == CLEANMASK(k->mod)
|
||||
&& sym == k->keysym && k->func) {
|
||||
+ if (c && c->isfullscreen) {
|
||||
+ if (k->func == togglefullscreen) {
|
||||
+ k->func(&k->arg);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
k->func(&k->arg);
|
||||
return 1;
|
||||
}
|
||||
--
|
||||
2.48.1
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
### Description
|
||||
Change mfact by dragging the mouse.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/Palanix/dwl/src/branch/dragmfact)
|
||||
- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dragmfact/dragmfact-v0.7.patch)
|
||||
- [v0.6](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dragmfact/dragmfact-v0.6.patch)
|
||||
- [2024-02-16](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dragmfact/dragmfact.patch)
|
||||
|
||||
### Authors
|
||||
- [Palanix](https://codeberg.org/Palanix)
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
From aeee958aec3e0774f3ea8baefe028e1a8cc2d2ce Mon Sep 17 00:00:00 2001
|
||||
From: Palanix <palanixyt@gmail.com>
|
||||
Date: Fri, 25 Mar 2022 23:45:10 +0100
|
||||
Subject: [PATCH] Change mfact using Middle mouse
|
||||
|
||||
---
|
||||
config.def.h | 2 +-
|
||||
dwl.c | 9 ++++++++-
|
||||
2 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..c9071a5 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -171,6 +171,6 @@ static const Key keys[] = {
|
||||
|
||||
static const Button buttons[] = {
|
||||
{ MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },
|
||||
- { MODKEY, BTN_MIDDLE, togglefloating, {0} },
|
||||
+ { MODKEY, BTN_MIDDLE, moveresize, {.ui = Curmfact} },
|
||||
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
|
||||
};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 145fd01..0a3d140 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -80,7 +80,7 @@
|
||||
#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
|
||||
|
||||
/* enums */
|
||||
-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||
+enum { CurNormal, CurPressed, CurMove, CurResize, Curmfact }; /* cursor */
|
||||
enum { XDGShell, LayerShell, X11 }; /* client types */
|
||||
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
|
||||
#ifdef XWAYLAND
|
||||
@@ -1823,6 +1823,9 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
.width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
return;
|
||||
+ } else if (cursor_mode == Curmfact && time) {
|
||||
+ selmon->mfact = (float) (cursor->x / selmon->m.width);
|
||||
+ arrange(selmon);
|
||||
}
|
||||
|
||||
/* If there's no client surface under the cursor, set the cursor image to a
|
||||
@@ -1874,6 +1877,10 @@ moveresize(const Arg *arg)
|
||||
grabc->geom.y + grabc->geom.height);
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
break;
|
||||
+ case Curmfact:
|
||||
+ setfloating(grabc, 0);
|
||||
+ selmon->mfact = (float) (cursor->x / selmon->m.width);
|
||||
+ arrange(selmon);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.45.2
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
From ae44bfc181fc1532d2f0c4deb20e20634050a661 Mon Sep 17 00:00:00 2001
|
||||
From: Palanix <palanixyt@gmail.com>
|
||||
Date: Fri, 25 Mar 2022 23:45:10 +0100
|
||||
Subject: [PATCH] Change mfact using Middle mouse
|
||||
|
||||
---
|
||||
config.def.h | 2 +-
|
||||
dwl.c | 9 ++++++++-
|
||||
2 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..c9071a5 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -171,6 +171,6 @@ static const Key keys[] = {
|
||||
|
||||
static const Button buttons[] = {
|
||||
{ MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },
|
||||
- { MODKEY, BTN_MIDDLE, togglefloating, {0} },
|
||||
+ { MODKEY, BTN_MIDDLE, moveresize, {.ui = Curmfact} },
|
||||
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
|
||||
};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 5bf995e..dfb0754 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -81,7 +81,7 @@
|
||||
#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
|
||||
|
||||
/* enums */
|
||||
-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||
+enum { CurNormal, CurPressed, CurMove, CurResize, Curmfact }; /* cursor */
|
||||
enum { XDGShell, LayerShell, X11 }; /* client types */
|
||||
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
|
||||
#ifdef XWAYLAND
|
||||
@@ -1872,6 +1872,9 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
.width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
return;
|
||||
+ } else if (cursor_mode == Curmfact && time) {
|
||||
+ selmon->mfact = (float) (cursor->x / selmon->m.width);
|
||||
+ arrange(selmon);
|
||||
}
|
||||
|
||||
/* If there's no client surface under the cursor, set the cursor image to a
|
||||
@@ -1923,6 +1926,10 @@ moveresize(const Arg *arg)
|
||||
grabc->geom.y + grabc->geom.height);
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
break;
|
||||
+ case Curmfact:
|
||||
+ setfloating(grabc, 0);
|
||||
+ selmon->mfact = (float) (cursor->x / selmon->m.width);
|
||||
+ arrange(selmon);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.45.2
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
From 435cdf673e5a8080123109dbf874aac2ccef1498 Mon Sep 17 00:00:00 2001
|
||||
From: Palanix <palanixyt@gmail.com>
|
||||
Date: Fri, 25 Mar 2022 23:45:10 +0100
|
||||
Subject: [PATCH] Change mfact using Middle mouse
|
||||
|
||||
---
|
||||
config.def.h | 2 +-
|
||||
dwl.c | 9 ++++++++-
|
||||
2 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 9009517..3c26522 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -166,6 +166,6 @@ static const Key keys[] = {
|
||||
|
||||
static const Button buttons[] = {
|
||||
{ MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },
|
||||
- { MODKEY, BTN_MIDDLE, togglefloating, {0} },
|
||||
+ { MODKEY, BTN_MIDDLE, moveresize, {.ui = Curmfact} },
|
||||
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
|
||||
};
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index fa76db2..528e102 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -76,7 +76,7 @@
|
||||
#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
|
||||
|
||||
/* enums */
|
||||
-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||
+enum { CurNormal, CurPressed, CurMove, CurResize, Curmfact }; /* cursor */
|
||||
enum { XDGShell, LayerShell, X11 }; /* client types */
|
||||
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrFS, LyrTop, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
|
||||
#ifdef XWAYLAND
|
||||
@@ -1639,6 +1639,9 @@ motionnotify(uint32_t time)
|
||||
resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
.width = ROUND(cursor->x) - grabc->geom.x, .height = ROUND(cursor->y) - grabc->geom.y}, 1);
|
||||
return;
|
||||
+ } else if (cursor_mode == Curmfact && time) {
|
||||
+ selmon->mfact = (float) (cursor->x / selmon->m.width);
|
||||
+ arrange(selmon);
|
||||
}
|
||||
|
||||
/* Find the client under the pointer and send the event along. */
|
||||
@@ -1701,6 +1704,10 @@ moveresize(const Arg *arg)
|
||||
grabc->geom.y + grabc->geom.height);
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
break;
|
||||
+ case Curmfact:
|
||||
+ setfloating(grabc, 0);
|
||||
+ selmon->mfact = (float) (cursor->x / selmon->m.width);
|
||||
+ arrange(selmon);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.43.2
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
### Description
|
||||
implement rio-like window resizing
|
||||
|
||||
select window to resize (mod+middleclick by default) then drag out an area for it to occupy
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/notchoc/dwl/src/branch/dragresize)
|
||||
- [2024-07-10](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/dragresize/dragresize.patch)
|
||||
- [2024-06-19](https://codeberg.org/dwl/dwl-patches/raw/commit/8c75e6dbc1728bf70d42547222464f496d9ea613/patches/dragresize/dragresize.patch)
|
||||
|
||||
### Authors
|
||||
- [notchoc](https://codeberg.org/notchoc)
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
From 83ae7d4816a49f46063ab16ffecd32b2e7e61784 Mon Sep 17 00:00:00 2001
|
||||
From: choc <notchoc@proton.me>
|
||||
Date: Fri, 15 Sep 2023 11:45:16 +0800
|
||||
Subject: [PATCH] dragresize: implement rio-like window resizing
|
||||
|
||||
select window to resize then drag out an area for it to occupy
|
||||
---
|
||||
dwl.c | 132 +++++++++++++++++++++++++++++++++++++++++++---------------
|
||||
1 file changed, 98 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index dc0437e..843aa7a 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -80,7 +80,7 @@
|
||||
#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
|
||||
|
||||
/* enums */
|
||||
-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
||||
+enum { CurNormal, CurPressed, CurSelect, CurMove, CurResize, CurBind }; /* cursor */
|
||||
enum { XDGShell, LayerShell, X11 }; /* client types */
|
||||
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
|
||||
#ifdef XWAYLAND
|
||||
@@ -603,15 +603,21 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
|
||||
switch (event->state) {
|
||||
case WLR_BUTTON_PRESSED:
|
||||
- cursor_mode = CurPressed;
|
||||
selmon = xytomon(cursor->x, cursor->y);
|
||||
- if (locked)
|
||||
+ if (locked) {
|
||||
+ cursor_mode = CurPressed;
|
||||
break;
|
||||
+ }
|
||||
|
||||
- /* Change focus if the button was _pressed_ over a client */
|
||||
- xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
|
||||
- if (c && (!client_is_unmanaged(c) || client_wants_focus(c)))
|
||||
- focusclient(c, 1);
|
||||
+ if (cursor_mode == CurNormal)
|
||||
+ cursor_mode = CurPressed;
|
||||
+
|
||||
+ if (cursor_mode != CurResize) {
|
||||
+ /* Change focus if the button was _pressed_ over a client */
|
||||
+ xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
|
||||
+ if (c && (!client_is_unmanaged(c) || client_wants_focus(c)))
|
||||
+ focusclient(c, 1);
|
||||
+ }
|
||||
|
||||
keyboard = wlr_seat_get_keyboard(seat);
|
||||
mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
||||
@@ -624,17 +630,42 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||
}
|
||||
break;
|
||||
case WLR_BUTTON_RELEASED:
|
||||
+ if (locked) {
|
||||
+ cursor_mode = CurNormal;
|
||||
+ break;
|
||||
+ }
|
||||
/* If you released any buttons, we exit interactive move/resize mode. */
|
||||
- /* TODO should reset to the pointer focus's current setcursor */
|
||||
- if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
||||
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
+ switch (cursor_mode) {
|
||||
+ case CurPressed:
|
||||
cursor_mode = CurNormal;
|
||||
- /* Drop the window off on its new monitor */
|
||||
- selmon = xytomon(cursor->x, cursor->y);
|
||||
- setmon(grabc, selmon, 0);
|
||||
+ case CurNormal:
|
||||
+ break;
|
||||
+ case CurSelect:
|
||||
return;
|
||||
- } else {
|
||||
+ case CurResize:
|
||||
+ /* a label can only be part of a statement - Wpedantic */
|
||||
+ {
|
||||
+ int nw = abs((int) cursor->x - grabcx);
|
||||
+ int nh = abs((int) cursor->y - grabcy);
|
||||
+ if (nw > 1 && nh > 1) {
|
||||
+ setfloating(grabc, 1);
|
||||
+ resize(grabc, (struct wlr_box){.x = MIN(ROUND(cursor->x), grabcx),
|
||||
+ .y = MIN(ROUND(cursor->y), grabcy),
|
||||
+ .width = nw, .height = nh}, 1);
|
||||
+ }
|
||||
+ }
|
||||
+ /* fallthrough */
|
||||
+ default:
|
||||
+ /* TODO should reset to the pointer focus's current setcursor */
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
+ /* Drop the window off on its new monitor */
|
||||
+ if (grabc && cursor_mode != CurBind) {
|
||||
+ selmon = xytomon(cursor->x, cursor->y);
|
||||
+ setmon(grabc, selmon, 0);
|
||||
+ grabc = NULL;
|
||||
+ }
|
||||
cursor_mode = CurNormal;
|
||||
+ return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1815,15 +1846,33 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
||||
wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
|
||||
|
||||
/* If we are currently grabbing the mouse, handle and return */
|
||||
- if (cursor_mode == CurMove) {
|
||||
+ switch (cursor_mode) {
|
||||
+ case CurSelect:
|
||||
+ return;
|
||||
+ case CurMove:
|
||||
/* Move the grabbed client to the new position. */
|
||||
resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy,
|
||||
.width = grabc->geom.width, .height = grabc->geom.height}, 1);
|
||||
return;
|
||||
- } else if (cursor_mode == CurResize) {
|
||||
- resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
|
||||
- .width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
|
||||
- return;
|
||||
+ case CurResize:
|
||||
+ {
|
||||
+ int w, h, x, y;
|
||||
+ if (!grabc)
|
||||
+ return;
|
||||
+ w = abs(grabcx - (int)round(cursor->x));
|
||||
+ h = abs(grabcy - (int)round(cursor->y));
|
||||
+ x = MIN(grabcx, (int)round(cursor->x)) - grabc->geom.x;
|
||||
+ y = MIN(grabcy, (int)round(cursor->y)) - grabc->geom.y;
|
||||
+ wlr_scene_rect_set_size(grabc->border[0], w, grabc->bw);
|
||||
+ wlr_scene_rect_set_size(grabc->border[1], w, grabc->bw);
|
||||
+ wlr_scene_rect_set_size(grabc->border[2], grabc->bw, h - 2 * grabc->bw);
|
||||
+ wlr_scene_rect_set_size(grabc->border[3], grabc->bw, h - 2 * grabc->bw);
|
||||
+ wlr_scene_node_set_position(&grabc->border[0]->node, x, y);
|
||||
+ wlr_scene_node_set_position(&grabc->border[1]->node, x, y + h - grabc->bw);
|
||||
+ wlr_scene_node_set_position(&grabc->border[2]->node, x, y + grabc->bw);
|
||||
+ wlr_scene_node_set_position(&grabc->border[3]->node, x + w - grabc->bw, y + grabc->bw);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* If there's no client surface under the cursor, set the cursor image to a
|
||||
@@ -1853,29 +1902,43 @@ motionrelative(struct wl_listener *listener, void *data)
|
||||
void
|
||||
moveresize(const Arg *arg)
|
||||
{
|
||||
- if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||
- return;
|
||||
- xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
|
||||
- if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
|
||||
+ /* Consider global select bool instead of this + CurSelect enum */
|
||||
+ bool selected = (cursor_mode == CurSelect);
|
||||
+ if (!selected) {
|
||||
+ if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||
+ return;
|
||||
+ xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) {
|
||||
+ grabc = NULL;
|
||||
+ cursor_mode = CurNormal;
|
||||
return;
|
||||
+ }
|
||||
|
||||
- /* Float the window and tell motionnotify to grab it */
|
||||
- setfloating(grabc, 1);
|
||||
+ /* TODO: factor out selected bool */
|
||||
switch (cursor_mode = arg->ui) {
|
||||
+ case CurResize:
|
||||
+ if (!selected) break;
|
||||
+ grabcx = ROUND(cursor->x);
|
||||
+ grabcy = ROUND(cursor->y);
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "tcross");
|
||||
+ return;
|
||||
case CurMove:
|
||||
grabcx = (int)round(cursor->x) - grabc->geom.x;
|
||||
grabcy = (int)round(cursor->y) - grabc->geom.y;
|
||||
+ setfloating(grabc, 1);
|
||||
wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
|
||||
- break;
|
||||
- case CurResize:
|
||||
- /* Doesn't work for X11 output - the next absolute motion event
|
||||
- * returns the cursor to where it started */
|
||||
- wlr_cursor_warp_closest(cursor, NULL,
|
||||
- grabc->geom.x + grabc->geom.width,
|
||||
- grabc->geom.y + grabc->geom.height);
|
||||
- wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
|
||||
- break;
|
||||
+ return;
|
||||
+ default:
|
||||
+ grabc = NULL;
|
||||
+ cursor_mode = CurNormal;
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
||||
+ return;
|
||||
}
|
||||
+
|
||||
+ cursor_mode = CurSelect;
|
||||
+ wlr_cursor_set_xcursor(cursor, cursor_mgr, "crosshair");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2149,6 +2212,7 @@ resize(Client *c, struct wlr_box geo, int interact)
|
||||
wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw);
|
||||
wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw);
|
||||
wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw);
|
||||
+ wlr_scene_node_set_position(&c->border[0]->node, 0, 0);
|
||||
wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
|
||||
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
||||
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
### Description
|
||||
Always use the English keymap to get keycodes, so key bindings work even when using a non-English keyboard layout.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/ForzCross/dwl/src/branch/en-keycodes.patch)
|
||||
- [v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/en-keycodes/en-keycodes.patch)
|
||||
|
||||
### Authors
|
||||
- [ForzCross](https://codeberg.org/ForzCross)
|
||||
- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV))
|
||||
- [dimkr](https://codeberg.org/dimkr) (<dima@dimakrasner.com>)
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
From cd61fac9cb6e9d0172e2f7a01e6a514d676ba5f0 Mon Sep 17 00:00:00 2001
|
||||
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
|
||||
Date: Tue, 4 Feb 2025 23:53:11 +0100
|
||||
Subject: [PATCH] Always use the English keymap to get keycodes
|
||||
|
||||
---
|
||||
dwl.c | 23 +++++++++++++++++++----
|
||||
1 file changed, 19 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index def2562..c299365 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -413,6 +413,11 @@ static struct wlr_box sgeom;
|
||||
static struct wl_list mons;
|
||||
static Monitor *selmon;
|
||||
|
||||
+static const struct xkb_rule_names en_rules = {.layout = "us"};
|
||||
+static struct xkb_context *en_context;
|
||||
+static struct xkb_keymap *en_keymap;
|
||||
+static struct xkb_state *en_state;
|
||||
+
|
||||
#ifdef XWAYLAND
|
||||
static void activatex11(struct wl_listener *listener, void *data);
|
||||
static void associatex11(struct wl_listener *listener, void *data);
|
||||
@@ -694,6 +699,9 @@ cleanup(void)
|
||||
wlr_backend_destroy(backend);
|
||||
|
||||
wl_display_destroy(dpy);
|
||||
+ xkb_state_unref(en_state);
|
||||
+ xkb_keymap_unref(en_keymap);
|
||||
+ xkb_context_unref(en_context);
|
||||
/* Destroy after the wayland display (when the monitors are already destroyed)
|
||||
to avoid destroying them with an invalid scene output. */
|
||||
wlr_scene_node_destroy(&scene->tree.node);
|
||||
@@ -1582,16 +1590,19 @@ keypress(struct wl_listener *listener, void *data)
|
||||
/* This event is raised when a key is pressed or released. */
|
||||
KeyboardGroup *group = wl_container_of(listener, group, key);
|
||||
struct wlr_keyboard_key_event *event = data;
|
||||
+ int nsyms, handled;
|
||||
|
||||
/* Translate libinput keycode -> xkbcommon */
|
||||
uint32_t keycode = event->keycode + 8;
|
||||
/* Get a list of keysyms based on the keymap for this keyboard */
|
||||
const xkb_keysym_t *syms;
|
||||
- int nsyms = xkb_state_key_get_syms(
|
||||
- group->wlr_group->keyboard.xkb_state, keycode, &syms);
|
||||
-
|
||||
- int handled = 0;
|
||||
uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
|
||||
+ xkb_state_update_key(en_state, keycode,
|
||||
+ (event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
+ ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
+ nsyms = xkb_state_key_get_syms(en_state, keycode, &syms);
|
||||
+
|
||||
+ handled = 0;
|
||||
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
|
||||
@@ -2607,6 +2618,10 @@ setup(void)
|
||||
* pointer, touch, and drawing tablet device. We also rig up a listener to
|
||||
* let us know when new input devices are available on the backend.
|
||||
*/
|
||||
+ en_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
+ en_keymap = xkb_keymap_new_from_names(en_context, &en_rules,
|
||||
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
+ en_state = xkb_state_new(en_keymap);
|
||||
LISTEN_STATIC(&backend->events.new_input, inputdevice);
|
||||
virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(dpy);
|
||||
LISTEN_STATIC(&virtual_keyboard_mgr->events.new_virtual_keyboard, virtualkeyboard);
|
||||
--
|
||||
2.48.1
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
### Description
|
||||
Input device configuration (click method, tap-and-drag, acceleration, etc), border size and colors via environment variables.
|
||||
|
||||
### Download
|
||||
- [2024-02-11](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/envcfg/envcfg.patch)
|
||||
|
||||
### Authors
|
||||
- [Dima Krasner](https://codeberg.org/dimkr) (<dima@dimakrasner.com>)
|
||||
Executable
+302
@@ -0,0 +1,302 @@
|
||||
From 3c3ea42cd50bfa5111be69b3c1f71afa0443bb53 Mon Sep 17 00:00:00 2001
|
||||
From: Dima Krasner <dima@dimakrasner.com>
|
||||
Date: Sat, 30 Dec 2023 10:49:48 +0200
|
||||
Subject: [PATCH] allow environment variables to override config.h
|
||||
|
||||
---
|
||||
Makefile | 1 +
|
||||
config.def.h | 10 +--
|
||||
dwl.c | 5 ++
|
||||
env.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 228 insertions(+), 5 deletions(-)
|
||||
create mode 100644 env.c
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 9308656..c66d376 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -22,6 +22,7 @@ dwl: dwl.o util.o
|
||||
dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
|
||||
pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \
|
||||
wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
|
||||
+dwl.o: env.c
|
||||
util.o: util.c util.h
|
||||
|
||||
# wayland-scanner is a tool which generates C headers and rigging for Wayland
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index a784eb4..e0f10de 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -6,11 +6,11 @@
|
||||
/* appearance */
|
||||
static const int sloppyfocus = 1; /* focus follows mouse */
|
||||
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||
-static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
-static const float rootcolor[] = COLOR(0x222222ff);
|
||||
-static const float bordercolor[] = COLOR(0x444444ff);
|
||||
-static const float focuscolor[] = COLOR(0x005577ff);
|
||||
-static const float urgentcolor[] = COLOR(0xff0000ff);
|
||||
+static unsigned int borderpx = 1; /* border pixel of windows */
|
||||
+static float rootcolor[] = COLOR(0x222222ff);
|
||||
+static float bordercolor[] = COLOR(0x444444ff);
|
||||
+static float focuscolor[] = COLOR(0x005577ff);
|
||||
+static float urgentcolor[] = COLOR(0xff0000ff);
|
||||
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
|
||||
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index d48bf40..de33dfe 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -429,6 +429,8 @@ static xcb_atom_t netatom[NetLast];
|
||||
/* attempt to encapsulate suck into one file */
|
||||
#include "client.h"
|
||||
|
||||
+#include "env.c"
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applybounds(Client *c, struct wlr_box *bbox)
|
||||
@@ -1082,6 +1084,8 @@ createpointer(struct wlr_pointer *pointer)
|
||||
libinput_device_config_accel_set_profile(device, accel_profile);
|
||||
libinput_device_config_accel_set_speed(device, accel_speed);
|
||||
}
|
||||
+
|
||||
+ inputconfig(device);
|
||||
}
|
||||
|
||||
wlr_cursor_attach_input_device(cursor, &pointer->base);
|
||||
@@ -3141,6 +3145,7 @@ main(int argc, char *argv[])
|
||||
/* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */
|
||||
if (!getenv("XDG_RUNTIME_DIR"))
|
||||
die("XDG_RUNTIME_DIR must be set");
|
||||
+ loadtheme();
|
||||
setup();
|
||||
run(startup_cmd);
|
||||
cleanup();
|
||||
diff --git a/env.c b/env.c
|
||||
new file mode 100644
|
||||
index 0000000..618f81e
|
||||
--- /dev/null
|
||||
+++ b/env.c
|
||||
@@ -0,0 +1,217 @@
|
||||
+static int
|
||||
+isenabled(const char *val, int def)
|
||||
+{
|
||||
+ return ((def && (!val || !val[0] || (val[0] != '0'))) || (!def && (val && val[0] && (val[0] != '0'))));
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+setclickmethod(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+ long l;
|
||||
+ char *end = NULL;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_CLICK_METHOD");
|
||||
+ if (!val || !val[0])
|
||||
+ return;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ l = strtol(val, &end, 10);
|
||||
+ if (errno || (end && *end))
|
||||
+ return;
|
||||
+
|
||||
+ libinput_device_config_click_set_method(libinput_device,
|
||||
+ (enum libinput_config_click_method)l);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+settap(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_TAP");
|
||||
+ if (val) {
|
||||
+ if (!val[0])
|
||||
+ return;
|
||||
+
|
||||
+ libinput_device_config_tap_set_enabled(libinput_device,
|
||||
+ isenabled(val, 1) ? LIBINPUT_CONFIG_TAP_ENABLED :
|
||||
+ LIBINPUT_CONFIG_TAP_DISABLED);
|
||||
+ } else if (tap_to_click && libinput_device_config_tap_get_finger_count(libinput_device))
|
||||
+ libinput_device_config_tap_set_enabled(libinput_device,
|
||||
+ LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+settapanddrag(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_DRAG");
|
||||
+ if (val && val[0])
|
||||
+ libinput_device_config_tap_set_drag_enabled(libinput_device,
|
||||
+ isenabled(val, 1) ? LIBINPUT_CONFIG_DRAG_ENABLED :
|
||||
+ LIBINPUT_CONFIG_DRAG_DISABLED);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+setnaturalscroll(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_NATURAL_SCROLL");
|
||||
+ if (val && val[0])
|
||||
+ libinput_device_config_scroll_set_natural_scroll_enabled(
|
||||
+ libinput_device, isenabled(val, 0));
|
||||
+ else if (!val && libinput_device_config_scroll_has_natural_scroll(libinput_device))
|
||||
+ libinput_device_config_scroll_set_natural_scroll_enabled(
|
||||
+ libinput_device, natural_scrolling);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+setaccelprofile(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+ double profile;
|
||||
+ char *end = NULL;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_ACCELERATION_PROFILE");
|
||||
+ if (!val || !val[0])
|
||||
+ return;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ profile = strtod(val, &end);
|
||||
+ if (errno || (end && *end))
|
||||
+ return;
|
||||
+
|
||||
+ libinput_device_config_accel_set_profile(libinput_device,
|
||||
+ (enum libinput_config_accel_profile)profile);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+setaccelspeed(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+ double accel = 0;
|
||||
+ char *end = NULL;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_ACCELERATION");
|
||||
+ if (!val || !val[0])
|
||||
+ return;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ accel = strtod(val, &end);
|
||||
+ if (errno || (end && *end) || (accel < -1) || (accel > 1))
|
||||
+ return;
|
||||
+
|
||||
+ libinput_device_config_accel_set_speed(libinput_device, accel);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+setscrollmethod(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+ long l;
|
||||
+ char *end = NULL;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_SCROLL_METHOD");
|
||||
+ if (!val || !val[0])
|
||||
+ return;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ l = strtol(val, &end, 10);
|
||||
+ if (errno || (end && *end))
|
||||
+ return;
|
||||
+
|
||||
+ libinput_device_config_scroll_set_method(libinput_device,
|
||||
+ (enum libinput_config_scroll_method)l);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+setdwt(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_DISABLE_WHILE_TYPING");
|
||||
+ if (val && val[0])
|
||||
+ libinput_device_config_dwt_set_enabled(libinput_device,
|
||||
+ isenabled(val, false) ? LIBINPUT_CONFIG_DWT_ENABLED :
|
||||
+ LIBINPUT_CONFIG_DWT_DISABLED);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+setmiddleemul(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_MIDDLE_EMULATION");
|
||||
+ if (val && val[0])
|
||||
+ libinput_device_config_middle_emulation_set_enabled(libinput_device,
|
||||
+ isenabled(val, false) ? LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED :
|
||||
+ LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+setlefthanded(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ const char *val;
|
||||
+
|
||||
+ val = getenv("LIBINPUT_DEFAULT_LEFT_HANDED");
|
||||
+ if (val && val[0])
|
||||
+ libinput_device_config_left_handed_set(libinput_device,
|
||||
+ isenabled(val, 0));
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+inputconfig(struct libinput_device *libinput_device)
|
||||
+{
|
||||
+ setclickmethod(libinput_device);
|
||||
+ settap(libinput_device);
|
||||
+ settapanddrag(libinput_device);
|
||||
+ setnaturalscroll(libinput_device);
|
||||
+ setaccelprofile(libinput_device);
|
||||
+ setaccelspeed(libinput_device);
|
||||
+ setscrollmethod(libinput_device);
|
||||
+ setdwt(libinput_device);
|
||||
+ setmiddleemul(libinput_device);
|
||||
+ setlefthanded(libinput_device);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+parsecolor(const char *val, float color[4])
|
||||
+{
|
||||
+ uint8_t r, g, b;
|
||||
+ if (sscanf(val, "#%02hhx%02hhx%02hhx", &r, &g, &b) == 3) {
|
||||
+ color[0] = (float)r / 0xFF;
|
||||
+ color[1] = (float)g / 0xFF;
|
||||
+ color[2] = (float)b / 0xFF;
|
||||
+ color[3] = 1.0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+loadtheme(void)
|
||||
+{
|
||||
+ const char *val;
|
||||
+ unsigned int tmp;
|
||||
+
|
||||
+ val = getenv("DWL_ROOT_COLOR");
|
||||
+ if (val)
|
||||
+ parsecolor(val, rootcolor);
|
||||
+
|
||||
+ val = getenv("DWL_BORDER_COLOR");
|
||||
+ if (val)
|
||||
+ parsecolor(val, bordercolor);
|
||||
+
|
||||
+ val = getenv("DWL_FOCUS_COLOR");
|
||||
+ if (val)
|
||||
+ parsecolor(val, focuscolor);
|
||||
+
|
||||
+ val = getenv("DWL_URGENT_COLOR");
|
||||
+ if (val)
|
||||
+ parsecolor(val, urgentcolor);
|
||||
+
|
||||
+ val = getenv("DWL_BORDER");
|
||||
+ if (val && sscanf(val, "%u", &tmp) == 1)
|
||||
+ borderpx = tmp;
|
||||
+}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
### Description
|
||||
Allow setting fake fullscreen per client
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/notchoc/dwl/src/branch/fakefullscreenclient)
|
||||
- [2024-03-29](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/fakefullscreenclient/fakefullscreenclient.patch)
|
||||
### Authors
|
||||
- [notchoc](https://codeberg.org/notchoc)
|
||||
@@ -0,0 +1,87 @@
|
||||
From 2ec6d0c668b4daee601337f8da45ccfa3a7d5fc6 Mon Sep 17 00:00:00 2001
|
||||
From: choc <notchoc@proton.me>
|
||||
Date: Fri, 29 Mar 2024 22:50:00 +0800
|
||||
Subject: [PATCH] implement fakefullscreenclient
|
||||
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 23 ++++++++++++++++++++++-
|
||||
2 files changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 9009517..8c220eb 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -137,6 +137,7 @@ static const Key keys[] = {
|
||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_E, togglefakefullscreen, {0} },
|
||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index 5867b0c..1e78491 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -137,7 +137,7 @@ typedef struct {
|
||||
#endif
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
- int isfloating, isurgent, isfullscreen;
|
||||
+ int isfloating, isurgent, isfullscreen, isfakefullscreen;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
|
||||
@@ -318,6 +318,7 @@ static void setcursor(struct wl_listener *listener, void *data);
|
||||
static void setcursorshape(struct wl_listener *listener, void *data);
|
||||
static void setfloating(Client *c, int floating);
|
||||
static void setfullscreen(Client *c, int fullscreen);
|
||||
+static void setfakefullscreen(Client *c, int fullscreen);
|
||||
static void setgamma(struct wl_listener *listener, void *data);
|
||||
static void setlayout(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
@@ -332,6 +333,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *m);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void togglefullscreen(const Arg *arg);
|
||||
+static void togglefakefullscreen(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unlocksession(struct wl_listener *listener, void *data);
|
||||
@@ -2181,6 +2183,17 @@ setfullscreen(Client *c, int fullscreen)
|
||||
printstatus();
|
||||
}
|
||||
|
||||
+void
|
||||
+setfakefullscreen(Client *c, int fullscreen)
|
||||
+{
|
||||
+ c->isfakefullscreen = fullscreen;
|
||||
+ if (!c->mon)
|
||||
+ return;
|
||||
+ if (c->isfullscreen)
|
||||
+ setfullscreen(c, 0);
|
||||
+ client_set_fullscreen(c, fullscreen);
|
||||
+}
|
||||
+
|
||||
void
|
||||
setgamma(struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -2620,6 +2633,14 @@ togglefullscreen(const Arg *arg)
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
+void
|
||||
+togglefakefullscreen(const Arg *arg)
|
||||
+{
|
||||
+ Client *sel = focustop(selmon);
|
||||
+ if (sel)
|
||||
+ setfakefullscreen(sel, !sel->isfakefullscreen);
|
||||
+}
|
||||
+
|
||||
void
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
--
|
||||
2.44.0
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
### Description
|
||||
Tries a different display mode if the preferred mode doesn't work.
|
||||
|
||||
### Download
|
||||
- [2024-02-11](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/fallback/fallback.patch)
|
||||
|
||||
### Authors
|
||||
- [Dima Krasner](https://codeberg.org/dimkr) (<dima@dimakrasner.com>)
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
From a94c52af879027e654f67c36621a8c9b2f338f56 Mon Sep 17 00:00:00 2001
|
||||
From: Dima Krasner <dima@dimakrasner.com>
|
||||
Date: Sat, 2 Dec 2023 10:36:35 +0200
|
||||
Subject: [PATCH] fall back to a lower output mode if needed
|
||||
(swaywm/sway@4cdc4ac)
|
||||
|
||||
---
|
||||
dwl.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index d48bf40..7719f7e 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -920,6 +920,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||
/* This event is raised by the backend when a new output (aka a display or
|
||||
* monitor) becomes available. */
|
||||
struct wlr_output *wlr_output = data;
|
||||
+ struct wlr_output_mode *preferred_mode, *mode;
|
||||
const MonitorRule *r;
|
||||
size_t i;
|
||||
struct wlr_output_state state;
|
||||
@@ -956,7 +957,17 @@ createmon(struct wl_listener *listener, void *data)
|
||||
* monitor supports only a specific set of modes. We just pick the
|
||||
* monitor's preferred mode; a more sophisticated compositor would let
|
||||
* the user configure it. */
|
||||
- wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output));
|
||||
+ preferred_mode = wlr_output_preferred_mode(wlr_output);
|
||||
+ wlr_output_state_set_mode(&state, preferred_mode);
|
||||
+ if (!wlr_output_test_state(wlr_output, &state) && !wl_list_empty(&wlr_output->modes)) {
|
||||
+ wl_list_for_each(mode, &wlr_output->modes, link) {
|
||||
+ if (mode != preferred_mode) {
|
||||
+ wlr_output_state_set_mode(&state, mode);
|
||||
+ if (wlr_output_test_state(wlr_output, &state))
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* Set up event listeners */
|
||||
LISTEN(&wlr_output->events.frame, &m->frame, rendermon);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
### Description
|
||||
Focus the window to the left, right, above or below the current focused window
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/ldev105/dwl/src/branch/focusdir)
|
||||
- [2023-01-22](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/focusdir/focusdir.patch)
|
||||
|
||||
### Authors
|
||||
- [ldev105](https://codeberg.org/ldev105)
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
From a0e71a687b7fcaebdaf1da80c09bf5563bff46b1 Mon Sep 17 00:00:00 2001
|
||||
From: ldev <ldev@ldev.eu.org>
|
||||
Date: Mon, 12 Feb 2024 21:50:24 +0100
|
||||
Subject: [PATCH] focusdir
|
||||
|
||||
---
|
||||
config.def.h | 4 ++++
|
||||
dwl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 49 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 9009517..2a1a82e 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -124,6 +124,10 @@ static const Key keys[] = {
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_h, focusdir, {.ui = 0} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_l, focusdir, {.ui = 1} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_k, focusdir, {.ui = 2} },
|
||||
+ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_j, focusdir, {.ui = 3} },
|
||||
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf02a6d..64d5de7 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* See LICENSE file for copyright and license details.
|
||||
*/
|
||||
+#include <limits.h>
|
||||
#include <getopt.h>
|
||||
#include <libinput.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
@@ -268,6 +269,7 @@ static Monitor *dirtomon(enum wlr_direction dir);
|
||||
static void focusclient(Client *c, int lift);
|
||||
static void focusmon(const Arg *arg);
|
||||
static void focusstack(const Arg *arg);
|
||||
+static void focusdir(const Arg *arg);
|
||||
static Client *focustop(Monitor *m);
|
||||
static void fullscreennotify(struct wl_listener *listener, void *data);
|
||||
static void handlesig(int signo);
|
||||
@@ -1271,6 +1273,49 @@ focusstack(const Arg *arg)
|
||||
focusclient(c, 1);
|
||||
}
|
||||
|
||||
+void focusdir(const Arg *arg)
|
||||
+{
|
||||
+ /* Focus the left, right, up, down client relative to the current focused client on selmon */
|
||||
+ Client *c, *sel = focustop(selmon);
|
||||
+ if (!sel || sel->isfullscreen)
|
||||
+ return;
|
||||
+
|
||||
+ int dist=INT_MAX;
|
||||
+ Client *newsel = NULL;
|
||||
+ int newdist=INT_MAX;
|
||||
+ wl_list_for_each(c, &clients, link) {
|
||||
+ if (!VISIBLEON(c, selmon))
|
||||
+ continue; /* skip non visible windows */
|
||||
+
|
||||
+ if (arg->ui == 0 && sel->geom.x <= c->geom.x) {
|
||||
+ /* Client isn't on our left */
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (arg->ui == 1 && sel->geom.x >= c->geom.x) {
|
||||
+ /* Client isn't on our right */
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (arg->ui == 2 && sel->geom.y <= c->geom.y) {
|
||||
+ /* Client isn't above us */
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (arg->ui == 3 && sel->geom.y >= c->geom.y) {
|
||||
+ /* Client isn't below us */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ dist=abs(sel->geom.x-c->geom.x)+abs(sel->geom.y-c->geom.y);
|
||||
+ if (dist < newdist){
|
||||
+ newdist = dist;
|
||||
+ newsel=c;
|
||||
+ }
|
||||
+ }
|
||||
+ if (newsel != NULL){
|
||||
+ focusclient(newsel, 1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* We probably should change the name of this, it sounds like
|
||||
* will focus the topmost client of this mon, when actually will
|
||||
* only return that client */
|
||||
--
|
||||
2.43.0
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
### Description
|
||||
An extremely simple patch that adds the option to change DWL's window sending behavior; when active, sent windows will be followed, i.e. when a window is sent to another tag, the view changes to that tag.<br>No dependencies.
|
||||
|
||||

|
||||
|
||||
### Download
|
||||
- [v0.7](/dwl/dwl-patches/raw/branch/main/patches/follow/follow.patch)<br>Targets tag v0.7, but also works on git master and v0.6.
|
||||
|
||||
### Author
|
||||
- [moonsabre](https://codeberg.org/moonsabre)
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
From c4de366aa5e2a465f5e2963f4ffed7adde77929a Mon Sep 17 00:00:00 2001
|
||||
From: moonsabre <moonsabre@tuta.io>
|
||||
Date: Thu, 13 Mar 2025 14:36:49 -0700
|
||||
Subject: [PATCH] Add parameter for following sent windows.
|
||||
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwl.c | 2 ++
|
||||
2 files changed, 3 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 22d2171..cdbdc72 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -6,6 +6,7 @@
|
||||
/* appearance */
|
||||
static const int sloppyfocus = 1; /* focus follows mouse */
|
||||
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||
+static const int follow = 1; /* 1 means follow windows when sent to another tag */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const float rootcolor[] = COLOR(0x222222ff);
|
||||
static const float bordercolor[] = COLOR(0x444444ff);
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index a2711f6..d2cf8ba 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -2677,6 +2677,8 @@ tag(const Arg *arg)
|
||||
sel->tags = arg->ui & TAGMASK;
|
||||
focusclient(focustop(selmon), 1);
|
||||
arrange(selmon);
|
||||
+ if (follow == 1)
|
||||
+ view(arg);
|
||||
printstatus();
|
||||
}
|
||||
|
||||
--
|
||||
2.48.1
|
||||
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 607 KiB |
@@ -0,0 +1,9 @@
|
||||
### Description
|
||||
Implement `foreign-toplevel-management`, it add handlers for activate, close, fullscreen and destroy request events, it's missing minimize and maximize request handlers.
|
||||
|
||||
### Download
|
||||
- [git branch](https://codeberg.org/wochap/dwl/src/branch/v0.6-a/foreign-toplevel-management)
|
||||
- [2024-05-02](https://codeberg.org/dwl/dwl-patches/raw/commit/e58c3ec41a39df934d2998161d7187ac965ea77a/foreign-toplevel-management/foreign-toplevel-management.patch)
|
||||
|
||||
### Authors
|
||||
- [wochap](https://codeberg.org/wochap)
|
||||
+507
@@ -0,0 +1,507 @@
|
||||
From dc63d64cd69f515013464b3feb8acb411f5a348f Mon Sep 17 00:00:00 2001
|
||||
From: wochap <gean.marroquin@gmail.com>
|
||||
Date: Thu, 2 May 2024 17:25:45 -0500
|
||||
Subject: [PATCH] implement foreign toplevel management
|
||||
|
||||
---
|
||||
Makefile | 5 +-
|
||||
dwl.c | 93 +++++-
|
||||
...oreign-toplevel-management-unstable-v1.xml | 270 ++++++++++++++++++
|
||||
3 files changed, 366 insertions(+), 2 deletions(-)
|
||||
create mode 100644 protocols/wlr-foreign-toplevel-management-unstable-v1.xml
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index a67fdd3..e0e1260 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -16,7 +16,7 @@ LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
|
||||
all: dwl
|
||||
dwl: dwl.o util.o
|
||||
$(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@
|
||||
-dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h
|
||||
+dwl.o: dwl.c config.mk config.h client.h cursor-shape-v1-protocol.h pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h wlr-foreign-toplevel-management-unstable-v1-protocol.h
|
||||
util.o: util.c util.h
|
||||
|
||||
# wayland-scanner is a tool which generates C headers and rigging for Wayland
|
||||
@@ -37,6 +37,9 @@ wlr-layer-shell-unstable-v1-protocol.h:
|
||||
xdg-shell-protocol.h:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||
+wlr-foreign-toplevel-management-unstable-v1-protocol.h:
|
||||
+ $(WAYLAND_SCANNER) server-header \
|
||||
+ protocols/wlr-foreign-toplevel-management-unstable-v1.xml $@
|
||||
|
||||
config.h:
|
||||
cp config.def.h $@
|
||||
diff --git a/dwl.c b/dwl.c
|
||||
index bf763df..648616d 100644
|
||||
--- a/dwl.c
|
||||
+++ b/dwl.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_drm.h>
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
+#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||
@@ -126,6 +127,11 @@ typedef struct {
|
||||
struct wl_listener fullscreen;
|
||||
struct wl_listener set_decoration_mode;
|
||||
struct wl_listener destroy_decoration;
|
||||
+ struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel;
|
||||
+ struct wl_listener factivate;
|
||||
+ struct wl_listener fclose;
|
||||
+ struct wl_listener ffullscreen;
|
||||
+ struct wl_listener fdestroy;
|
||||
struct wlr_box prev; /* layout-relative, includes border */
|
||||
struct wlr_box bounds;
|
||||
#ifdef XWAYLAND
|
||||
@@ -347,6 +353,11 @@ static Monitor *xytomon(double x, double y);
|
||||
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||
static void zoom(const Arg *arg);
|
||||
+static void createforeigntoplevel(Client *c);
|
||||
+static void factivatenotify(struct wl_listener *listener, void *data);
|
||||
+static void fclosenotify(struct wl_listener *listener, void *data);
|
||||
+static void fdestroynotify(struct wl_listener *listener, void *data);
|
||||
+static void ffullscreennotify(struct wl_listener *listener, void *data);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
@@ -392,6 +403,8 @@ static struct wlr_scene_rect *locked_bg;
|
||||
static struct wlr_session_lock_v1 *cur_lock;
|
||||
static struct wl_listener lock_listener = {.notify = locksession};
|
||||
|
||||
+static struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_mgr;
|
||||
+
|
||||
static struct wlr_seat *seat;
|
||||
static KeyboardGroup kb_group = {0};
|
||||
static KeyboardGroup vkb_group = {0};
|
||||
@@ -458,6 +471,11 @@ applyrules(Client *c)
|
||||
if (!(title = client_get_title(c)))
|
||||
title = broken;
|
||||
|
||||
+ if (c->foreign_toplevel) {
|
||||
+ wlr_foreign_toplevel_handle_v1_set_app_id(c->foreign_toplevel, appid);
|
||||
+ wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title);
|
||||
+ }
|
||||
+
|
||||
for (r = rules; r < END(rules); r++) {
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
@@ -1288,6 +1306,8 @@ focusclient(Client *c, int lift)
|
||||
client_set_border_color(old_c, bordercolor);
|
||||
|
||||
client_activate_surface(old, 0);
|
||||
+ if (old_c->foreign_toplevel)
|
||||
+ wlr_foreign_toplevel_handle_v1_set_activated(old_c->foreign_toplevel, 0);
|
||||
}
|
||||
}
|
||||
printstatus();
|
||||
@@ -1306,6 +1326,8 @@ focusclient(Client *c, int lift)
|
||||
|
||||
/* Activate the new client */
|
||||
client_activate_surface(client_surface(c), 1);
|
||||
+ if (c->foreign_toplevel)
|
||||
+ wlr_foreign_toplevel_handle_v1_set_activated(c->foreign_toplevel, 1);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1599,6 +1621,8 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
c->border[i]->node.data = c;
|
||||
}
|
||||
|
||||
+ createforeigntoplevel(c);
|
||||
+
|
||||
/* Initialize client geometry with room for border */
|
||||
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
||||
c->geom.width += 2 * c->bw;
|
||||
@@ -2232,12 +2256,17 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
|
||||
c->prev = c->geom;
|
||||
|
||||
/* Scene graph sends surface leave/enter events on move and resize */
|
||||
- if (oldmon)
|
||||
+ if (oldmon) {
|
||||
+ if (c->foreign_toplevel)
|
||||
+ wlr_foreign_toplevel_handle_v1_output_leave(c->foreign_toplevel, oldmon->wlr_output);
|
||||
arrange(oldmon);
|
||||
+ }
|
||||
if (m) {
|
||||
/* Make sure window actually overlaps with the monitor */
|
||||
resize(c, c->geom, 0);
|
||||
c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */
|
||||
+ if (c->foreign_toplevel)
|
||||
+ wlr_foreign_toplevel_handle_v1_output_enter(c->foreign_toplevel, m->wlr_output);
|
||||
setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */
|
||||
setfloating(c, c->isfloating);
|
||||
}
|
||||
@@ -2351,6 +2380,9 @@ setup(void)
|
||||
gamma_control_mgr = wlr_gamma_control_manager_v1_create(dpy);
|
||||
LISTEN_STATIC(&gamma_control_mgr->events.set_gamma, setgamma);
|
||||
|
||||
+ /* Initializes foreign toplevel management */
|
||||
+ foreign_toplevel_mgr = wlr_foreign_toplevel_manager_v1_create(dpy);
|
||||
+
|
||||
/* Creates an output layout, which a wlroots utility for working with an
|
||||
* arrangement of screens in a physical layout. */
|
||||
output_layout = wlr_output_layout_create();
|
||||
@@ -2691,6 +2723,11 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&c->flink);
|
||||
}
|
||||
|
||||
+ if (c->foreign_toplevel) {
|
||||
+ wlr_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel);
|
||||
+ c->foreign_toplevel = NULL;
|
||||
+ }
|
||||
+
|
||||
wlr_scene_node_destroy(&c->scene->node);
|
||||
printstatus();
|
||||
motionnotify(0, NULL, 0, 0, 0, 0);
|
||||
@@ -2802,6 +2839,12 @@ void
|
||||
updatetitle(struct wl_listener *listener, void *data)
|
||||
{
|
||||
Client *c = wl_container_of(listener, c, set_title);
|
||||
+ if (c->foreign_toplevel) {
|
||||
+ const char *title;
|
||||
+ if (!(title = client_get_title(c)))
|
||||
+ title = broken;
|
||||
+ wlr_foreign_toplevel_handle_v1_set_title(c->foreign_toplevel, title);
|
||||
+ }
|
||||
if (c == focustop(c->mon))
|
||||
printstatus();
|
||||
}
|
||||
@@ -2929,6 +2972,54 @@ zoom(const Arg *arg)
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
+void
|
||||
+createforeigntoplevel(Client *c)
|
||||
+{
|
||||
+ c->foreign_toplevel = wlr_foreign_toplevel_handle_v1_create(foreign_toplevel_mgr);
|
||||
+
|
||||
+ LISTEN(&c->foreign_toplevel->events.request_activate, &c->factivate, factivatenotify);
|
||||
+ LISTEN(&c->foreign_toplevel->events.request_close, &c->fclose, fclosenotify);
|
||||
+ LISTEN(&c->foreign_toplevel->events.request_fullscreen, &c->ffullscreen, ffullscreennotify);
|
||||
+ LISTEN(&c->foreign_toplevel->events.destroy, &c->fdestroy, fdestroynotify);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+factivatenotify(struct wl_listener *listener, void *data)
|
||||
+{
|
||||
+ Client *c = wl_container_of(listener, c, factivate);
|
||||
+ if (c->mon == selmon) {
|
||||
+ c->tags = c->mon->tagset[c->mon->seltags];
|
||||
+ } else {
|
||||
+ setmon(c, selmon, 0);
|
||||
+ }
|
||||
+ focusclient(c, 1);
|
||||
+ arrange(c->mon);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+fclosenotify(struct wl_listener *listener, void *data)
|
||||
+{
|
||||
+ Client *c = wl_container_of(listener, c, fclose);
|
||||
+ client_send_close(c);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+ffullscreennotify(struct wl_listener *listener, void *data) {
|
||||
+ Client *c = wl_container_of(listener, c, ffullscreen);
|
||||
+ struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
|
||||
+ setfullscreen(c, event->fullscreen);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+fdestroynotify(struct wl_listener *listener, void *data)
|
||||
+{
|
||||
+ Client *c = wl_container_of(listener, c, fdestroy);
|
||||
+ wl_list_remove(&c->factivate.link);
|
||||
+ wl_list_remove(&c->fclose.link);
|
||||
+ wl_list_remove(&c->ffullscreen.link);
|
||||
+ wl_list_remove(&c->fdestroy.link);
|
||||
+}
|
||||
+
|
||||
#ifdef XWAYLAND
|
||||
void
|
||||
activatex11(struct wl_listener *listener, void *data)
|
||||
diff --git a/protocols/wlr-foreign-toplevel-management-unstable-v1.xml b/protocols/wlr-foreign-toplevel-management-unstable-v1.xml
|
||||
new file mode 100644
|
||||
index 0000000..44505bb
|
||||
--- /dev/null
|
||||
+++ b/protocols/wlr-foreign-toplevel-management-unstable-v1.xml
|
||||
@@ -0,0 +1,270 @@
|
||||
+<?xml version="1.0" encoding="UTF-8"?>
|
||||
+<protocol name="wlr_foreign_toplevel_management_unstable_v1">
|
||||
+ <copyright>
|
||||
+ Copyright © 2018 Ilia Bozhinov
|
||||
+
|
||||
+ Permission to use, copy, modify, distribute, and sell this
|
||||
+ software and its documentation for any purpose is hereby granted
|
||||
+ without fee, provided that the above copyright notice appear in
|
||||
+ all copies and that both that copyright notice and this permission
|
||||
+ notice appear in supporting documentation, and that the name of
|
||||
+ the copyright holders not be used in advertising or publicity
|
||||
+ pertaining to distribution of the software without specific,
|
||||
+ written prior permission. The copyright holders make no
|
||||
+ representations about the suitability of this software for any
|
||||
+ purpose. It is provided "as is" without express or implied
|
||||
+ warranty.
|
||||
+
|
||||
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
+ THIS SOFTWARE.
|
||||
+ </copyright>
|
||||
+
|
||||
+ <interface name="zwlr_foreign_toplevel_manager_v1" version="3">
|
||||
+ <description summary="list and control opened apps">
|
||||
+ The purpose of this protocol is to enable the creation of taskbars
|
||||
+ and docks by providing them with a list of opened applications and
|
||||
+ letting them request certain actions on them, like maximizing, etc.
|
||||
+
|
||||
+ After a client binds the zwlr_foreign_toplevel_manager_v1, each opened
|
||||
+ toplevel window will be sent via the toplevel event
|
||||
+ </description>
|
||||
+
|
||||
+ <event name="toplevel">
|
||||
+ <description summary="a toplevel has been created">
|
||||
+ This event is emitted whenever a new toplevel window is created. It
|
||||
+ is emitted for all toplevels, regardless of the app that has created
|
||||
+ them.
|
||||
+
|
||||
+ All initial details of the toplevel(title, app_id, states, etc.) will
|
||||
+ be sent immediately after this event via the corresponding events in
|
||||
+ zwlr_foreign_toplevel_handle_v1.
|
||||
+ </description>
|
||||
+ <arg name="toplevel" type="new_id" interface="zwlr_foreign_toplevel_handle_v1"/>
|
||||
+ </event>
|
||||
+
|
||||
+ <request name="stop">
|
||||
+ <description summary="stop sending events">
|
||||
+ Indicates the client no longer wishes to receive events for new toplevels.
|
||||
+ However the compositor may emit further toplevel_created events, until
|
||||
+ the finished event is emitted.
|
||||
+
|
||||
+ The client must not send any more requests after this one.
|
||||
+ </description>
|
||||
+ </request>
|
||||
+
|
||||
+ <event name="finished" type="destructor">
|
||||
+ <description summary="the compositor has finished with the toplevel manager">
|
||||
+ This event indicates that the compositor is done sending events to the
|
||||
+ zwlr_foreign_toplevel_manager_v1. The server will destroy the object
|
||||
+ immediately after sending this request, so it will become invalid and
|
||||
+ the client should free any resources associated with it.
|
||||
+ </description>
|
||||
+ </event>
|
||||
+ </interface>
|
||||
+
|
||||
+ <interface name="zwlr_foreign_toplevel_handle_v1" version="3">
|
||||
+ <description summary="an opened toplevel">
|
||||
+ A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
|
||||
+ window. Each app may have multiple opened toplevels.
|
||||
+
|
||||
+ Each toplevel has a list of outputs it is visible on, conveyed to the
|
||||
+ client with the output_enter and output_leave events.
|
||||
+ </description>
|
||||
+
|
||||
+ <event name="title">
|
||||
+ <description summary="title change">
|
||||
+ This event is emitted whenever the title of the toplevel changes.
|
||||
+ </description>
|
||||
+ <arg name="title" type="string"/>
|
||||
+ </event>
|
||||
+
|
||||
+ <event name="app_id">
|
||||
+ <description summary="app-id change">
|
||||
+ This event is emitted whenever the app-id of the toplevel changes.
|
||||
+ </description>
|
||||
+ <arg name="app_id" type="string"/>
|
||||
+ </event>
|
||||
+
|
||||
+ <event name="output_enter">
|
||||
+ <description summary="toplevel entered an output">
|
||||
+ This event is emitted whenever the toplevel becomes visible on
|
||||
+ the given output. A toplevel may be visible on multiple outputs.
|
||||
+ </description>
|
||||
+ <arg name="output" type="object" interface="wl_output"/>
|
||||
+ </event>
|
||||
+
|
||||
+ <event name="output_leave">
|
||||
+ <description summary="toplevel left an output">
|
||||
+ This event is emitted whenever the toplevel stops being visible on
|
||||
+ the given output. It is guaranteed that an entered-output event
|
||||
+ with the same output has been emitted before this event.
|
||||
+ </description>
|
||||
+ <arg name="output" type="object" interface="wl_output"/>
|
||||
+ </event>
|
||||
+
|
||||
+ <request name="set_maximized">
|
||||
+ <description summary="requests that the toplevel be maximized">
|
||||
+ Requests that the toplevel be maximized. If the maximized state actually
|
||||
+ changes, this will be indicated by the state event.
|
||||
+ </description>
|
||||
+ </request>
|
||||
+
|
||||
+ <request name="unset_maximized">
|
||||
+ <description summary="requests that the toplevel be unmaximized">
|
||||
+ Requests that the toplevel be unmaximized. If the maximized state actually
|
||||
+ changes, this will be indicated by the state event.
|
||||
+ </description>
|
||||
+ </request>
|
||||
+
|
||||
+ <request name="set_minimized">
|
||||
+ <description summary="requests that the toplevel be minimized">
|
||||
+ Requests that the toplevel be minimized. If the minimized state actually
|
||||
+ changes, this will be indicated by the state event.
|
||||
+ </description>
|
||||
+ </request>
|
||||
+
|
||||
+ <request name="unset_minimized">
|
||||
+ <description summary="requests that the toplevel be unminimized">
|
||||
+ Requests that the toplevel be unminimized. If the minimized state actually
|
||||
+ changes, this will be indicated by the state event.
|
||||
+ </description>
|
||||
+ </request>
|
||||
+
|
||||
+ <request name="activate">
|
||||
+ <description summary="activate the toplevel">
|
||||
+ Request that this toplevel be activated on the given seat.
|
||||
+ There is no guarantee the toplevel will be actually activated.
|
||||
+ </description>
|
||||
+ <arg name="seat" type="object" interface="wl_seat"/>
|
||||
+ </request>
|
||||
+
|
||||
+ <enum name="state">
|
||||
+ <description summary="types of states on the toplevel">
|
||||
+ The different states that a toplevel can have. These have the same meaning
|
||||
+ as the states with the same names defined in xdg-toplevel
|
||||
+ </description>
|
||||
+
|
||||
+ <entry name="maximized" value="0" summary="the toplevel is maximized"/>
|
||||
+ <entry name="minimized" value="1" summary="the toplevel is minimized"/>
|
||||
+ <entry name="activated" value="2" summary="the toplevel is active"/>
|
||||
+ <entry name="fullscreen" value="3" summary="the toplevel is fullscreen" since="2"/>
|
||||
+ </enum>
|
||||
+
|
||||
+ <event name="state">
|
||||
+ <description summary="the toplevel state changed">
|
||||
+ This event is emitted immediately after the zlw_foreign_toplevel_handle_v1
|
||||
+ is created and each time the toplevel state changes, either because of a
|
||||
+ compositor action or because of a request in this protocol.
|
||||
+ </description>
|
||||
+
|
||||
+ <arg name="state" type="array"/>
|
||||
+ </event>
|
||||
+
|
||||
+ <event name="done">
|
||||
+ <description summary="all information about the toplevel has been sent">
|
||||
+ This event is sent after all changes in the toplevel state have been
|
||||
+ sent.
|
||||
+
|
||||
+ This allows changes to the zwlr_foreign_toplevel_handle_v1 properties
|
||||
+ to be seen as atomic, even if they happen via multiple events.
|
||||
+ </description>
|
||||
+ </event>
|
||||
+
|
||||
+ <request name="close">
|
||||
+ <description summary="request that the toplevel be closed">
|
||||
+ Send a request to the toplevel to close itself. The compositor would
|
||||
+ typically use a shell-specific method to carry out this request, for
|
||||
+ example by sending the xdg_toplevel.close event. However, this gives
|
||||
+ no guarantees the toplevel will actually be destroyed. If and when
|
||||
+ this happens, the zwlr_foreign_toplevel_handle_v1.closed event will
|
||||
+ be emitted.
|
||||
+ </description>
|
||||
+ </request>
|
||||
+
|
||||
+ <request name="set_rectangle">
|
||||
+ <description summary="the rectangle which represents the toplevel">
|
||||
+ The rectangle of the surface specified in this request corresponds to
|
||||
+ the place where the app using this protocol represents the given toplevel.
|
||||
+ It can be used by the compositor as a hint for some operations, e.g
|
||||
+ minimizing. The client is however not required to set this, in which
|
||||
+ case the compositor is free to decide some default value.
|
||||
+
|
||||
+ If the client specifies more than one rectangle, only the last one is
|
||||
+ considered.
|
||||
+
|
||||
+ The dimensions are given in surface-local coordinates.
|
||||
+ Setting width=height=0 removes the already-set rectangle.
|
||||
+ </description>
|
||||
+
|
||||
+ <arg name="surface" type="object" interface="wl_surface"/>
|
||||
+ <arg name="x" type="int"/>
|
||||
+ <arg name="y" type="int"/>
|
||||
+ <arg name="width" type="int"/>
|
||||
+ <arg name="height" type="int"/>
|
||||
+ </request>
|
||||
+
|
||||
+ <enum name="error">
|
||||
+ <entry name="invalid_rectangle" value="0"
|
||||
+ summary="the provided rectangle is invalid"/>
|
||||
+ </enum>
|
||||
+
|
||||
+ <event name="closed">
|
||||
+ <description summary="this toplevel has been destroyed">
|
||||
+ This event means the toplevel has been destroyed. It is guaranteed there
|
||||
+ won't be any more events for this zwlr_foreign_toplevel_handle_v1. The
|
||||
+ toplevel itself becomes inert so any requests will be ignored except the
|
||||
+ destroy request.
|
||||
+ </description>
|
||||
+ </event>
|
||||
+
|
||||
+ <request name="destroy" type="destructor">
|
||||
+ <description summary="destroy the zwlr_foreign_toplevel_handle_v1 object">
|
||||
+ Destroys the zwlr_foreign_toplevel_handle_v1 object.
|
||||
+
|
||||
+ This request should be called either when the client does not want to
|
||||
+ use the toplevel anymore or after the closed event to finalize the
|
||||
+ destruction of the object.
|
||||
+ </description>
|
||||
+ </request>
|
||||
+
|
||||
+ <!-- Version 2 additions -->
|
||||
+
|
||||
+ <request name="set_fullscreen" since="2">
|
||||
+ <description summary="request that the toplevel be fullscreened">
|
||||
+ Requests that the toplevel be fullscreened on the given output. If the
|
||||
+ fullscreen state and/or the outputs the toplevel is visible on actually
|
||||
+ change, this will be indicated by the state and output_enter/leave
|
||||
+ events.
|
||||
+
|
||||
+ The output parameter is only a hint to the compositor. Also, if output
|
||||
+ is NULL, the compositor should decide which output the toplevel will be
|
||||
+ fullscreened on, if at all.
|
||||
+ </description>
|
||||
+ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
+ </request>
|
||||
+
|
||||
+ <request name="unset_fullscreen" since="2">
|
||||
+ <description summary="request that the toplevel be unfullscreened">
|
||||
+ Requests that the toplevel be unfullscreened. If the fullscreen state
|
||||
+ actually changes, this will be indicated by the state event.
|
||||
+ </description>
|
||||
+ </request>
|
||||
+
|
||||
+ <!-- Version 3 additions -->
|
||||
+
|
||||
+ <event name="parent" since="3">
|
||||
+ <description summary="parent change">
|
||||
+ This event is emitted whenever the parent of the toplevel changes.
|
||||
+
|
||||
+ No event is emitted when the parent handle is destroyed by the client.
|
||||
+ </description>
|
||||
+ <arg name="parent" type="object" interface="zwlr_foreign_toplevel_handle_v1" allow-null="true"/>
|
||||
+ </event>
|
||||
+ </interface>
|
||||
+</protocol>
|
||||
--
|
||||
2.43.2
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user