mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-07-10 11:04:10 -04:00
commit
621ea37a24
48 changed files with 2500 additions and 4052 deletions
692
LICENSE.dwl
692
LICENSE.dwl
|
|
@ -1,692 +0,0 @@
|
||||||
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>.
|
|
||||||
39
LICENSE.dwm
39
LICENSE.dwm
|
|
@ -1,39 +0,0 @@
|
||||||
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.
|
|
||||||
19
LICENSE.sway
19
LICENSE.sway
|
|
@ -1,19 +0,0 @@
|
||||||
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.
|
|
||||||
127
LICENSE.tinywl
127
LICENSE.tinywl
|
|
@ -1,127 +0,0 @@
|
||||||
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.
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
Copyright (c) 2017, 2018 Drew DeVault
|
|
||||||
Copyright (c) 2014 Jari Vetoniemi
|
|
||||||
Copyright (c) 2023 The wlroots contributors
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
@ -114,6 +114,13 @@ bindr=Super,Super_L,spawn,rofi -show run
|
||||||
| `exchange_stack_client` | `next/prev` | Exchange window position in stack. |
|
| `exchange_stack_client` | `next/prev` | Exchange window position in stack. |
|
||||||
| `zoom` | - | Swap focused window with Master. |
|
| `zoom` | - | Swap focused window with Master. |
|
||||||
|
|
||||||
|
### Group
|
||||||
|
| Command | Param | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `groupjoin` | `left/right/up/down` | Join group by direction. |
|
||||||
|
| `groupfocus` | `prev/next` | Focus group member by direction. |
|
||||||
|
| `groupleave` | - | Leave group. |
|
||||||
|
|
||||||
### Tags & Monitors
|
### Tags & Monitors
|
||||||
|
|
||||||
| Command | Param | Description |
|
| Command | Param | Description |
|
||||||
|
|
@ -170,11 +177,12 @@ bindr=Super,Super_L,spawn,rofi -show run
|
||||||
| `setkeymode` | `mode` | Set keymode. |
|
| `setkeymode` | `mode` | Set keymode. |
|
||||||
| `switch_keyboard_layout` | `[index]` | Switch keyboard layout. Optional index (0, 1, 2...) to switch to specific layout. |
|
| `switch_keyboard_layout` | `[index]` | Switch keyboard layout. Optional index (0, 1, 2...) to switch to specific layout. |
|
||||||
| `setoption` | `key,value` | Set config option temporarily. |
|
| `setoption` | `key,value` | Set config option temporarily. |
|
||||||
| `disable_monitor` | `monitor_spec` | Shutdown monitor. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
| `sleep_monitor` | `monitor_spec` | Shutdown monitor power but not remove. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
||||||
| `enable_monitor` | `monitor_spec` | Power on monitor. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
| `wakeup_monitor` | `monitor_spec` | Turn on monitor power. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
||||||
| `toggle_monitor` | `monitor_spec` | Toggle monitor power. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
| `sleep_toggle_monitor` | `monitor_spec` | Toggle monitor power but not remove. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format).
|
||||||
| `chvt` | `1-9` | Change virtual terminal (tty, equivalent to using ctrl+alt+Fkeys) |
|
| `disable_monitor` | `monitor_spec` | remove monitor. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
||||||
|
| `enable_monitor` | `monitor_spec` | add monitor. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
||||||
|
| `toggle_monitor` | `monitor_spec` | Toggle monitor add/remove. Accepts a [monitor spec](/docs/configuration/monitors#monitor-spec-format). |
|
||||||
|
|
||||||
### Media Controls
|
### Media Controls
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,9 @@ description: Advanced settings for XWayland, focus behavior, and system integrat
|
||||||
| Setting | Default | Description |
|
| Setting | Default | Description |
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| `xwayland_persistence` | `1` | Keep XWayland running even when no X11 apps are open (reduces startup lag). |
|
| `xwayland_persistence` | `1` | Keep XWayland running even when no X11 apps are open (reduces startup lag). |
|
||||||
| `syncobj_enable` | `0` | Enable `drm_syncobj` timeline support (helps with gaming stutter/lag). **Requires restart.** |
|
| `syncobj_enable` | `1` | Enable `drm_syncobj` timeline support (helps with gaming stutter/lag). **Requires restart.** |
|
||||||
| `allow_lock_transparent` | `0` | Allow the lock screen to be transparent. |
|
| `allow_lock_transparent` | `0` | Allow the lock screen to be transparent. |
|
||||||
| `allow_shortcuts_inhibit` | `1` | Allow shortcuts to be inhibited by clients. |
|
| `allow_shortcuts_inhibit` | `1` | Allow shortcuts to be inhibited by clients. |
|
||||||
| `vrr` | - | Set via [monitor rule](/docs/configuration/monitors#monitor-rules). |
|
|
||||||
|
|
||||||
## Focus & Input
|
## Focus & Input
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,10 @@ monitorrule=name:Values,Parameter:Values,Parameter:Values
|
||||||
| `y` | integer | 0-99999 | Y position |
|
| `y` | integer | 0-99999 | Y position |
|
||||||
| `scale` | float | 0.01-100.0 | Monitor scale |
|
| `scale` | float | 0.01-100.0 | Monitor scale |
|
||||||
| `vrr` | integer | 0, 1 | Enable variable refresh rate |
|
| `vrr` | integer | 0, 1 | Enable variable refresh rate |
|
||||||
|
| `hdr` | integer | 0, 1 | Enable hdr support |
|
||||||
| `rr` | integer | 0-7 | Monitor transform |
|
| `rr` | integer | 0-7 | Monitor transform |
|
||||||
| `custom` | integer | 0, 1 | Enable custom mode (not supported on all displays — may cause black screen) |
|
| `custom` | integer | 0, 1 | Enable custom mode (not supported on all displays — may cause black screen) |
|
||||||
|
| `disable` | integer | 0, 1 | Disable the monitor |
|
||||||
|
|
||||||
### Transform Values
|
### Transform Values
|
||||||
|
|
||||||
|
|
@ -102,6 +104,21 @@ Tearing allows games to bypass the compositor's VSync for lower latency.
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| `allow_tearing` | `0` | Global tearing control: `0` (Disable), `1` (Enable), `2` (Fullscreen only). |
|
| `allow_tearing` | `0` | Global tearing control: `0` (Disable), `1` (Enable), `2` (Fullscreen only). |
|
||||||
|
|
||||||
|
## HDR
|
||||||
|
| Setting | Default | Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `hdr_depth` | `2`| Set the hdr depth for the current display. `0` is Default, `1` is HDR8, `2` is HDR10. |
|
||||||
|
|
||||||
|
- you should enable HDR in monitorrule first, refer to [Monitors — Monitor Rules](/docs/configuration/monitors#monitor-rules)
|
||||||
|
- you must set `env=WLR_RENDERER,vulkan` before mango starts.
|
||||||
|
|
||||||
|
#### for example(must relogin once after setting):
|
||||||
|
```conf
|
||||||
|
env=WLR_RENDERER,vulkan
|
||||||
|
monitorrule=name:eDP-1,model:0x15F5,width:1920,height:1080,refresh:60,x:0,y:0,scale:1,vrr:0,rr:0:hdr:1
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
**Enable Globally:**
|
**Enable Globally:**
|
||||||
|
|
@ -130,16 +147,9 @@ windowrule=force_tearing:1,title:vkcube
|
||||||
|
|
||||||
> **Warning:** Some graphics cards require setting the `WLR_DRM_NO_ATOMIC` environment variable before mango starts to successfully enable tearing.
|
> **Warning:** Some graphics cards require setting the `WLR_DRM_NO_ATOMIC` environment variable before mango starts to successfully enable tearing.
|
||||||
|
|
||||||
Add this to `/etc/environment` and reboot:
|
Add this to config and relogin mango:
|
||||||
|
|
||||||
```bash
|
|
||||||
WLR_DRM_NO_ATOMIC=1
|
|
||||||
```
|
```
|
||||||
|
env=WLR_DRM_NO_ATOMIC,1
|
||||||
Or run mango with the environment variable:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
WLR_DRM_NO_ATOMIC=1 mango
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -156,7 +166,7 @@ WLR_DRM_DEVICES=/dev/dri/card1 mango
|
||||||
WLR_DRM_DEVICES=/dev/dri/card0:/dev/dri/card1 mango
|
WLR_DRM_DEVICES=/dev/dri/card0:/dev/dri/card1 mango
|
||||||
```
|
```
|
||||||
|
|
||||||
Some GPUs have compatibility issues with `syncobj_enable=1` — it may crash apps like `kitty` that use syncobj. Set `WLR_DRM_NO_ATOMIC=1` in `/etc/environment` and reboot to resolve this.
|
Some GPUs have compatibility issues with `syncobj_enable=1` — it may crash apps like `kitty` that use syncobj. Set `env=WLR_DRM_NO_ATOMIC,1` in `config.conf` and relogin to resolve this.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,8 @@ Then force it for your specific game:
|
||||||
windowrule=force_tearing:1,title:Counter-Strike 2
|
windowrule=force_tearing:1,title:Counter-Strike 2
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Warning:** Some graphics cards require setting `WLR_DRM_NO_ATOMIC=1` before mango starts for tearing to work. Add it to `/etc/environment` and reboot, or launch mango with `WLR_DRM_NO_ATOMIC=1 mango`. See [Monitors — Tearing](/docs/configuration/monitors#tearing-game-mode) for details.
|
> **Warning:** Some graphics cards require setting `env=WLR_DRM_NO_ATOMIC,1` in config before mango starts for tearing to work.
|
||||||
|
> See [Monitors — Tearing](/docs/configuration/monitors#tearing-game-mode) for details.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ description: Configure Waybar for mangowm.
|
||||||
|
|
||||||
mangowm is compatible with Waybar's `ext/workspaces` module (Wayland standard) or the `dwl/tags` module. We recommend `ext/workspaces` for the best experience.
|
mangowm is compatible with Waybar's `ext/workspaces` module (Wayland standard) or the `dwl/tags` module. We recommend `ext/workspaces` for the best experience.
|
||||||
|
|
||||||
> **Tip:** You can also use the `dwl/tags` module, but `ext/workspaces` provides better integration with mangowm's features. The `ext/workspaces` module requires **Waybar > 0.14.0**.
|
|
||||||
|
|
||||||
### `config.jsonc`
|
### `config.jsonc`
|
||||||
|
|
||||||
Add the following to your Waybar configuration:
|
Add the following to your Waybar configuration:
|
||||||
|
|
@ -16,23 +14,42 @@ Add the following to your Waybar configuration:
|
||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
"modules-left": [
|
"modules-left": [
|
||||||
"ext/workspaces",
|
"mango/workspaces",
|
||||||
"dwl/window"
|
"mango/layout",
|
||||||
|
"mango/window"
|
||||||
],
|
],
|
||||||
"ext/workspaces": {
|
"modules-right": [
|
||||||
"format": "{icon}",
|
"mango/language",
|
||||||
"ignore-hidden": true,
|
"mango/keymode",
|
||||||
"on-click": "activate",
|
],
|
||||||
"on-click-right": "deactivate",
|
"mango/workspaces": {
|
||||||
"sort-by-id": true
|
"format": "{icon}",
|
||||||
|
"hide-empty": true,
|
||||||
|
"on-click": "activate",
|
||||||
|
"on-click-right": "toggle",
|
||||||
|
"overview-label": "OVERVIEW",
|
||||||
|
},
|
||||||
|
"mango/keymode": {
|
||||||
|
"format": "{}",
|
||||||
|
// "format-default": " Default",
|
||||||
|
// "format-test": " Test",
|
||||||
|
},
|
||||||
|
"mango/window": {
|
||||||
|
"format": "{}",
|
||||||
|
"icon-size": 20
|
||||||
|
},
|
||||||
|
"mango/layout": {
|
||||||
|
"format": "{}",
|
||||||
|
// "format-S": "Scroller",
|
||||||
|
// "format-T": "Tile",
|
||||||
|
},
|
||||||
|
"mango/language": {
|
||||||
|
"format": "{short}",
|
||||||
},
|
},
|
||||||
"dwl/window": {
|
|
||||||
"format": "[{layout}] {title}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Styling
|
## Styling Example
|
||||||
|
|
||||||
You can style the tags using standard CSS in `style.css`.
|
You can style the tags using standard CSS in `style.css`.
|
||||||
|
|
||||||
|
|
@ -40,27 +57,13 @@ You can style the tags using standard CSS in `style.css`.
|
||||||
|
|
||||||
```css
|
```css
|
||||||
#workspaces {
|
#workspaces {
|
||||||
border-radius: 4px;
|
|
||||||
border-width: 2px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: #c9b890;
|
border-color: #c9b890;
|
||||||
margin-left: 4px;
|
|
||||||
padding-left: 10px;
|
|
||||||
padding-right: 6px;
|
|
||||||
background: rgba(40, 40, 40, 0.76);
|
background: rgba(40, 40, 40, 0.76);
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button {
|
#workspaces button {
|
||||||
border: none;
|
|
||||||
background: none;
|
background: none;
|
||||||
box-shadow: inherit;
|
|
||||||
text-shadow: inherit;
|
|
||||||
color: #ddca9e;
|
color: #ddca9e;
|
||||||
padding: 1px;
|
|
||||||
padding-left: 1px;
|
|
||||||
padding-right: 1px;
|
|
||||||
margin-right: 2px;
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button.hidden {
|
#workspaces button.hidden {
|
||||||
|
|
@ -79,61 +82,44 @@ You can style the tags using standard CSS in `style.css`.
|
||||||
#workspaces button.active {
|
#workspaces button.active {
|
||||||
background-color: #ddca9e;
|
background-color: #ddca9e;
|
||||||
color: #282828;
|
color: #282828;
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
padding-top: 1px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button.urgent {
|
#workspaces button.urgent {
|
||||||
background-color: #ef5e5e;
|
background-color: #ef5e5e;
|
||||||
color: #282828;
|
color: #282828;
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
padding-top: 1px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#tags {
|
#workspaces button.overview {
|
||||||
background-color: transparent;
|
background-color: #ef5e5e;
|
||||||
}
|
color: #282828;
|
||||||
|
|
||||||
#tags button {
|
|
||||||
background-color: #fff;
|
|
||||||
color: #a585cd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button:not(.occupied):not(.focused) {
|
|
||||||
font-size: 0;
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 0;
|
|
||||||
margin: -17px;
|
|
||||||
padding: 0;
|
|
||||||
color: transparent;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button.occupied {
|
|
||||||
background-color: #fff;
|
|
||||||
color: #cdc885;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button.focused {
|
|
||||||
background-color: rgb(186, 142, 213);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tags button.urgent {
|
|
||||||
background: rgb(171, 101, 101);
|
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#window {
|
#window {
|
||||||
background-color: rgb(237, 196, 147);
|
background-color: #CA9297;
|
||||||
color: rgb(63, 37, 5);
|
color: #282828;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window#waybar.empty #window {
|
||||||
|
background: none;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layout {
|
||||||
|
background-color: #CA9297;
|
||||||
|
color: #282828;
|
||||||
|
}
|
||||||
|
|
||||||
|
#language {
|
||||||
|
background-color: #CA9297;
|
||||||
|
color: #282828;
|
||||||
|
}
|
||||||
|
|
||||||
|
#keymode {
|
||||||
|
background-color: #CA9297;
|
||||||
|
color: #282828;
|
||||||
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Complete Configuration Example
|
## Complete Configuration Example
|
||||||
|
|
|
||||||
|
|
@ -69,17 +69,17 @@ You can also color-code windows based on their state:
|
||||||
### Tab Bar For Monocle Layout
|
### Tab Bar For Monocle Layout
|
||||||
| Setting | Default | Description |
|
| Setting | Default | Description |
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| `tab_bar_height` | `50` | Height of the tab bar for monocle layout. |
|
| `group_bar_height` | `50` | Height of the tab bar for monocle layout. |
|
||||||
| `tab_bar_decorate_fg_color` | `0xc4939dff` | text color.
|
| `group_bar_decorate_fg_color` | `0xc4939dff` | text color.
|
||||||
| `tab_bar_decorate_bg_color` | `0x201b14ff` | background color.|
|
| `group_bar_decorate_bg_color` | `0x201b14ff` | background color.|
|
||||||
| `tab_bar_decorate_focus_fg_color` | `0x201b14ff` | text color for focus. |
|
| `group_bar_decorate_focus_fg_color` | `0x201b14ff` | text color for focus. |
|
||||||
| `tab_bar_decorate_focus_bg_color` | `0xc4939dff` | background color for focus.|
|
| `group_bar_decorate_focus_bg_color` | `0xc4939dff` | background color for focus.|
|
||||||
| `tab_bar_decorate_border_color` | `0x8BAA9Bff` | border color.|
|
| `group_bar_decorate_border_color` | `0x8BAA9Bff` | border color.|
|
||||||
| `tab_bar_decorate_border_width` | `4` | border width.|
|
| `group_bar_decorate_border_width` | `4` | border width.|
|
||||||
| `tab_bar_decorate_corner_radius` | `5` | corner radius.|
|
| `group_bar_decorate_corner_radius` | `5` | corner radius.|
|
||||||
| `tab_bar_decorate_padding_x` | `0` | horizontal padding.|
|
| `group_bar_decorate_padding_x` | `0` | horizontal padding.|
|
||||||
| `tab_bar_decorate_padding_y` | `0` | vertical padding.|
|
| `group_bar_decorate_padding_y` | `0` | vertical padding.|
|
||||||
| `tab_bar_decorate_font_desc` | `monospace Bold 16` | font set.|
|
| `group_bar_decorate_font_desc` | `monospace Bold 16` | font set.|
|
||||||
|
|
||||||
## Borders
|
## Borders
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ windowrule=Parameter:Values,Parameter:Values,appid:Values,title:Values
|
||||||
| `single_scratchpad` | integer | `0` / `1` (default 1) | Only show one out of named scratchpads or the normal scratchpad |
|
| `single_scratchpad` | integer | `0` / `1` (default 1) | Only show one out of named scratchpads or the normal scratchpad |
|
||||||
| `allow_shortcuts_inhibit` | integer | `0` / `1` (default 1) | Allow shortcuts to be inhibited by clients |
|
| `allow_shortcuts_inhibit` | integer | `0` / `1` (default 1) | Allow shortcuts to be inhibited by clients |
|
||||||
| `idleinhibit_when_focus` | integer | `0` / `1` (default 0) | Automatically keep idle inhibit active when this window is focused |
|
| `idleinhibit_when_focus` | integer | `0` / `1` (default 0) | Automatically keep idle inhibit active when this window is focused |
|
||||||
|
| `vrr_only_fullscreen` | integer | `0` / `1` (default 0) | VRR only fullscreen,you need to turn `vrr` to `0` in monitor rule first |
|
||||||
|
| `shield_when_capture` | integer | `0` / `1` | Shield window when captured |
|
||||||
|
|
||||||
|
|
||||||
### Geometry & Position
|
### Geometry & Position
|
||||||
|
|
||||||
|
|
@ -138,7 +141,7 @@ windowrule=offsetx:20,offsety:-30,width:800,height:600,appid:alacritty
|
||||||
# Send to specific tag and monitor
|
# Send to specific tag and monitor
|
||||||
windowrule=tags:9,monitor:HDMI-A-1,appid:discord
|
windowrule=tags:9,monitor:HDMI-A-1,appid:discord
|
||||||
|
|
||||||
# Terminal swallowing setup
|
# Terminal swallowdby setup
|
||||||
windowrule=isterm:1,appid:st
|
windowrule=isterm:1,appid:st
|
||||||
windowrule=noswallow:1,appid:foot
|
windowrule=noswallow:1,appid:foot
|
||||||
|
|
||||||
|
|
@ -237,6 +240,7 @@ layerrule=layer_name:Values,Parameter:Values,Parameter:Values
|
||||||
| `noblur` | integer | `0` / `1` | Disable blur |
|
| `noblur` | integer | `0` / `1` | Disable blur |
|
||||||
| `noanim` | integer | `0` / `1` | Disable layer animation |
|
| `noanim` | integer | `0` / `1` | Disable layer animation |
|
||||||
| `noshadow` | integer | `0` / `1` | Disable layer shadow |
|
| `noshadow` | integer | `0` / `1` | Disable layer shadow |
|
||||||
|
| `shield_when_capture`| integer | `0` / `1` | Shield layer when captured.(it is better to combination with `noanim:1`) |
|
||||||
|
|
||||||
> **Tip:** For animation types, see [Animations](/docs/visuals/animations#animation-types). For visual effects, see [Window Effects](/docs/visuals/effects).
|
> **Tip:** For animation types, see [Animations](/docs/visuals/animations#animation-types). For visual effects, see [Window Effects](/docs/visuals/effects).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,12 @@ libdrm = dependency('libdrm')
|
||||||
xcb = dependency('xcb', required : get_option('xwayland'))
|
xcb = dependency('xcb', required : get_option('xwayland'))
|
||||||
xlibs = dependency('xcb-icccm', required : get_option('xwayland'))
|
xlibs = dependency('xcb-icccm', required : get_option('xwayland'))
|
||||||
wayland_server_dep = dependency('wayland-server',version: '>=1.23.1')
|
wayland_server_dep = dependency('wayland-server',version: '>=1.23.1')
|
||||||
wlroots_dep = dependency('wlroots-0.19',version: '>=0.19.0')
|
wlroots_dep = dependency('wlroots-0.20',version: '>=0.20.0')
|
||||||
xkbcommon_dep = dependency('xkbcommon')
|
xkbcommon_dep = dependency('xkbcommon')
|
||||||
libinput_dep = dependency('libinput',version: '>=1.27.1')
|
libinput_dep = dependency('libinput',version: '>=1.27.1')
|
||||||
libwayland_client_dep = dependency('wayland-client')
|
libwayland_client_dep = dependency('wayland-client')
|
||||||
pcre2_dep = dependency('libpcre2-8')
|
pcre2_dep = dependency('libpcre2-8')
|
||||||
libscenefx_dep = dependency('scenefx-0.4',version: '>=0.4.1')
|
libscenefx_dep = dependency('scenefx-0.5',version: '>=0.5.0')
|
||||||
pixman_dep = dependency('pixman-1')
|
pixman_dep = dependency('pixman-1')
|
||||||
cjson_dep = dependency('libcjson')
|
cjson_dep = dependency('libcjson')
|
||||||
pangocairo_dep = dependency('pangocairo')
|
pangocairo_dep = dependency('pangocairo')
|
||||||
|
|
@ -97,7 +97,7 @@ executable('mango',
|
||||||
'src/mango.c',
|
'src/mango.c',
|
||||||
'src/common/util.c',
|
'src/common/util.c',
|
||||||
'src/draw/text-node.c',
|
'src/draw/text-node.c',
|
||||||
'src/ext-protocol/wlr_ext_workspace_v1.c',
|
|
||||||
wayland_sources,
|
wayland_sources,
|
||||||
dependencies : [
|
dependencies : [
|
||||||
libm,
|
libm,
|
||||||
|
|
@ -121,7 +121,6 @@ executable('mango',
|
||||||
)
|
)
|
||||||
|
|
||||||
# build mmsg
|
# build mmsg
|
||||||
dwl_ipc_protocol = 'protocols/dwl-ipc-unstable-v2.xml'
|
|
||||||
|
|
||||||
wayland_scanner_client_header = generator(
|
wayland_scanner_client_header = generator(
|
||||||
wayland_scanner,
|
wayland_scanner,
|
||||||
|
|
@ -138,8 +137,6 @@ wayland_scanner_private_code = generator(
|
||||||
# use generator in mmsg target
|
# use generator in mmsg target
|
||||||
executable('mmsg',
|
executable('mmsg',
|
||||||
'mmsg/mmsg.c',
|
'mmsg/mmsg.c',
|
||||||
wayland_scanner_private_code.process(dwl_ipc_protocol),
|
|
||||||
wayland_scanner_client_header.process(dwl_ipc_protocol),
|
|
||||||
dependencies: [
|
dependencies: [
|
||||||
libwayland_client_dep
|
libwayland_client_dep
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,253 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
This is largely ripped from somebar's ipc patchset; just with some personal modifications.
|
|
||||||
I would probably just submit raphi's patchset but I don't think that would be polite.
|
|
||||||
-->
|
|
||||||
<protocol name="dwl_ipc_unstable_v2">
|
|
||||||
<description summary="inter-proccess-communication about dwl's state">
|
|
||||||
This protocol allows clients to update and get updates from dwl.
|
|
||||||
|
|
||||||
Warning! The protocol described in this file is experimental and
|
|
||||||
backward incompatible changes may be made. Backward compatible
|
|
||||||
changes may be added together with the corresponding interface
|
|
||||||
version bump.
|
|
||||||
Backward incompatible changes are done by bumping the version
|
|
||||||
number in the protocol and interface names and resetting the
|
|
||||||
interface version. Once the protocol is to be declared stable,
|
|
||||||
the 'z' prefix and the version number in the protocol and
|
|
||||||
interface names are removed and the interface version number is
|
|
||||||
reset.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<interface name="zdwl_ipc_manager_v2" version="2">
|
|
||||||
<description summary="manage dwl state">
|
|
||||||
This interface is exposed as a global in wl_registry.
|
|
||||||
|
|
||||||
Clients can use this interface to get a dwl_ipc_output.
|
|
||||||
After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
|
|
||||||
The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<request name="release" type="destructor">
|
|
||||||
<description summary="release dwl_ipc_manager">
|
|
||||||
Indicates that the client will not the dwl_ipc_manager object anymore.
|
|
||||||
Objects created through this instance are not affected.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="get_output">
|
|
||||||
<description summary="get a dwl_ipc_outout for a wl_output">
|
|
||||||
Get a dwl_ipc_outout for the specified wl_output.
|
|
||||||
</description>
|
|
||||||
<arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
|
|
||||||
<arg name="output" type="object" interface="wl_output"/>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<event name="tags">
|
|
||||||
<description summary="Announces tag amount">
|
|
||||||
This event is sent after binding.
|
|
||||||
A roundtrip after binding guarantees the client recieved all tags.
|
|
||||||
</description>
|
|
||||||
<arg name="amount" type="uint"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="layout">
|
|
||||||
<description summary="Announces a layout">
|
|
||||||
This event is sent after binding.
|
|
||||||
A roundtrip after binding guarantees the client recieved all layouts.
|
|
||||||
</description>
|
|
||||||
<arg name="name" type="string"/>
|
|
||||||
</event>
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
<interface name="zdwl_ipc_output_v2" version="2">
|
|
||||||
<description summary="control dwl output">
|
|
||||||
Observe and control a dwl output.
|
|
||||||
|
|
||||||
Events are double-buffered:
|
|
||||||
Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
|
|
||||||
|
|
||||||
Request are not double-buffered:
|
|
||||||
The compositor will update immediately upon request.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<enum name="tag_state">
|
|
||||||
<entry name="none" value="0" summary="no state"/>
|
|
||||||
<entry name="active" value="1" summary="tag is active"/>
|
|
||||||
<entry name="urgent" value="2" summary="tag has at least one urgent client"/>
|
|
||||||
</enum>
|
|
||||||
|
|
||||||
<request name="release" type="destructor">
|
|
||||||
<description summary="release dwl_ipc_outout">
|
|
||||||
Indicates to that the client no longer needs this dwl_ipc_output.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<event name="toggle_visibility">
|
|
||||||
<description summary="Toggle client visibilty">
|
|
||||||
Indicates the client should hide or show themselves.
|
|
||||||
If the client is visible then hide, if hidden then show.
|
|
||||||
</description>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="active">
|
|
||||||
<description summary="Update the selected output.">
|
|
||||||
Indicates if the output is active. Zero is invalid, nonzero is valid.
|
|
||||||
</description>
|
|
||||||
<arg name="active" type="uint"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="tag">
|
|
||||||
<description summary="Update the state of a tag.">
|
|
||||||
Indicates that a tag has been updated.
|
|
||||||
</description>
|
|
||||||
<arg name="tag" type="uint" summary="Index of the tag"/>
|
|
||||||
<arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
|
|
||||||
<arg name="clients" type="uint" summary="The number of clients in the tag."/>
|
|
||||||
<arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="layout">
|
|
||||||
<description summary="Update the layout.">
|
|
||||||
Indicates a new layout is selected.
|
|
||||||
</description>
|
|
||||||
<arg name="layout" type="uint" summary="Index of the layout."/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="title">
|
|
||||||
<description summary="Update the title.">
|
|
||||||
Indicates the title has changed.
|
|
||||||
</description>
|
|
||||||
<arg name="title" type="string" summary="The new title name."/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="appid" since="1">
|
|
||||||
<description summary="Update the appid.">
|
|
||||||
Indicates the appid has changed.
|
|
||||||
</description>
|
|
||||||
<arg name="appid" type="string" summary="The new appid."/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="layout_symbol" since="1">
|
|
||||||
<description summary="Update the current layout symbol">
|
|
||||||
Indicates the layout has changed. Since layout symbols are dynamic.
|
|
||||||
As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying.
|
|
||||||
You can ignore the zdwl_ipc_output.layout event.
|
|
||||||
</description>
|
|
||||||
<arg name="layout" type="string" summary="The new layout"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="frame">
|
|
||||||
<description summary="The update sequence is done.">
|
|
||||||
Indicates that a sequence of status updates have finished and the client should redraw.
|
|
||||||
</description>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<request name="set_tags">
|
|
||||||
<description summary="Set the active tags of this output"/>
|
|
||||||
<arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
|
|
||||||
<arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="set_client_tags">
|
|
||||||
<description summary="Set the tags of the focused client.">
|
|
||||||
The tags are updated as follows:
|
|
||||||
new_tags = (current_tags AND and_tags) XOR xor_tags
|
|
||||||
</description>
|
|
||||||
<arg name="and_tags" type="uint"/>
|
|
||||||
<arg name="xor_tags" type="uint"/>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="set_layout">
|
|
||||||
<description summary="Set the layout of this output"/>
|
|
||||||
<arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="quit" since="2">
|
|
||||||
<description summary="Quit mango">This request allows clients to instruct the compositor to quit mango.</description>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="dispatch" since="2">
|
|
||||||
<description summary="Set the active tags of this output"/>
|
|
||||||
<arg name="dispatch" type="string" summary="dispatch name."/>
|
|
||||||
<arg name="arg1" type="string" summary="arg1."/>
|
|
||||||
<arg name="arg2" type="string" summary="arg2."/>
|
|
||||||
<arg name="arg3" type="string" summary="arg3."/>
|
|
||||||
<arg name="arg4" type="string" summary="arg4."/>
|
|
||||||
<arg name="arg5" type="string" summary="arg5."/>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<!-- Version 2 -->
|
|
||||||
<event name="fullscreen" since="2">
|
|
||||||
<description summary="Update fullscreen status">
|
|
||||||
Indicates if the selected client on this output is fullscreen.
|
|
||||||
</description>
|
|
||||||
<arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="floating" since="2">
|
|
||||||
<description summary="Update the floating status">
|
|
||||||
Indicates if the selected client on this output is floating.
|
|
||||||
</description>
|
|
||||||
<arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="x" since="2">
|
|
||||||
<description summary="Update the x coordinates">
|
|
||||||
Indicates if x coordinates of the selected client.
|
|
||||||
</description>
|
|
||||||
<arg name="x" type="int" summary="x coordinate of the selected client"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="y" since="2">
|
|
||||||
<description summary="Update the y coordinates">
|
|
||||||
Indicates if y coordinates of the selected client.
|
|
||||||
</description>
|
|
||||||
<arg name="y" type="int" summary="y coordinate of the selected client"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="width" since="2">
|
|
||||||
<description summary="Update the width">
|
|
||||||
Indicates if width of the selected client.
|
|
||||||
</description>
|
|
||||||
<arg name="width" type="int" summary="width of the selected client"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="height" since="2">
|
|
||||||
<description summary="Update the height">
|
|
||||||
Indicates if height of the selected client.
|
|
||||||
</description>
|
|
||||||
<arg name="height" type="int" summary="height of the selected client"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="last_layer" since="2">
|
|
||||||
<description summary="last map layer.">
|
|
||||||
last map layer.
|
|
||||||
</description>
|
|
||||||
<arg name="last_layer" type="string" summary="last map layer."/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="kb_layout" since="2">
|
|
||||||
<description summary="current keyboard layout.">
|
|
||||||
current keyboard layout.
|
|
||||||
</description>
|
|
||||||
<arg name="kb_layout" type="string" summary="current keyboard layout."/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="keymode" since="2">
|
|
||||||
<description summary="current keybind mode.">
|
|
||||||
current keybind mode.
|
|
||||||
</description>
|
|
||||||
<arg name="keymode" type="string" summary="current keybind mode."/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="scalefactor" since="2">
|
|
||||||
<description summary="scale factor of monitor.">
|
|
||||||
scale factor of monitor.
|
|
||||||
</description>
|
|
||||||
<arg name="scalefactor" type="uint" summary="scale factor of monitor."/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
</protocol>
|
|
||||||
|
|
@ -21,7 +21,6 @@ wayland_xmls = [
|
||||||
wl_protocol_dir + '/staging/ext-workspace/ext-workspace-v1.xml',
|
wl_protocol_dir + '/staging/ext-workspace/ext-workspace-v1.xml',
|
||||||
wl_protocol_dir + '/staging/tearing-control/tearing-control-v1.xml',
|
wl_protocol_dir + '/staging/tearing-control/tearing-control-v1.xml',
|
||||||
'wlr-foreign-toplevel-management-unstable-v1.xml',
|
'wlr-foreign-toplevel-management-unstable-v1.xml',
|
||||||
'dwl-ipc-unstable-v2.xml',
|
|
||||||
'wlr-layer-shell-unstable-v1.xml',
|
'wlr-layer-shell-unstable-v1.xml',
|
||||||
'wlr-output-power-management-unstable-v1.xml',
|
'wlr-output-power-management-unstable-v1.xml',
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ static void finish_exchange_arrange_and_focus(Client *c1, Client *c2,
|
||||||
} else {
|
} else {
|
||||||
arrange(c1->mon, false, false);
|
arrange(c1->mon, false, false);
|
||||||
}
|
}
|
||||||
wl_list_remove(&c2->flink);
|
|
||||||
wl_list_insert(&c1->flink, &c2->flink);
|
wl_list_safe_reinsert_next(&c1->flink, &c2->flink);
|
||||||
|
|
||||||
if (config.warpcursor)
|
if (config.warpcursor)
|
||||||
warp_cursor(c1);
|
warp_cursor(c1);
|
||||||
|
|
@ -57,7 +57,14 @@ void client_tile_resize(Client *c, struct wlr_box geo, int32_t interact) {
|
||||||
if (!ISFAKETILED(c))
|
if (!ISFAKETILED(c))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!c->isfullscreen && !c->ismaximizescreen) {
|
if (!c->mon->isoverview && !c->isfullscreen &&
|
||||||
|
(c->group_next || c->group_prev)) {
|
||||||
|
geo.y = geo.y + config.group_bar_height;
|
||||||
|
geo.height -= config.group_bar_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!c->isfullscreen && !c->ismaximizescreen) ||
|
||||||
|
is_scroller_layout(c->mon)) {
|
||||||
resize(c, geo, interact);
|
resize(c, geo, interact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +80,7 @@ void client_active(Client *c) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->swallowing || !c->mon)
|
if (c->swallowdby || !c->mon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c->isminimized) {
|
if (c->isminimized) {
|
||||||
|
|
@ -104,19 +111,199 @@ void client_add_jump_label_node(Client *c) {
|
||||||
wlr_scene_node_set_enabled(&c->jump_label_node->scene_buffer->node, false);
|
wlr_scene_node_set_enabled(&c->jump_label_node->scene_buffer->node, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_add_tab_bar_node(Client *c) {
|
void client_add_group_bar(Client *c) {
|
||||||
|
|
||||||
if (config.tab_bar_height <= 0) {
|
if (config.group_bar_height <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MangoNodeData *mangonodedata = ecalloc(1, sizeof(MangoNodeData));
|
uint32_t layer = c->isoverlay ? LyrOverlay
|
||||||
mangonodedata->node_data = c;
|
: c->isfloating || c->isfullscreen ? LyrTop
|
||||||
mangonodedata->type = MANGO_TITLE_NODE;
|
: c->ismaximizescreen ? LyrMaximize
|
||||||
|
: LyrTile;
|
||||||
|
|
||||||
c->tab_bar_node = mango_tab_bar_node_create(
|
c->group_bar = mango_group_bar_create(c, GroupBar, layers[layer],
|
||||||
mangonodedata, layers[LyrDecorate], config.tabdata, 0, 0);
|
config.groupbardata, 0, 0);
|
||||||
wlr_scene_node_lower_to_bottom(&c->tab_bar_node->scene_buffer->node);
|
wlr_scene_node_lower_to_bottom(&c->group_bar->scene_buffer->node);
|
||||||
wlr_scene_node_set_enabled(&c->tab_bar_node->scene_buffer->node, false);
|
wlr_scene_node_set_enabled(&c->group_bar->scene_buffer->node, false);
|
||||||
mango_tab_bar_node_update(c->tab_bar_node, client_get_title(c), 1.0);
|
mango_group_bar_update(c->group_bar, client_get_title(c),
|
||||||
|
c->mon ? c->mon->wlr_output->scale
|
||||||
|
: selmon ? selmon->wlr_output->scale
|
||||||
|
: 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void client_focus_group_member(Client *c) {
|
||||||
|
if (!c->group_prev && !c->group_next)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (c->isgroupfocusing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Client *head = c;
|
||||||
|
while (head->group_prev)
|
||||||
|
head = head->group_prev;
|
||||||
|
|
||||||
|
Client *cur_focusing = NULL;
|
||||||
|
while (head) {
|
||||||
|
if (head->isgroupfocusing) {
|
||||||
|
cur_focusing = head;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
head = head->group_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cur_focusing || !cur_focusing->mon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cur_focusing && cur_focusing->mon->isoverview)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cur_focusing->isgroupfocusing = false;
|
||||||
|
c->mon = cur_focusing->mon;
|
||||||
|
client_replace(c, cur_focusing, true, false);
|
||||||
|
mango_group_bar_set_focus(cur_focusing->group_bar, false);
|
||||||
|
|
||||||
|
c->isgroupfocusing = true;
|
||||||
|
mango_group_bar_set_focus(c->group_bar, true);
|
||||||
|
|
||||||
|
client_reparent_group(c);
|
||||||
|
|
||||||
|
focusclient(c, 1);
|
||||||
|
|
||||||
|
arrange(c->mon, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_check_tab_node_visible(Client *c) {
|
||||||
|
|
||||||
|
if (!c || !c->mon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Client *head = c;
|
||||||
|
while (head->group_prev)
|
||||||
|
head = head->group_prev;
|
||||||
|
|
||||||
|
Client *cur = head;
|
||||||
|
while (cur) {
|
||||||
|
if (!c->mon->isoverview && cur->group_bar &&
|
||||||
|
(cur->group_next || cur->group_prev) && TAGMATCH(c, c->mon) &&
|
||||||
|
ISNORMAL(c) && !c->isfullscreen) {
|
||||||
|
wlr_scene_node_set_enabled(&cur->group_bar->scene_buffer->node,
|
||||||
|
true);
|
||||||
|
} else {
|
||||||
|
wlr_scene_node_set_enabled(&cur->group_bar->scene_buffer->node,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
cur = cur->group_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_raise_group(Client *c) {
|
||||||
|
if (!c || !c->mon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Client *head = c;
|
||||||
|
while (head->group_prev)
|
||||||
|
head = head->group_prev;
|
||||||
|
|
||||||
|
Client *cur = head;
|
||||||
|
while (cur) {
|
||||||
|
if (cur->group_bar) {
|
||||||
|
wlr_scene_node_raise_to_top(&cur->group_bar->scene_buffer->node);
|
||||||
|
}
|
||||||
|
wlr_scene_node_raise_to_top(&cur->scene->node);
|
||||||
|
cur = cur->group_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_reparent_group(Client *c) {
|
||||||
|
if (!c || !c->mon)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32_t layer = c->isoverlay ? LyrOverlay
|
||||||
|
: c->isfloating || c->isfullscreen ? LyrTop
|
||||||
|
: c->ismaximizescreen ? LyrMaximize
|
||||||
|
: LyrTile;
|
||||||
|
|
||||||
|
Client *head = c;
|
||||||
|
while (head->group_prev)
|
||||||
|
head = head->group_prev;
|
||||||
|
|
||||||
|
Client *cur = head;
|
||||||
|
while (cur) {
|
||||||
|
if (cur->group_bar) {
|
||||||
|
wlr_scene_node_reparent(&cur->group_bar->scene_buffer->node,
|
||||||
|
layers[layer]);
|
||||||
|
}
|
||||||
|
wlr_scene_node_reparent(&cur->scene->node, layers[layer]);
|
||||||
|
cur = cur->group_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_handle_decorate_click(MangoGroupBar *gb) {
|
||||||
|
|
||||||
|
if (!gb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (gb->node_data) {
|
||||||
|
Client *c = gb->node_data;
|
||||||
|
client_focus_group_member(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_group_mon(Client *c, Monitor *m) {
|
||||||
|
Client *head = c;
|
||||||
|
while (head->group_prev)
|
||||||
|
head = head->group_prev;
|
||||||
|
|
||||||
|
Client *cur = head;
|
||||||
|
while (cur) {
|
||||||
|
client_change_mon(cur, m);
|
||||||
|
cur = cur->group_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_group_config(Client *c) {
|
||||||
|
Client *head = c;
|
||||||
|
while (head->group_prev)
|
||||||
|
head = head->group_prev;
|
||||||
|
|
||||||
|
Client *cur = head;
|
||||||
|
while (cur) {
|
||||||
|
mango_jump_label_node_apply_config(cur->jump_label_node,
|
||||||
|
&config.jumplabeldata);
|
||||||
|
wlr_scene_rect_set_color(cur->droparea, config.dropcolor);
|
||||||
|
wlr_scene_rect_set_color(cur->splitindicator[0], config.splitcolor);
|
||||||
|
wlr_scene_rect_set_color(cur->splitindicator[1], config.splitcolor);
|
||||||
|
mango_group_bar_apply_config(cur->group_bar, &config.groupbardata);
|
||||||
|
cur = cur->group_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_group_detach(Client *c) {
|
||||||
|
if (c->group_prev)
|
||||||
|
c->group_prev->group_next = c->group_next;
|
||||||
|
if (c->group_next)
|
||||||
|
c->group_next->group_prev = c->group_prev;
|
||||||
|
c->group_prev = NULL;
|
||||||
|
c->group_next = NULL;
|
||||||
|
c->isgroupfocusing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_group_replace(Client *old, Client *new) {
|
||||||
|
client_group_detach(new);
|
||||||
|
|
||||||
|
new->group_prev = old->group_prev;
|
||||||
|
new->group_next = old->group_next;
|
||||||
|
if (old->group_prev)
|
||||||
|
old->group_prev->group_next = new;
|
||||||
|
if (old->group_next)
|
||||||
|
old->group_next->group_prev = new;
|
||||||
|
old->group_prev = NULL;
|
||||||
|
old->group_next = NULL;
|
||||||
|
|
||||||
|
if (old->is_logic_hide || (!new->group_prev && !new->group_next)) {
|
||||||
|
new->isgroupfocusing = false;
|
||||||
|
} else {
|
||||||
|
new->isgroupfocusing = old->isgroupfocusing;
|
||||||
|
}
|
||||||
|
}
|
||||||
61
src/action/monitor.h
Normal file
61
src/action/monitor.h
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
bool mango_scene_output_commit(struct wlr_scene_output *scene_output,
|
||||||
|
struct wlr_output_state *state) {
|
||||||
|
struct wlr_output *wlr_output = scene_output->output;
|
||||||
|
Monitor *m = wlr_output->data;
|
||||||
|
bool committed = false;
|
||||||
|
|
||||||
|
bool frame_allow_tearing = check_tearing_frame_allow(m);
|
||||||
|
|
||||||
|
if (!wlr_scene_output_needs_frame(scene_output))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 构建状态,将场景的 Buffer 附着到 state 上
|
||||||
|
if (!wlr_scene_output_build_state(scene_output, state, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (frame_allow_tearing) {
|
||||||
|
state->tearing_page_flip = true;
|
||||||
|
} else {
|
||||||
|
state->tearing_page_flip = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试是否支持撕裂
|
||||||
|
if (state->tearing_page_flip == true) {
|
||||||
|
if (!wlr_output_test_state(wlr_output, state)) {
|
||||||
|
// 如果 DRM 拒绝(例如当前输出/驱动不支持撕裂),降级关闭撕裂
|
||||||
|
state->tearing_page_flip = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交状态
|
||||||
|
committed = wlr_output_commit_state(wlr_output, state);
|
||||||
|
if (!committed && state->tearing_page_flip) {
|
||||||
|
// 重试一次
|
||||||
|
state->tearing_page_flip = false;
|
||||||
|
committed = wlr_output_commit_state(wlr_output, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (committed) {
|
||||||
|
if (state == &m->pending) {
|
||||||
|
wlr_output_state_finish(&m->pending);
|
||||||
|
wlr_output_state_init(&m->pending);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_INFO, "Failed to commit output %s", m->wlr_output->name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return committed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mango_output_commit(Monitor *m) {
|
||||||
|
|
||||||
|
bool committed = wlr_output_commit_state(m->wlr_output, &m->pending);
|
||||||
|
if (committed) {
|
||||||
|
wlr_output_state_finish(&m->pending);
|
||||||
|
wlr_output_state_init(&m->pending);
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to commit frame");
|
||||||
|
}
|
||||||
|
return committed;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -30,7 +30,7 @@ struct dvec2 calculate_animation_curve_at(double t, int32_t type) {
|
||||||
|
|
||||||
void handle_snapshot_meta_destroy(struct wl_listener *listener, void *data) {
|
void handle_snapshot_meta_destroy(struct wl_listener *listener, void *data) {
|
||||||
SnapshotMetadata *meta = wl_container_of(listener, meta, destroy);
|
SnapshotMetadata *meta = wl_container_of(listener, meta, destroy);
|
||||||
wl_list_remove(&meta->destroy.link); // 安全移除监听器
|
wl_list_remove(&meta->destroy.link);
|
||||||
free(meta);
|
free(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,6 +175,7 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
||||||
}
|
}
|
||||||
meta->orig_width = scene_buffer->dst_width;
|
meta->orig_width = scene_buffer->dst_width;
|
||||||
meta->orig_height = scene_buffer->dst_height;
|
meta->orig_height = scene_buffer->dst_height;
|
||||||
|
meta->type = Snapshot;
|
||||||
|
|
||||||
struct wlr_scene_surface *scene_surface =
|
struct wlr_scene_surface *scene_surface =
|
||||||
wlr_scene_surface_try_from_buffer(scene_buffer);
|
wlr_scene_surface_try_from_buffer(scene_buffer);
|
||||||
|
|
@ -212,11 +213,8 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
||||||
|
|
||||||
// Effects
|
// Effects
|
||||||
wlr_scene_buffer_set_opacity(snapshot_buffer, scene_buffer->opacity);
|
wlr_scene_buffer_set_opacity(snapshot_buffer, scene_buffer->opacity);
|
||||||
wlr_scene_buffer_set_corner_radius(snapshot_buffer,
|
wlr_scene_buffer_set_corner_radii(snapshot_buffer,
|
||||||
scene_buffer->corner_radius,
|
scene_buffer->corners);
|
||||||
scene_buffer->corners);
|
|
||||||
|
|
||||||
wlr_scene_buffer_set_backdrop_blur(snapshot_buffer, false);
|
|
||||||
|
|
||||||
if (scene_surface != NULL && scene_surface->surface->buffer != NULL) {
|
if (scene_surface != NULL && scene_surface->surface->buffer != NULL) {
|
||||||
wlr_scene_buffer_set_buffer(snapshot_buffer,
|
wlr_scene_buffer_set_buffer(snapshot_buffer,
|
||||||
|
|
@ -248,6 +246,8 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int32_t lx,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WLR_SCENE_NODE_BLUR:
|
||||||
|
break;
|
||||||
case WLR_SCENE_NODE_OPTIMIZED_BLUR:
|
case WLR_SCENE_NODE_OPTIMIZED_BLUR:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
void layer_actual_size(LayerSurface *l, int32_t *width, int32_t *height) {
|
void layer_actual_size(LayerSurface *l, int32_t *width, int32_t *height) {
|
||||||
struct wlr_box box;
|
|
||||||
|
|
||||||
if (l->animation.running) {
|
if (l->animation.running) {
|
||||||
*width = l->animation.current.width;
|
*width = l->animation.current.width;
|
||||||
*height = l->animation.current.height;
|
*height = l->animation.current.height;
|
||||||
} else {
|
} else {
|
||||||
get_layer_target_geometry(l, &box);
|
*width = l->geom.width;
|
||||||
*width = box.width;
|
*height = l->geom.height;
|
||||||
*height = box.height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,6 +149,34 @@ void set_layer_dir_animaiton(LayerSurface *l, struct wlr_box *geo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void layer_draw_shield(LayerSurface *l) {
|
||||||
|
int32_t width, height;
|
||||||
|
|
||||||
|
if (!l->mapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (active_capture_count > 0 && l->shield_when_capture) {
|
||||||
|
|
||||||
|
layer_actual_size(l, &width, &height);
|
||||||
|
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
wlr_scene_node_set_enabled(&l->shield->node, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_scene_node_raise_to_top(&l->shield->node);
|
||||||
|
wlr_scene_node_set_position(&l->shield->node, 0, 0);
|
||||||
|
wlr_scene_rect_set_size(l->shield, width, height);
|
||||||
|
wlr_scene_node_set_enabled(&l->shield->node, true);
|
||||||
|
} else {
|
||||||
|
if (l->shield->node.enabled) {
|
||||||
|
wlr_scene_node_lower_to_bottom(&l->shield->node);
|
||||||
|
wlr_scene_node_set_position(&l->shield->node, 0, 0);
|
||||||
|
wlr_scene_node_set_enabled(&l->shield->node, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void layer_draw_shadow(LayerSurface *l) {
|
void layer_draw_shadow(LayerSurface *l) {
|
||||||
|
|
||||||
if (!l->mapped || !l->shadow)
|
if (!l->mapped || !l->shadow)
|
||||||
|
|
@ -187,8 +213,7 @@ void layer_draw_shadow(LayerSurface *l) {
|
||||||
|
|
||||||
struct clipped_region clipped_region = {
|
struct clipped_region clipped_region = {
|
||||||
.area = intersection_box,
|
.area = intersection_box,
|
||||||
.corner_radius = config.border_radius,
|
.corners = corner_radii_all(config.border_radius),
|
||||||
.corners = config.border_radius_location_default,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
wlr_scene_node_set_position(&l->shadow->node, shadow_box.x, shadow_box.y);
|
wlr_scene_node_set_position(&l->shadow->node, shadow_box.x, shadow_box.y);
|
||||||
|
|
@ -328,9 +353,14 @@ void layer_animation_next_tick(LayerSurface *l) {
|
||||||
(1.0 - config.fadein_begin_opacity),
|
(1.0 - config.fadein_begin_opacity),
|
||||||
1.0f);
|
1.0f);
|
||||||
|
|
||||||
if (config.animation_fade_in)
|
if (config.animation_fade_in) {
|
||||||
|
if (config.blur && !l->noblur && !config.blur_optimized) {
|
||||||
|
wlr_scene_blur_set_strength(l->blur, opacity);
|
||||||
|
wlr_scene_blur_set_alpha(l->blur, opacity);
|
||||||
|
}
|
||||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||||
scene_buffer_apply_opacity, &opacity);
|
scene_buffer_apply_opacity, &opacity);
|
||||||
|
}
|
||||||
|
|
||||||
wlr_scene_node_set_position(&l->scene->node, x, y);
|
wlr_scene_node_set_position(&l->scene->node, x, y);
|
||||||
|
|
||||||
|
|
@ -358,6 +388,10 @@ void layer_animation_next_tick(LayerSurface *l) {
|
||||||
.height = height,
|
.height = height,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (config.blur && config.blur_layer && !l->noblur && l->blur)
|
||||||
|
wlr_scene_blur_set_size(l->blur, l->animation.current.width,
|
||||||
|
l->animation.current.height);
|
||||||
|
|
||||||
if (animation_passed >= 1.0) {
|
if (animation_passed >= 1.0) {
|
||||||
l->animation.running = false;
|
l->animation.running = false;
|
||||||
l->need_output_flush = false;
|
l->need_output_flush = false;
|
||||||
|
|
@ -374,6 +408,10 @@ void init_fadeout_layers(LayerSurface *l) {
|
||||||
if (!l->mon || !l->scene)
|
if (!l->mon || !l->scene)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (l->shield_when_capture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((l->animation_type_close &&
|
if ((l->animation_type_close &&
|
||||||
strcmp(l->animation_type_close, "none") == 0) ||
|
strcmp(l->animation_type_close, "none") == 0) ||
|
||||||
(!l->animation_type_close &&
|
(!l->animation_type_close &&
|
||||||
|
|
@ -567,8 +605,10 @@ bool layer_draw_frame(LayerSurface *l) {
|
||||||
if (config.animations && config.layer_animations && l->animation.running &&
|
if (config.animations && config.layer_animations && l->animation.running &&
|
||||||
!l->noanim) {
|
!l->noanim) {
|
||||||
layer_animation_next_tick(l);
|
layer_animation_next_tick(l);
|
||||||
|
layer_draw_shield(l);
|
||||||
layer_draw_shadow(l);
|
layer_draw_shadow(l);
|
||||||
} else {
|
} else {
|
||||||
|
layer_draw_shield(l);
|
||||||
layer_draw_shadow(l);
|
layer_draw_shadow(l);
|
||||||
l->need_output_flush = false;
|
l->need_output_flush = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,9 @@ void set_tagin_animation(Monitor *m, Client *c) {
|
||||||
|
|
||||||
void set_arrange_visible(Monitor *m, Client *c, bool want_animation) {
|
void set_arrange_visible(Monitor *m, Client *c, bool want_animation) {
|
||||||
|
|
||||||
if (!ISTILED(c) || ((!c->is_clip_to_hide || !is_scroller_layout(c->mon)) &&
|
if (!ISTILED(c) || (!c->is_clip_to_hide || !is_scroller_layout(c->mon))) {
|
||||||
(!c->is_monocle_hide || !is_monocle_layout(c->mon)))) {
|
|
||||||
c->is_clip_to_hide = false;
|
c->is_clip_to_hide = false;
|
||||||
c->is_monocle_hide = false;
|
c->is_logic_hide = false;
|
||||||
wlr_scene_node_set_enabled(&c->scene->node, true);
|
wlr_scene_node_set_enabled(&c->scene->node, true);
|
||||||
wlr_scene_node_set_enabled(&c->scene_surface->node, true);
|
wlr_scene_node_set_enabled(&c->scene_surface->node, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,4 +205,30 @@ void wl_list_swap(struct wl_list *l1, struct wl_list *l2) {
|
||||||
tmp2_prev->next = l1;
|
tmp2_prev->next = l1;
|
||||||
tmp2_next->prev = l1;
|
tmp2_next->prev = l1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wl_list_safe_reinsert_prev(struct wl_list *l1, struct wl_list *l2) {
|
||||||
|
if (!l1 || !l2)
|
||||||
|
return;
|
||||||
|
if (l1 == l2)
|
||||||
|
return;
|
||||||
|
if (l1->prev == l2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl_list_remove(l2);
|
||||||
|
wl_list_init(l2);
|
||||||
|
wl_list_insert(l1->prev, l2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wl_list_safe_reinsert_next(struct wl_list *l1, struct wl_list *l2) {
|
||||||
|
if (!l1 || !l2)
|
||||||
|
return;
|
||||||
|
if (l1 == l2)
|
||||||
|
return;
|
||||||
|
if (l1->next == l2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl_list_remove(l2);
|
||||||
|
wl_list_init(l2);
|
||||||
|
wl_list_insert(l1, l2);
|
||||||
}
|
}
|
||||||
|
|
@ -12,4 +12,6 @@ char *join_strings(char *arr[], const char *sep);
|
||||||
char *join_strings_with_suffix(char *arr[], const char *suffix,
|
char *join_strings_with_suffix(char *arr[], const char *suffix,
|
||||||
const char *sep);
|
const char *sep);
|
||||||
char *string_printf(const char *fmt, ...);
|
char *string_printf(const char *fmt, ...);
|
||||||
void wl_list_swap(struct wl_list *l1, struct wl_list *l2);
|
void wl_list_swap(struct wl_list *l1, struct wl_list *l2);
|
||||||
|
void wl_list_safe_reinsert_prev(struct wl_list *l1, struct wl_list *l2);
|
||||||
|
void wl_list_safe_reinsert_next(struct wl_list *l1, struct wl_list *l2);
|
||||||
|
|
@ -22,6 +22,11 @@ enum { NUM_TYPE_MINUS, NUM_TYPE_PLUS, NUM_TYPE_DEFAULT };
|
||||||
|
|
||||||
enum { KEY_TYPE_CODE, KEY_TYPE_SYM };
|
enum { KEY_TYPE_CODE, KEY_TYPE_SYM };
|
||||||
|
|
||||||
|
enum render_bit_depth {
|
||||||
|
MANGO_RENDER_BIT_DEPTH_DEFAULT = 0,
|
||||||
|
MANGO_RENDER_BIT_DEPTH_8,
|
||||||
|
MANGO_RENDER_BIT_DEPTH_10,
|
||||||
|
};
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t keycode1;
|
uint32_t keycode1;
|
||||||
uint32_t keycode2;
|
uint32_t keycode2;
|
||||||
|
|
@ -74,11 +79,13 @@ typedef struct {
|
||||||
int32_t isunglobal;
|
int32_t isunglobal;
|
||||||
int32_t isglobal;
|
int32_t isglobal;
|
||||||
int32_t isoverlay;
|
int32_t isoverlay;
|
||||||
|
int32_t shield_when_capture;
|
||||||
int32_t allow_shortcuts_inhibit;
|
int32_t allow_shortcuts_inhibit;
|
||||||
int32_t ignore_maximize;
|
int32_t ignore_maximize;
|
||||||
int32_t ignore_minimize;
|
int32_t ignore_minimize;
|
||||||
int32_t isnosizehint;
|
int32_t isnosizehint;
|
||||||
int32_t idleinhibit_when_focus;
|
int32_t idleinhibit_when_focus;
|
||||||
|
int32_t vrr_only_fullscreen;
|
||||||
char *monitor;
|
char *monitor;
|
||||||
int32_t offsetx;
|
int32_t offsetx;
|
||||||
int32_t offsety;
|
int32_t offsety;
|
||||||
|
|
@ -113,6 +120,8 @@ typedef struct {
|
||||||
float refresh; // Refresh rate
|
float refresh; // Refresh rate
|
||||||
int32_t vrr; // variable refresh rate
|
int32_t vrr; // variable refresh rate
|
||||||
int32_t custom; // enable custom mode
|
int32_t custom; // enable custom mode
|
||||||
|
int32_t hdr; // enable hdr mode
|
||||||
|
int32_t disable; // prefer disable
|
||||||
} ConfigMonitorRule;
|
} ConfigMonitorRule;
|
||||||
|
|
||||||
// 修改后的宏定义
|
// 修改后的宏定义
|
||||||
|
|
@ -179,6 +188,7 @@ typedef struct {
|
||||||
char *layer_name; // 布局名称
|
char *layer_name; // 布局名称
|
||||||
char *animation_type_open;
|
char *animation_type_open;
|
||||||
char *animation_type_close;
|
char *animation_type_close;
|
||||||
|
int32_t shield_when_capture;
|
||||||
int32_t noblur;
|
int32_t noblur;
|
||||||
int32_t noanim;
|
int32_t noanim;
|
||||||
int32_t noshadow;
|
int32_t noshadow;
|
||||||
|
|
@ -332,7 +342,7 @@ typedef struct {
|
||||||
uint32_t gappoh;
|
uint32_t gappoh;
|
||||||
uint32_t gappov;
|
uint32_t gappov;
|
||||||
uint32_t borderpx;
|
uint32_t borderpx;
|
||||||
uint32_t tab_bar_height;
|
uint32_t group_bar_height;
|
||||||
float scratchpad_width_ratio;
|
float scratchpad_width_ratio;
|
||||||
float scratchpad_height_ratio;
|
float scratchpad_height_ratio;
|
||||||
float rootcolor[4];
|
float rootcolor[4];
|
||||||
|
|
@ -410,7 +420,9 @@ typedef struct {
|
||||||
struct xkb_context *ctx;
|
struct xkb_context *ctx;
|
||||||
struct xkb_keymap *keymap;
|
struct xkb_keymap *keymap;
|
||||||
DecorateDrawData jumplabeldata;
|
DecorateDrawData jumplabeldata;
|
||||||
DecorateDrawData tabdata;
|
DecorateDrawData groupbardata;
|
||||||
|
|
||||||
|
int32_t hdr_depth;
|
||||||
} Config;
|
} Config;
|
||||||
|
|
||||||
typedef int32_t (*FuncType)(const Arg *);
|
typedef int32_t (*FuncType)(const Arg *);
|
||||||
|
|
@ -418,7 +430,7 @@ Config config;
|
||||||
|
|
||||||
bool parse_config_file(Config *config, const char *file_path, bool must_exist);
|
bool parse_config_file(Config *config, const char *file_path, bool must_exist);
|
||||||
bool apply_rule_to_state(Monitor *m, const ConfigMonitorRule *rule,
|
bool apply_rule_to_state(Monitor *m, const ConfigMonitorRule *rule,
|
||||||
struct wlr_output_state *state, int vrr, int custom);
|
struct wlr_output_state *state);
|
||||||
bool monitor_matches_rule(Monitor *m, const ConfigMonitorRule *rule);
|
bool monitor_matches_rule(Monitor *m, const ConfigMonitorRule *rule);
|
||||||
|
|
||||||
// Helper function to trim whitespace from start and end of a string
|
// Helper function to trim whitespace from start and end of a string
|
||||||
|
|
@ -1010,9 +1022,17 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
||||||
if (strcmp(func_name, "focusstack") == 0) {
|
if (strcmp(func_name, "focusstack") == 0) {
|
||||||
func = focusstack;
|
func = focusstack;
|
||||||
(*arg).i = parse_circle_direction(arg_value);
|
(*arg).i = parse_circle_direction(arg_value);
|
||||||
|
} else if (strcmp(func_name, "groupfocus") == 0) {
|
||||||
|
func = groupfocus;
|
||||||
|
(*arg).i = parse_circle_direction(arg_value);
|
||||||
} else if (strcmp(func_name, "focusdir") == 0) {
|
} else if (strcmp(func_name, "focusdir") == 0) {
|
||||||
func = focusdir;
|
func = focusdir;
|
||||||
(*arg).i = parse_direction(arg_value);
|
(*arg).i = parse_direction(arg_value);
|
||||||
|
} else if (strcmp(func_name, "groupjoin") == 0) {
|
||||||
|
func = groupjoin;
|
||||||
|
(*arg).i = parse_direction(arg_value);
|
||||||
|
} else if (strcmp(func_name, "groupleave") == 0) {
|
||||||
|
func = groupleave;
|
||||||
} else if (strcmp(func_name, "focusid") == 0) {
|
} else if (strcmp(func_name, "focusid") == 0) {
|
||||||
func = focusid;
|
func = focusid;
|
||||||
} else if (strcmp(func_name, "incnmaster") == 0) {
|
} else if (strcmp(func_name, "incnmaster") == 0) {
|
||||||
|
|
@ -1277,6 +1297,15 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
||||||
} else if (strcmp(func_name, "toggle_monitor") == 0) {
|
} else if (strcmp(func_name, "toggle_monitor") == 0) {
|
||||||
func = toggle_monitor;
|
func = toggle_monitor;
|
||||||
(*arg).v = strdup(arg_value);
|
(*arg).v = strdup(arg_value);
|
||||||
|
} else if (strcmp(func_name, "sleep_monitor") == 0) {
|
||||||
|
func = sleep_monitor;
|
||||||
|
(*arg).v = strdup(arg_value);
|
||||||
|
} else if (strcmp(func_name, "wakeup_monitor") == 0) {
|
||||||
|
func = wakeup_monitor;
|
||||||
|
(*arg).v = strdup(arg_value);
|
||||||
|
} else if (strcmp(func_name, "sleep_toggle_monitor") == 0) {
|
||||||
|
func = sleep_toggle_monitor;
|
||||||
|
(*arg).v = strdup(arg_value);
|
||||||
} else if (strcmp(func_name, "scroller_stack") == 0) {
|
} else if (strcmp(func_name, "scroller_stack") == 0) {
|
||||||
func = scroller_stack;
|
func = scroller_stack;
|
||||||
(*arg).i = parse_direction(arg_value);
|
(*arg).i = parse_direction(arg_value);
|
||||||
|
|
@ -1510,6 +1539,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->drag_floating_refresh_interval = atof(value);
|
config->drag_floating_refresh_interval = atof(value);
|
||||||
} else if (strcmp(key, "allow_tearing") == 0) {
|
} else if (strcmp(key, "allow_tearing") == 0) {
|
||||||
config->allow_tearing = atoi(value);
|
config->allow_tearing = atoi(value);
|
||||||
|
} else if (strcmp(key, "hdr_depth") == 0) {
|
||||||
|
config->hdr_depth = atoi(value);
|
||||||
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
||||||
config->allow_shortcuts_inhibit = atoi(value);
|
config->allow_shortcuts_inhibit = atoi(value);
|
||||||
} else if (strcmp(key, "allow_lock_transparent") == 0) {
|
} else if (strcmp(key, "allow_lock_transparent") == 0) {
|
||||||
|
|
@ -1765,76 +1796,76 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->cursor_size = atoi(value);
|
config->cursor_size = atoi(value);
|
||||||
} else if (strcmp(key, "cursor_theme") == 0) {
|
} else if (strcmp(key, "cursor_theme") == 0) {
|
||||||
config->cursor_theme = strdup(value);
|
config->cursor_theme = strdup(value);
|
||||||
} else if (strcmp(key, "tab_bar_decorate_font_desc") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_font_desc") == 0) {
|
||||||
config->tabdata.font_desc = strdup(value);
|
config->groupbardata.font_desc = strdup(value);
|
||||||
} else if (strcmp(key, "tab_bar_decorate_fg_color") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_fg_color") == 0) {
|
||||||
int64_t color = parse_color(value);
|
int64_t color = parse_color(value);
|
||||||
if (color == -1) {
|
if (color == -1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||||
"tab_bar_decorate_fg_color "
|
"group_bar_decorate_fg_color "
|
||||||
"format: %s\n",
|
"format: %s\n",
|
||||||
value);
|
value);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
convert_hex_to_rgba(config->tabdata.fg_color, color);
|
convert_hex_to_rgba(config->groupbardata.fg_color, color);
|
||||||
}
|
}
|
||||||
} else if (strcmp(key, "tab_bar_decorate_bg_color") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_bg_color") == 0) {
|
||||||
int64_t color = parse_color(value);
|
int64_t color = parse_color(value);
|
||||||
if (color == -1) {
|
if (color == -1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||||
"tab_bar_decorate_bg_color "
|
"group_bar_decorate_bg_color "
|
||||||
"format: %s\n",
|
"format: %s\n",
|
||||||
value);
|
value);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
convert_hex_to_rgba(config->tabdata.bg_color, color);
|
convert_hex_to_rgba(config->groupbardata.bg_color, color);
|
||||||
}
|
}
|
||||||
} else if (strcmp(key, "tab_bar_decorate_focus_fg_color") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_focus_fg_color") == 0) {
|
||||||
int64_t color = parse_color(value);
|
int64_t color = parse_color(value);
|
||||||
if (color == -1) {
|
if (color == -1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||||
"tab_bar_decorate_focus_fg_color "
|
"group_bar_decorate_focus_fg_color "
|
||||||
"format: %s\n",
|
"format: %s\n",
|
||||||
value);
|
value);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
convert_hex_to_rgba(config->tabdata.focus_fg_color, color);
|
convert_hex_to_rgba(config->groupbardata.focus_fg_color, color);
|
||||||
}
|
}
|
||||||
} else if (strcmp(key, "tab_bar_decorate_focus_bg_color") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_focus_bg_color") == 0) {
|
||||||
int64_t color = parse_color(value);
|
int64_t color = parse_color(value);
|
||||||
if (color == -1) {
|
if (color == -1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||||
"tab_bar_decorate_focus_bg_color "
|
"group_bar_decorate_focus_bg_color "
|
||||||
"format: %s\n",
|
"format: %s\n",
|
||||||
value);
|
value);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
convert_hex_to_rgba(config->tabdata.focus_bg_color, color);
|
convert_hex_to_rgba(config->groupbardata.focus_bg_color, color);
|
||||||
}
|
}
|
||||||
} else if (strcmp(key, "tab_bar_decorate_border_color") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_border_color") == 0) {
|
||||||
int64_t color = parse_color(value);
|
int64_t color = parse_color(value);
|
||||||
if (color == -1) {
|
if (color == -1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
"\033[1m\033[31m[ERROR]:\033[33m Invalid "
|
||||||
"tab_bar_decorate_border_color "
|
"group_bar_decorate_border_color "
|
||||||
"format: %s\n",
|
"format: %s\n",
|
||||||
value);
|
value);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
convert_hex_to_rgba(config->tabdata.border_color, color);
|
convert_hex_to_rgba(config->groupbardata.border_color, color);
|
||||||
}
|
}
|
||||||
} else if (strcmp(key, "tab_bar_decorate_border_width") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_border_width") == 0) {
|
||||||
config->tabdata.border_width = CLAMP_INT(atoi(value), 0, 100);
|
config->groupbardata.border_width = CLAMP_INT(atoi(value), 0, 100);
|
||||||
} else if (strcmp(key, "tab_bar_decorate_corner_radius") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_corner_radius") == 0) {
|
||||||
config->tabdata.corner_radius = CLAMP_INT(atoi(value), 0, 100);
|
config->groupbardata.corner_radius = CLAMP_INT(atoi(value), 0, 100);
|
||||||
} else if (strcmp(key, "tab_bar_decorate_padding_x") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_padding_x") == 0) {
|
||||||
config->tabdata.padding_x = CLAMP_INT(atoi(value), 0, 100);
|
config->groupbardata.padding_x = CLAMP_INT(atoi(value), 0, 100);
|
||||||
} else if (strcmp(key, "tab_bar_decorate_padding_y") == 0) {
|
} else if (strcmp(key, "group_bar_decorate_padding_y") == 0) {
|
||||||
config->tabdata.padding_y = CLAMP_INT(atoi(value), 0, 100);
|
config->groupbardata.padding_y = CLAMP_INT(atoi(value), 0, 100);
|
||||||
} else if (strcmp(key, "jump_label_decorate_font_desc") == 0) {
|
} else if (strcmp(key, "jump_label_decorate_font_desc") == 0) {
|
||||||
config->jumplabeldata.font_desc = strdup(value);
|
config->jumplabeldata.font_desc = strdup(value);
|
||||||
} else if (strcmp(key, "jump_label_decorate_fg_color") == 0) {
|
} else if (strcmp(key, "jump_label_decorate_fg_color") == 0) {
|
||||||
|
|
@ -1951,8 +1982,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->scratchpad_height_ratio = atof(value);
|
config->scratchpad_height_ratio = atof(value);
|
||||||
} else if (strcmp(key, "borderpx") == 0) {
|
} else if (strcmp(key, "borderpx") == 0) {
|
||||||
config->borderpx = atoi(value);
|
config->borderpx = atoi(value);
|
||||||
} else if (strcmp(key, "tab_bar_height") == 0) {
|
} else if (strcmp(key, "group_bar_height") == 0) {
|
||||||
config->tab_bar_height = atoi(value);
|
config->group_bar_height = atoi(value);
|
||||||
} else if (strcmp(key, "rootcolor") == 0) {
|
} else if (strcmp(key, "rootcolor") == 0) {
|
||||||
int64_t color = parse_color(value);
|
int64_t color = parse_color(value);
|
||||||
if (color == -1) {
|
if (color == -1) {
|
||||||
|
|
@ -2106,7 +2137,9 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->height = -1;
|
rule->height = -1;
|
||||||
rule->refresh = 0.0f;
|
rule->refresh = 0.0f;
|
||||||
rule->vrr = 0;
|
rule->vrr = 0;
|
||||||
|
rule->hdr = 0;
|
||||||
rule->custom = 0;
|
rule->custom = 0;
|
||||||
|
rule->disable = 0;
|
||||||
|
|
||||||
bool parse_error = false;
|
bool parse_error = false;
|
||||||
char *token = strtok(value, ",");
|
char *token = strtok(value, ",");
|
||||||
|
|
@ -2144,6 +2177,10 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->refresh = CLAMP_FLOAT(atof(val), 0.001f, 1000.0f);
|
rule->refresh = CLAMP_FLOAT(atof(val), 0.001f, 1000.0f);
|
||||||
} else if (strcmp(key, "vrr") == 0) {
|
} else if (strcmp(key, "vrr") == 0) {
|
||||||
rule->vrr = CLAMP_INT(atoi(val), 0, 1);
|
rule->vrr = CLAMP_INT(atoi(val), 0, 1);
|
||||||
|
} else if (strcmp(key, "hdr") == 0) {
|
||||||
|
rule->hdr = CLAMP_INT(atoi(val), 0, 1);
|
||||||
|
} else if (strcmp(key, "disable") == 0) {
|
||||||
|
rule->disable = CLAMP_INT(atoi(val), 0, 1);
|
||||||
} else if (strcmp(key, "custom") == 0) {
|
} else if (strcmp(key, "custom") == 0) {
|
||||||
rule->custom = CLAMP_INT(atoi(val), 0, 1);
|
rule->custom = CLAMP_INT(atoi(val), 0, 1);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2274,6 +2311,7 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->layer_name = NULL;
|
rule->layer_name = NULL;
|
||||||
rule->animation_type_open = NULL;
|
rule->animation_type_open = NULL;
|
||||||
rule->animation_type_close = NULL;
|
rule->animation_type_close = NULL;
|
||||||
|
rule->shield_when_capture = 0;
|
||||||
rule->noblur = 0;
|
rule->noblur = 0;
|
||||||
rule->noanim = 0;
|
rule->noanim = 0;
|
||||||
rule->noshadow = 0;
|
rule->noshadow = 0;
|
||||||
|
|
@ -2296,6 +2334,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->animation_type_open = strdup(val);
|
rule->animation_type_open = strdup(val);
|
||||||
} else if (strcmp(key, "animation_type_close") == 0) {
|
} else if (strcmp(key, "animation_type_close") == 0) {
|
||||||
rule->animation_type_close = strdup(val);
|
rule->animation_type_close = strdup(val);
|
||||||
|
} else if (strcmp(key, "shield_when_capture") == 0) {
|
||||||
|
rule->shield_when_capture = CLAMP_INT(atoi(val), 0, 1);
|
||||||
} else if (strcmp(key, "noblur") == 0) {
|
} else if (strcmp(key, "noblur") == 0) {
|
||||||
rule->noblur = CLAMP_INT(atoi(val), 0, 1);
|
rule->noblur = CLAMP_INT(atoi(val), 0, 1);
|
||||||
} else if (strcmp(key, "noanim") == 0) {
|
} else if (strcmp(key, "noanim") == 0) {
|
||||||
|
|
@ -2349,11 +2389,13 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->isunglobal = -1;
|
rule->isunglobal = -1;
|
||||||
rule->isglobal = -1;
|
rule->isglobal = -1;
|
||||||
rule->isoverlay = -1;
|
rule->isoverlay = -1;
|
||||||
|
rule->shield_when_capture = -1;
|
||||||
rule->allow_shortcuts_inhibit = -1;
|
rule->allow_shortcuts_inhibit = -1;
|
||||||
rule->ignore_maximize = -1;
|
rule->ignore_maximize = -1;
|
||||||
rule->ignore_minimize = -1;
|
rule->ignore_minimize = -1;
|
||||||
rule->isnosizehint = -1;
|
rule->isnosizehint = -1;
|
||||||
rule->idleinhibit_when_focus = -1;
|
rule->idleinhibit_when_focus = -1;
|
||||||
|
rule->vrr_only_fullscreen = -1;
|
||||||
rule->isterm = -1;
|
rule->isterm = -1;
|
||||||
rule->allow_csd = -1;
|
rule->allow_csd = -1;
|
||||||
rule->force_fakemaximize = -1;
|
rule->force_fakemaximize = -1;
|
||||||
|
|
@ -2456,6 +2498,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->focused_opacity = atof(val);
|
rule->focused_opacity = atof(val);
|
||||||
} else if (strcmp(key, "isoverlay") == 0) {
|
} else if (strcmp(key, "isoverlay") == 0) {
|
||||||
rule->isoverlay = atoi(val);
|
rule->isoverlay = atoi(val);
|
||||||
|
} else if (strcmp(key, "shield_when_capture") == 0) {
|
||||||
|
rule->shield_when_capture = atoi(val);
|
||||||
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
||||||
rule->allow_shortcuts_inhibit = atoi(val);
|
rule->allow_shortcuts_inhibit = atoi(val);
|
||||||
} else if (strcmp(key, "ignore_maximize") == 0) {
|
} else if (strcmp(key, "ignore_maximize") == 0) {
|
||||||
|
|
@ -2466,6 +2510,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->isnosizehint = atoi(val);
|
rule->isnosizehint = atoi(val);
|
||||||
} else if (strcmp(key, "idleinhibit_when_focus") == 0) {
|
} else if (strcmp(key, "idleinhibit_when_focus") == 0) {
|
||||||
rule->idleinhibit_when_focus = atoi(val);
|
rule->idleinhibit_when_focus = atoi(val);
|
||||||
|
} else if (strcmp(key, "vrr_only_fullscreen") == 0) {
|
||||||
|
rule->vrr_only_fullscreen = atoi(val);
|
||||||
} else if (strcmp(key, "isterm") == 0) {
|
} else if (strcmp(key, "isterm") == 0) {
|
||||||
rule->isterm = atoi(val);
|
rule->isterm = atoi(val);
|
||||||
} else if (strcmp(key, "allow_csd") == 0) {
|
} else if (strcmp(key, "allow_csd") == 0) {
|
||||||
|
|
@ -3401,9 +3447,9 @@ void free_config(void) {
|
||||||
config.jumplabeldata.font_desc = NULL;
|
config.jumplabeldata.font_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.tabdata.font_desc) {
|
if (config.groupbardata.font_desc) {
|
||||||
free((void *)config.tabdata.font_desc);
|
free((void *)config.groupbardata.font_desc);
|
||||||
config.tabdata.font_desc = NULL;
|
config.groupbardata.font_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.tablet_map_to_mon) {
|
if (config.tablet_map_to_mon) {
|
||||||
|
|
@ -3496,6 +3542,7 @@ void override_config(void) {
|
||||||
config.drag_tile_to_tile = CLAMP_INT(config.drag_tile_to_tile, 0, 1);
|
config.drag_tile_to_tile = CLAMP_INT(config.drag_tile_to_tile, 0, 1);
|
||||||
config.drag_tile_small = CLAMP_INT(config.drag_tile_small, 0, 1);
|
config.drag_tile_small = CLAMP_INT(config.drag_tile_small, 0, 1);
|
||||||
config.allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2);
|
config.allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2);
|
||||||
|
config.hdr_depth = CLAMP_INT(config.hdr_depth, 0, 2);
|
||||||
config.allow_shortcuts_inhibit =
|
config.allow_shortcuts_inhibit =
|
||||||
CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1);
|
CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1);
|
||||||
config.allow_lock_transparent =
|
config.allow_lock_transparent =
|
||||||
|
|
@ -3569,7 +3616,7 @@ void override_config(void) {
|
||||||
config.scratchpad_height_ratio =
|
config.scratchpad_height_ratio =
|
||||||
CLAMP_FLOAT(config.scratchpad_height_ratio, 0.1f, 1.0f);
|
CLAMP_FLOAT(config.scratchpad_height_ratio, 0.1f, 1.0f);
|
||||||
config.borderpx = CLAMP_INT(config.borderpx, 0, 200);
|
config.borderpx = CLAMP_INT(config.borderpx, 0, 200);
|
||||||
config.tab_bar_height = CLAMP_INT(config.tab_bar_height, 0, 500);
|
config.group_bar_height = CLAMP_INT(config.group_bar_height, 0, 500);
|
||||||
config.smartgaps = CLAMP_INT(config.smartgaps, 0, 1);
|
config.smartgaps = CLAMP_INT(config.smartgaps, 0, 1);
|
||||||
config.blur = CLAMP_INT(config.blur, 0, 1);
|
config.blur = CLAMP_INT(config.blur, 0, 1);
|
||||||
config.blur_layer = CLAMP_INT(config.blur_layer, 0, 1);
|
config.blur_layer = CLAMP_INT(config.blur_layer, 0, 1);
|
||||||
|
|
@ -3598,12 +3645,14 @@ void override_config(void) {
|
||||||
config.unfocused_opacity =
|
config.unfocused_opacity =
|
||||||
CLAMP_FLOAT(config.unfocused_opacity, 0.0f, 1.0f);
|
CLAMP_FLOAT(config.unfocused_opacity, 0.0f, 1.0f);
|
||||||
|
|
||||||
config.tabdata.border_width =
|
config.groupbardata.border_width =
|
||||||
CLAMP_INT(config.tabdata.border_width, 0, 100);
|
CLAMP_INT(config.groupbardata.border_width, 0, 100);
|
||||||
config.tabdata.corner_radius =
|
config.groupbardata.corner_radius =
|
||||||
CLAMP_INT(config.tabdata.corner_radius, 0, 100);
|
CLAMP_INT(config.groupbardata.corner_radius, 0, 100);
|
||||||
config.tabdata.padding_x = CLAMP_INT(config.tabdata.padding_x, 0, 100);
|
config.groupbardata.padding_x =
|
||||||
config.tabdata.padding_y = CLAMP_INT(config.tabdata.padding_y, 0, 100);
|
CLAMP_INT(config.groupbardata.padding_x, 0, 100);
|
||||||
|
config.groupbardata.padding_y =
|
||||||
|
CLAMP_INT(config.groupbardata.padding_y, 0, 100);
|
||||||
|
|
||||||
config.jumplabeldata.border_width =
|
config.jumplabeldata.border_width =
|
||||||
CLAMP_INT(config.jumplabeldata.border_width, 0, 100);
|
CLAMP_INT(config.jumplabeldata.border_width, 0, 100);
|
||||||
|
|
@ -3683,11 +3732,12 @@ void set_value_default() {
|
||||||
config.view_current_to_back = 0;
|
config.view_current_to_back = 0;
|
||||||
config.single_scratchpad = 1;
|
config.single_scratchpad = 1;
|
||||||
config.xwayland_persistence = 1;
|
config.xwayland_persistence = 1;
|
||||||
config.syncobj_enable = 0;
|
config.syncobj_enable = 1;
|
||||||
config.tag_carousel = 0;
|
config.tag_carousel = 0;
|
||||||
config.drag_tile_refresh_interval = 8.0f;
|
config.drag_tile_refresh_interval = 8.0f;
|
||||||
config.drag_floating_refresh_interval = 8.0f;
|
config.drag_floating_refresh_interval = 8.0f;
|
||||||
config.allow_tearing = TEARING_DISABLED;
|
config.allow_tearing = TEARING_DISABLED;
|
||||||
|
config.hdr_depth = MANGO_RENDER_BIT_DEPTH_10;
|
||||||
config.allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
config.allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
||||||
config.allow_lock_transparent = 0;
|
config.allow_lock_transparent = 0;
|
||||||
config.no_border_when_single = 0;
|
config.no_border_when_single = 0;
|
||||||
|
|
@ -3701,7 +3751,7 @@ void set_value_default() {
|
||||||
config.idleinhibit_ignore_visible = 0;
|
config.idleinhibit_ignore_visible = 0;
|
||||||
|
|
||||||
config.borderpx = 4;
|
config.borderpx = 4;
|
||||||
config.tab_bar_height = 50;
|
config.group_bar_height = 50;
|
||||||
config.overviewgappi = 5;
|
config.overviewgappi = 5;
|
||||||
config.overviewgappo = 30;
|
config.overviewgappo = 30;
|
||||||
config.cursor_hide_timeout = 0;
|
config.cursor_hide_timeout = 0;
|
||||||
|
|
@ -3738,7 +3788,6 @@ void set_value_default() {
|
||||||
config.blur_layer = 0;
|
config.blur_layer = 0;
|
||||||
config.blur_optimized = 1;
|
config.blur_optimized = 1;
|
||||||
config.border_radius = 0;
|
config.border_radius = 0;
|
||||||
config.border_radius_location_default = CORNER_LOCATION_ALL;
|
|
||||||
config.blur_params.num_passes = 1;
|
config.blur_params.num_passes = 1;
|
||||||
config.blur_params.radius = 5;
|
config.blur_params.radius = 5;
|
||||||
config.blur_params.noise = 0.02f;
|
config.blur_params.noise = 0.02f;
|
||||||
|
|
@ -3789,30 +3838,30 @@ void set_value_default() {
|
||||||
config.animation_curve_opafadeout[2] = 0.5;
|
config.animation_curve_opafadeout[2] = 0.5;
|
||||||
config.animation_curve_opafadeout[3] = 0.5;
|
config.animation_curve_opafadeout[3] = 0.5;
|
||||||
|
|
||||||
config.tabdata.fg_color[0] = 0xc4 / 255.0f;
|
config.groupbardata.fg_color[0] = 0xc4 / 255.0f;
|
||||||
config.tabdata.fg_color[1] = 0x93 / 255.0f;
|
config.groupbardata.fg_color[1] = 0x93 / 255.0f;
|
||||||
config.tabdata.fg_color[2] = 0x9d / 255.0f;
|
config.groupbardata.fg_color[2] = 0x9d / 255.0f;
|
||||||
config.tabdata.fg_color[3] = 1.0f;
|
config.groupbardata.fg_color[3] = 1.0f;
|
||||||
config.tabdata.bg_color[0] = 0x32 / 255.0f;
|
config.groupbardata.bg_color[0] = 0x32 / 255.0f;
|
||||||
config.tabdata.bg_color[1] = 0x32 / 255.0f;
|
config.groupbardata.bg_color[1] = 0x32 / 255.0f;
|
||||||
config.tabdata.bg_color[2] = 0x32 / 255.0f;
|
config.groupbardata.bg_color[2] = 0x32 / 255.0f;
|
||||||
config.tabdata.bg_color[3] = 1.0f;
|
config.groupbardata.bg_color[3] = 1.0f;
|
||||||
config.tabdata.focus_fg_color[0] = 0xed / 255.0f;
|
config.groupbardata.focus_fg_color[0] = 0xed / 255.0f;
|
||||||
config.tabdata.focus_fg_color[1] = 0xa6 / 255.0f;
|
config.groupbardata.focus_fg_color[1] = 0xa6 / 255.0f;
|
||||||
config.tabdata.focus_fg_color[2] = 0xb4 / 255.0f;
|
config.groupbardata.focus_fg_color[2] = 0xb4 / 255.0f;
|
||||||
config.tabdata.focus_fg_color[3] = 1.0f;
|
config.groupbardata.focus_fg_color[3] = 1.0f;
|
||||||
config.tabdata.focus_bg_color[0] = 0x4e / 255.0f;
|
config.groupbardata.focus_bg_color[0] = 0x4e / 255.0f;
|
||||||
config.tabdata.focus_bg_color[1] = 0x45 / 255.0f;
|
config.groupbardata.focus_bg_color[1] = 0x45 / 255.0f;
|
||||||
config.tabdata.focus_bg_color[2] = 0x3c / 255.0f;
|
config.groupbardata.focus_bg_color[2] = 0x3c / 255.0f;
|
||||||
config.tabdata.focus_bg_color[3] = 1.0f;
|
config.groupbardata.focus_bg_color[3] = 1.0f;
|
||||||
config.tabdata.border_color[0] = 0x8b / 255.0f;
|
config.groupbardata.border_color[0] = 0x8b / 255.0f;
|
||||||
config.tabdata.border_color[1] = 0xaa / 255.0f;
|
config.groupbardata.border_color[1] = 0xaa / 255.0f;
|
||||||
config.tabdata.border_color[2] = 0x9b / 255.0f;
|
config.groupbardata.border_color[2] = 0x9b / 255.0f;
|
||||||
config.tabdata.border_color[3] = 1.0f;
|
config.groupbardata.border_color[3] = 1.0f;
|
||||||
config.tabdata.border_width = 4;
|
config.groupbardata.border_width = 4;
|
||||||
config.tabdata.corner_radius = 5;
|
config.groupbardata.corner_radius = 5;
|
||||||
config.tabdata.padding_x = 0;
|
config.groupbardata.padding_x = 0;
|
||||||
config.tabdata.padding_y = 0;
|
config.groupbardata.padding_y = 0;
|
||||||
|
|
||||||
config.jumplabeldata.fg_color[0] = 0xc4 / 255.0f;
|
config.jumplabeldata.fg_color[0] = 0xc4 / 255.0f;
|
||||||
config.jumplabeldata.fg_color[1] = 0x93 / 255.0f;
|
config.jumplabeldata.fg_color[1] = 0x93 / 255.0f;
|
||||||
|
|
@ -3952,7 +4001,7 @@ bool parse_config(void) {
|
||||||
config.tag_rules_count = 0;
|
config.tag_rules_count = 0;
|
||||||
config.cursor_theme = NULL;
|
config.cursor_theme = NULL;
|
||||||
config.jumplabeldata.font_desc = NULL;
|
config.jumplabeldata.font_desc = NULL;
|
||||||
config.tabdata.font_desc = NULL;
|
config.groupbardata.font_desc = NULL;
|
||||||
config.tablet_map_to_mon = NULL;
|
config.tablet_map_to_mon = NULL;
|
||||||
strcpy(config.keymode, "default");
|
strcpy(config.keymode, "default");
|
||||||
|
|
||||||
|
|
@ -4017,16 +4066,13 @@ void reset_blur_params(void) {
|
||||||
void reapply_monitor_rules(void) {
|
void reapply_monitor_rules(void) {
|
||||||
ConfigMonitorRule *mr;
|
ConfigMonitorRule *mr;
|
||||||
Monitor *m = NULL;
|
Monitor *m = NULL;
|
||||||
int32_t ji, vrr, custom;
|
int32_t ji;
|
||||||
int32_t mx, my;
|
int32_t mx, my;
|
||||||
struct wlr_output_state state;
|
|
||||||
|
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (!m->wlr_output->enabled)
|
if (!m->wlr_output->enabled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wlr_output_state_init(&state);
|
|
||||||
|
|
||||||
for (ji = 0; ji < config.monitor_rules_count; ji++) {
|
for (ji = 0; ji < config.monitor_rules_count; ji++) {
|
||||||
if (config.monitor_rules_count < 1)
|
if (config.monitor_rules_count < 1)
|
||||||
break;
|
break;
|
||||||
|
|
@ -4036,18 +4082,33 @@ void reapply_monitor_rules(void) {
|
||||||
if (monitor_matches_rule(m, mr)) {
|
if (monitor_matches_rule(m, mr)) {
|
||||||
mx = mr->x == INT32_MAX ? m->m.x : mr->x;
|
mx = mr->x == INT32_MAX ? m->m.x : mr->x;
|
||||||
my = mr->y == INT32_MAX ? m->m.y : mr->y;
|
my = mr->y == INT32_MAX ? m->m.y : mr->y;
|
||||||
vrr = mr->vrr >= 0 ? mr->vrr : 0;
|
|
||||||
custom = mr->custom >= 0 ? mr->custom : 0;
|
|
||||||
|
|
||||||
(void)apply_rule_to_state(m, mr, &state, vrr, custom);
|
apply_rule_to_state(m, mr, &m->pending);
|
||||||
|
|
||||||
wlr_output_layout_add(output_layout, m->wlr_output, mx, my);
|
wlr_output_layout_add(output_layout, m->wlr_output, mx, my);
|
||||||
wlr_output_commit_state(m->wlr_output, &state);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_state_finish(&state);
|
if (m->prefer_disable) {
|
||||||
|
wlr_output_state_set_enabled(&m->pending, false);
|
||||||
|
} else {
|
||||||
|
wlr_output_state_set_enabled(&m->pending, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->hdr_enable) {
|
||||||
|
output_state_setup_hdr(m, false, &m->pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(mango_scene_output_commit(m->scene_output, &m->pending))) {
|
||||||
|
if (m->hdr_enable) {
|
||||||
|
output_state_setup_hdr(m, true, &m->pending);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wlr_output_effective_resolution(m->wlr_output, &m->m.width,
|
||||||
|
&m->m.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatemons(NULL, NULL);
|
updatemons(NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4116,14 +4177,7 @@ void reapply_property(void) {
|
||||||
if (!c->isnoborder && !c->isfullscreen) {
|
if (!c->isnoborder && !c->isfullscreen) {
|
||||||
c->bw = config.borderpx;
|
c->bw = config.borderpx;
|
||||||
}
|
}
|
||||||
|
client_set_group_config(c);
|
||||||
mango_jump_label_node_apply_config(c->jump_label_node,
|
|
||||||
&config.jumplabeldata);
|
|
||||||
mango_tab_bar_node_apply_config(c->tab_bar_node, &config.tabdata);
|
|
||||||
|
|
||||||
wlr_scene_rect_set_color(c->droparea, config.dropcolor);
|
|
||||||
wlr_scene_rect_set_color(c->splitindicator[0], config.splitcolor);
|
|
||||||
wlr_scene_rect_set_color(c->splitindicator[1], config.splitcolor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ int32_t minimized(const Arg *arg);
|
||||||
int32_t restore_minimized(const Arg *arg);
|
int32_t restore_minimized(const Arg *arg);
|
||||||
int32_t toggle_scratchpad(const Arg *arg);
|
int32_t toggle_scratchpad(const Arg *arg);
|
||||||
int32_t focusdir(const Arg *arg);
|
int32_t focusdir(const Arg *arg);
|
||||||
|
int32_t groupjoin(const Arg *arg);
|
||||||
|
int32_t groupleave(const Arg *arg);
|
||||||
int32_t toggleoverview(const Arg *arg);
|
int32_t toggleoverview(const Arg *arg);
|
||||||
int32_t togglejump(const Arg *arg);
|
int32_t togglejump(const Arg *arg);
|
||||||
int32_t set_proportion(const Arg *arg);
|
int32_t set_proportion(const Arg *arg);
|
||||||
|
|
@ -38,6 +40,7 @@ int32_t toggleglobal(const Arg *arg);
|
||||||
int32_t incnmaster(const Arg *arg);
|
int32_t incnmaster(const Arg *arg);
|
||||||
int32_t focusmon(const Arg *arg);
|
int32_t focusmon(const Arg *arg);
|
||||||
int32_t focusstack(const Arg *arg);
|
int32_t focusstack(const Arg *arg);
|
||||||
|
int32_t groupfocus(const Arg *arg);
|
||||||
int32_t chvt(const Arg *arg);
|
int32_t chvt(const Arg *arg);
|
||||||
int32_t reload_config(const Arg *arg);
|
int32_t reload_config(const Arg *arg);
|
||||||
int32_t smartmovewin(const Arg *arg);
|
int32_t smartmovewin(const Arg *arg);
|
||||||
|
|
@ -70,6 +73,9 @@ int32_t setoption(const Arg *arg);
|
||||||
int32_t disable_monitor(const Arg *arg);
|
int32_t disable_monitor(const Arg *arg);
|
||||||
int32_t enable_monitor(const Arg *arg);
|
int32_t enable_monitor(const Arg *arg);
|
||||||
int32_t toggle_monitor(const Arg *arg);
|
int32_t toggle_monitor(const Arg *arg);
|
||||||
|
int32_t sleep_monitor(const Arg *arg);
|
||||||
|
int32_t wakeup_monitor(const Arg *arg);
|
||||||
|
int32_t sleep_toggle_monitor(const Arg *arg);
|
||||||
int32_t scroller_stack(const Arg *arg);
|
int32_t scroller_stack(const Arg *arg);
|
||||||
int32_t toggle_all_floating(const Arg *arg);
|
int32_t toggle_all_floating(const Arg *arg);
|
||||||
int32_t dwindle_toggle_split_direction(const Arg *arg);
|
int32_t dwindle_toggle_split_direction(const Arg *arg);
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,94 @@ int32_t focusdir(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t groupjoin(const Arg *arg) {
|
||||||
|
|
||||||
|
if (!selmon)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Monitor *oldmon = NULL;
|
||||||
|
|
||||||
|
Client *need_join_client = arg->tc ? arg->tc : selmon->sel;
|
||||||
|
if (!need_join_client || !need_join_client->mon)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (need_join_client->mon->isoverview)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Client *need_replace_client = NULL;
|
||||||
|
need_replace_client = direction_select(arg);
|
||||||
|
|
||||||
|
if (!need_replace_client || !need_replace_client->mon)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (need_join_client == need_replace_client)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (need_join_client->group_next || need_join_client->group_prev) {
|
||||||
|
groupleave(&(Arg){.tc = need_join_client});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_join_client->mon != need_replace_client->mon) {
|
||||||
|
oldmon = need_join_client->mon;
|
||||||
|
need_join_client->mon = need_replace_client->mon;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!need_replace_client->group_prev && !need_replace_client->group_next) {
|
||||||
|
need_replace_client->isgroupfocusing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
need_join_client->group_next = need_replace_client;
|
||||||
|
|
||||||
|
if (need_replace_client->group_prev) {
|
||||||
|
need_replace_client->group_prev->group_next = need_join_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
need_join_client->group_prev = need_replace_client->group_prev;
|
||||||
|
|
||||||
|
need_replace_client->group_prev = need_join_client;
|
||||||
|
|
||||||
|
client_focus_group_member(need_join_client);
|
||||||
|
arrange(need_join_client->mon, false, false);
|
||||||
|
|
||||||
|
// oldmon可能已经死掉了
|
||||||
|
if (oldmon) {
|
||||||
|
arrange(oldmon, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t groupleave(const Arg *arg) {
|
||||||
|
|
||||||
|
if (!selmon)
|
||||||
|
return 0;
|
||||||
|
Client *tc = arg->tc ? arg->tc : selmon->sel;
|
||||||
|
if (!tc || !tc->mon || !tc->isgroupfocusing)
|
||||||
|
return 0;
|
||||||
|
if (!tc->group_next && !tc->group_prev) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tc->mon->isoverview)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Client *rc = tc->group_next ? tc->group_next : tc->group_prev;
|
||||||
|
|
||||||
|
client_focus_group_member(rc);
|
||||||
|
client_group_detach(tc);
|
||||||
|
|
||||||
|
tc->isgroupfocusing = false;
|
||||||
|
tc->is_logic_hide = false;
|
||||||
|
|
||||||
|
if (!rc->group_prev && !rc->group_next) {
|
||||||
|
rc->isgroupfocusing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
arrange(tc->mon, false, false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t focuslast(const Arg *arg) {
|
int32_t focuslast(const Arg *arg) {
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
Client *tc = NULL;
|
Client *tc = NULL;
|
||||||
|
|
@ -261,6 +349,34 @@ int32_t focusstack(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t groupfocus(const Arg *arg) {
|
||||||
|
Client *c = arg->tc ? arg->tc : selmon->sel;
|
||||||
|
if (!c || !c->mon)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!c->group_prev && !c->group_next) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->mon->isoverview)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Client *tc = NULL;
|
||||||
|
|
||||||
|
if (arg->i == NEXT) {
|
||||||
|
tc = c->group_next;
|
||||||
|
} else {
|
||||||
|
tc = c->group_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
client_focus_group_member(tc);
|
||||||
|
arrange(tc->mon, false, false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t incnmaster(const Arg *arg) {
|
int32_t incnmaster(const Arg *arg) {
|
||||||
if (!arg || !selmon)
|
if (!arg || !selmon)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -366,7 +482,7 @@ int32_t moveresize(const Arg *arg) {
|
||||||
|
|
||||||
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||||
return 0;
|
return 0;
|
||||||
xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
|
xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL, NULL);
|
||||||
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen ||
|
if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen ||
|
||||||
grabc->ismaximizescreen) {
|
grabc->ismaximizescreen) {
|
||||||
grabc = NULL;
|
grabc = NULL;
|
||||||
|
|
@ -1427,15 +1543,7 @@ int32_t toggleoverlay(const Arg *arg) {
|
||||||
|
|
||||||
c->isoverlay ^= 1;
|
c->isoverlay ^= 1;
|
||||||
|
|
||||||
if (c->isoverlay) {
|
client_reparent_group(c);
|
||||||
wlr_scene_node_reparent(&c->scene->node, layers[LyrOverlay]);
|
|
||||||
wlr_scene_node_raise_to_top(&c->scene->node);
|
|
||||||
} else if (client_should_overtop(c) && c->isfloating) {
|
|
||||||
wlr_scene_node_reparent(&c->scene->node, layers[LyrTop]);
|
|
||||||
} else {
|
|
||||||
wlr_scene_node_reparent(&c->scene->node,
|
|
||||||
layers[c->isfloating ? LyrTop : LyrTile]);
|
|
||||||
}
|
|
||||||
setborder_color(c);
|
setborder_color(c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1825,12 +1933,12 @@ int32_t togglejump(const Arg *arg) {
|
||||||
|
|
||||||
int32_t disable_monitor(const Arg *arg) {
|
int32_t disable_monitor(const Arg *arg) {
|
||||||
Monitor *m = NULL;
|
Monitor *m = NULL;
|
||||||
struct wlr_output_state state = {0};
|
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (match_monitor_spec(arg->v, m)) {
|
if (match_monitor_spec(arg->v, m)) {
|
||||||
wlr_output_state_set_enabled(&state, false);
|
wlr_output_state_set_enabled(&m->pending, false);
|
||||||
wlr_output_commit_state(m->wlr_output, &state);
|
mango_output_commit(m);
|
||||||
m->asleep = 1;
|
m->only_sleep = 0;
|
||||||
updatemons(NULL, NULL);
|
updatemons(NULL, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1840,12 +1948,11 @@ int32_t disable_monitor(const Arg *arg) {
|
||||||
|
|
||||||
int32_t enable_monitor(const Arg *arg) {
|
int32_t enable_monitor(const Arg *arg) {
|
||||||
Monitor *m = NULL;
|
Monitor *m = NULL;
|
||||||
struct wlr_output_state state = {0};
|
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (match_monitor_spec(arg->v, m)) {
|
if (match_monitor_spec(arg->v, m)) {
|
||||||
wlr_output_state_set_enabled(&state, true);
|
wlr_output_state_set_enabled(&m->pending, true);
|
||||||
wlr_output_commit_state(m->wlr_output, &state);
|
mango_output_commit(m);
|
||||||
m->asleep = 0;
|
m->only_sleep = 0;
|
||||||
updatemons(NULL, NULL);
|
updatemons(NULL, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1855,12 +1962,54 @@ int32_t enable_monitor(const Arg *arg) {
|
||||||
|
|
||||||
int32_t toggle_monitor(const Arg *arg) {
|
int32_t toggle_monitor(const Arg *arg) {
|
||||||
Monitor *m = NULL;
|
Monitor *m = NULL;
|
||||||
struct wlr_output_state state = {0};
|
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (match_monitor_spec(arg->v, m)) {
|
if (match_monitor_spec(arg->v, m)) {
|
||||||
wlr_output_state_set_enabled(&state, !m->wlr_output->enabled);
|
wlr_output_state_set_enabled(&m->pending, !m->wlr_output->enabled);
|
||||||
wlr_output_commit_state(m->wlr_output, &state);
|
mango_output_commit(m);
|
||||||
m->asleep = !m->wlr_output->enabled;
|
m->only_sleep = 0;
|
||||||
|
updatemons(NULL, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sleep_monitor(const Arg *arg) {
|
||||||
|
Monitor *m = NULL;
|
||||||
|
|
||||||
|
wl_list_for_each(m, &mons, link) {
|
||||||
|
if (match_monitor_spec(arg->v, m)) {
|
||||||
|
wlr_output_state_set_enabled(&m->pending, false);
|
||||||
|
mango_output_commit(m);
|
||||||
|
m->only_sleep = 1;
|
||||||
|
updatemons(NULL, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t wakeup_monitor(const Arg *arg) {
|
||||||
|
Monitor *m = NULL;
|
||||||
|
wl_list_for_each(m, &mons, link) {
|
||||||
|
if (match_monitor_spec(arg->v, m)) {
|
||||||
|
wlr_output_state_set_enabled(&m->pending, true);
|
||||||
|
mango_output_commit(m);
|
||||||
|
m->only_sleep = 0;
|
||||||
|
updatemons(NULL, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sleep_toggle_monitor(const Arg *arg) {
|
||||||
|
Monitor *m = NULL;
|
||||||
|
wl_list_for_each(m, &mons, link) {
|
||||||
|
if (match_monitor_spec(arg->v, m)) {
|
||||||
|
wlr_output_state_set_enabled(&m->pending, !m->wlr_output->enabled);
|
||||||
|
mango_output_commit(m);
|
||||||
|
m->only_sleep = !m->wlr_output->enabled;
|
||||||
updatemons(NULL, NULL);
|
updatemons(NULL, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1912,13 +2061,11 @@ int32_t scroller_apply_stack(Client *c, Client *target_client,
|
||||||
|
|
||||||
if (direction == LEFT || direction == UP) {
|
if (direction == LEFT || direction == UP) {
|
||||||
if (c != stack_head) {
|
if (c != stack_head) {
|
||||||
wl_list_remove(&c->link);
|
wl_list_safe_reinsert_prev(&stack_head->link, &c->link);
|
||||||
wl_list_insert(stack_head->link.prev, &c->link);
|
|
||||||
}
|
}
|
||||||
} else if (direction == RIGHT || direction == DOWN) {
|
} else if (direction == RIGHT || direction == DOWN) {
|
||||||
if (c != stack_tail) {
|
if (c != stack_tail) {
|
||||||
wl_list_remove(&c->link);
|
wl_list_safe_reinsert_next(&stack_head->link, &c->link);
|
||||||
wl_list_insert(&stack_tail->link, &c->link);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sync_scroller_state_to_clients(m, tag);
|
sync_scroller_state_to_clients(m, tag);
|
||||||
|
|
@ -2001,7 +2148,8 @@ int32_t dwindle_set_split_direction(Client *c, bool istoggle, bool horizontal) {
|
||||||
leaf->custom_leaf_split_h = false;
|
leaf->custom_leaf_split_h = false;
|
||||||
}
|
}
|
||||||
bool hit_no_border = check_hit_no_border(c);
|
bool hit_no_border = check_hit_no_border(c);
|
||||||
apply_split_border(c, hit_no_border);
|
struct ivec2 offsets = compute_edge_offsets(c);
|
||||||
|
client_draw_split_border(c, hit_no_border, offsets);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2040,6 +2188,13 @@ int32_t focusid(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Client *c = arg->tc;
|
Client *c = arg->tc;
|
||||||
|
|
||||||
|
if (c->swallowdby)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (c->group_next || c->group_prev)
|
||||||
|
client_focus_group_member(c);
|
||||||
|
|
||||||
client_active(c);
|
client_active(c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -59,10 +59,9 @@ static const struct wlr_buffer_impl text_buffer_impl = {
|
||||||
.end_data_ptr_access = text_buffer_end_data_ptr_access,
|
.end_data_ptr_access = text_buffer_end_data_ptr_access,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mango_jump_label_node *
|
MangoJumpLabel *mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
||||||
mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
DecorateDrawData data) {
|
||||||
DecorateDrawData data) {
|
MangoJumpLabel *node = calloc(1, sizeof(*node));
|
||||||
struct mango_jump_label_node *node = calloc(1, sizeof(*node));
|
|
||||||
if (!node)
|
if (!node)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
@ -104,7 +103,7 @@ mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_jump_label_node_destroy(struct mango_jump_label_node *node) {
|
void mango_jump_label_node_destroy(MangoJumpLabel *node) {
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -136,8 +135,8 @@ void mango_jump_label_node_destroy(struct mango_jump_label_node *node) {
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_jump_label_node_set_background(struct mango_jump_label_node *node,
|
void mango_jump_label_node_set_background(MangoJumpLabel *node, float r,
|
||||||
float r, float g, float b, float a) {
|
float g, float b, float a) {
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
node->bg_color[0] = r;
|
node->bg_color[0] = r;
|
||||||
|
|
@ -146,9 +145,9 @@ void mango_jump_label_node_set_background(struct mango_jump_label_node *node,
|
||||||
node->bg_color[3] = a;
|
node->bg_color[3] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_jump_label_node_set_border(struct mango_jump_label_node *node,
|
void mango_jump_label_node_set_border(MangoJumpLabel *node, float r, float g,
|
||||||
float r, float g, float b, float a,
|
float b, float a, int32_t width,
|
||||||
int32_t width, int32_t radius) {
|
int32_t radius) {
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
node->border_color[0] = r;
|
node->border_color[0] = r;
|
||||||
|
|
@ -159,17 +158,16 @@ void mango_jump_label_node_set_border(struct mango_jump_label_node *node,
|
||||||
node->corner_radius = radius;
|
node->corner_radius = radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_jump_label_node_set_padding(struct mango_jump_label_node *node,
|
void mango_jump_label_node_set_padding(MangoJumpLabel *node, int32_t pad_x,
|
||||||
int32_t pad_x, int32_t pad_y) {
|
int32_t pad_y) {
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
node->padding_x = pad_x >= 0 ? pad_x : 0;
|
node->padding_x = pad_x >= 0 ? pad_x : 0;
|
||||||
node->padding_y = pad_y >= 0 ? pad_y : 0;
|
node->padding_y = pad_y >= 0 ? pad_y : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_text_pixel_size(struct mango_jump_label_node *node,
|
static void get_text_pixel_size(MangoJumpLabel *node, const char *text,
|
||||||
const char *text, float scale, int32_t *out_w,
|
float scale, int32_t *out_w, int32_t *out_h) {
|
||||||
int32_t *out_h) {
|
|
||||||
if (node->measure_scale != scale) {
|
if (node->measure_scale != scale) {
|
||||||
pango_cairo_context_set_resolution(node->measure_context, 96.0 * scale);
|
pango_cairo_context_set_resolution(node->measure_context, 96.0 * scale);
|
||||||
node->measure_scale = scale;
|
node->measure_scale = scale;
|
||||||
|
|
@ -184,6 +182,10 @@ static void get_text_pixel_size(struct mango_jump_label_node *node,
|
||||||
|
|
||||||
static void draw_rounded_rect(cairo_t *cr, double x, double y, double w,
|
static void draw_rounded_rect(cairo_t *cr, double x, double y, double w,
|
||||||
double h, double r) {
|
double h, double r) {
|
||||||
|
// 宽高非正时不绘制任何东西
|
||||||
|
if (w <= 0.0 || h <= 0.0)
|
||||||
|
return;
|
||||||
|
|
||||||
double degrees = G_PI / 180.0;
|
double degrees = G_PI / 180.0;
|
||||||
cairo_new_sub_path(cr);
|
cairo_new_sub_path(cr);
|
||||||
cairo_arc(cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);
|
cairo_arc(cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);
|
||||||
|
|
@ -193,14 +195,14 @@ static void draw_rounded_rect(cairo_t *cr, double x, double y, double w,
|
||||||
cairo_close_path(cr);
|
cairo_close_path(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
|
||||||
const char *text, float scale) {
|
float scale) {
|
||||||
if (!node || !text)
|
if (!node || !text)
|
||||||
return;
|
return;
|
||||||
if (scale <= 0.0f)
|
if (scale <= 0.0f)
|
||||||
scale = 1.0f;
|
scale = 1.0f;
|
||||||
|
|
||||||
/* 脏检查,加入 focused 状态 */
|
// 脏检查
|
||||||
if (node->cached_scale == scale && node->cached_font_desc &&
|
if (node->cached_scale == scale && node->cached_font_desc &&
|
||||||
strcmp(node->cached_font_desc, node->font_desc) == 0 &&
|
strcmp(node->cached_font_desc, node->font_desc) == 0 &&
|
||||||
node->cached_text && strcmp(node->cached_text, text) == 0 &&
|
node->cached_text && strcmp(node->cached_text, text) == 0 &&
|
||||||
|
|
@ -222,7 +224,7 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 更新缓存 */
|
// 更新缓存
|
||||||
g_free(node->cached_text);
|
g_free(node->cached_text);
|
||||||
node->cached_text = g_strdup(text);
|
node->cached_text = g_strdup(text);
|
||||||
g_free(node->cached_font_desc);
|
g_free(node->cached_font_desc);
|
||||||
|
|
@ -266,6 +268,7 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
||||||
int32_t box_logical_w = logical_text_w + 2 * node->padding_x;
|
int32_t box_logical_w = logical_text_w + 2 * node->padding_x;
|
||||||
int32_t box_logical_h = logical_text_h + 2 * node->padding_y;
|
int32_t box_logical_h = logical_text_h + 2 * node->padding_y;
|
||||||
|
|
||||||
|
// 物理像素尺寸包含边框,避免边框越界
|
||||||
int32_t required_pixel_w =
|
int32_t required_pixel_w =
|
||||||
(int32_t)((box_logical_w + 2 * node->border_width) * scale + 0.5f);
|
(int32_t)((box_logical_w + 2 * node->border_width) * scale + 0.5f);
|
||||||
int32_t required_pixel_h =
|
int32_t required_pixel_h =
|
||||||
|
|
@ -318,13 +321,15 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
||||||
radius = bg_w / 2.0;
|
radius = bg_w / 2.0;
|
||||||
if (radius > bg_h / 2.0)
|
if (radius > bg_h / 2.0)
|
||||||
radius = bg_h / 2.0;
|
radius = bg_h / 2.0;
|
||||||
|
if (radius < 0.0)
|
||||||
|
radius = 0.0;
|
||||||
|
|
||||||
const float *active_bg =
|
const float *active_bg =
|
||||||
node->focused ? node->focus_bg_color : node->bg_color;
|
node->focused ? node->focus_bg_color : node->bg_color;
|
||||||
const float *active_fg =
|
const float *active_fg =
|
||||||
node->focused ? node->focus_fg_color : node->fg_color;
|
node->focused ? node->focus_fg_color : node->fg_color;
|
||||||
|
|
||||||
bool draw_bg = (active_bg[3] > 0.0f); // 使用 active_bg
|
bool draw_bg = (active_bg[3] > 0.0f) && (bg_w > 0.0 && bg_h > 0.0);
|
||||||
bool draw_border =
|
bool draw_border =
|
||||||
(node->border_width > 0) && (node->border_color[3] > 0.0f);
|
(node->border_width > 0) && (node->border_color[3] > 0.0f);
|
||||||
|
|
||||||
|
|
@ -340,25 +345,28 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_save(cr);
|
// 文本绘制仅在背景区域有有效空间时进行
|
||||||
double text_x = (node->border_width + node->padding_x) * scale;
|
if (bg_w > 0.0 && bg_h > 0.0) {
|
||||||
double text_y = (node->border_width + node->padding_y) * scale;
|
cairo_save(cr);
|
||||||
cairo_translate(cr, text_x, text_y);
|
double text_x = (node->border_width + node->padding_x) * scale;
|
||||||
|
double text_y = (node->border_width + node->padding_y) * scale;
|
||||||
|
cairo_translate(cr, text_x, text_y);
|
||||||
|
|
||||||
PangoContext *ctx = pango_cairo_create_context(cr);
|
PangoContext *ctx = pango_cairo_create_context(cr);
|
||||||
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
||||||
PangoLayout *layout = pango_layout_new(ctx);
|
PangoLayout *layout = pango_layout_new(ctx);
|
||||||
PangoFontDescription *desc = get_cached_font_desc(node->font_desc);
|
PangoFontDescription *desc = get_cached_font_desc(node->font_desc);
|
||||||
pango_layout_set_font_description(layout, desc);
|
pango_layout_set_font_description(layout, desc);
|
||||||
pango_layout_set_text(layout, text, -1);
|
pango_layout_set_text(layout, text, -1);
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, active_fg[0], active_fg[1], active_fg[2],
|
cairo_set_source_rgba(cr, active_fg[0], active_fg[1], active_fg[2],
|
||||||
active_fg[3]);
|
active_fg[3]);
|
||||||
pango_cairo_show_layout(cr, layout);
|
pango_cairo_show_layout(cr, layout);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
g_object_unref(ctx);
|
g_object_unref(ctx);
|
||||||
cairo_restore(cr);
|
cairo_restore(cr);
|
||||||
|
}
|
||||||
|
|
||||||
if (draw_border) {
|
if (draw_border) {
|
||||||
cairo_set_source_rgba(cr, node->border_color[0], node->border_color[1],
|
cairo_set_source_rgba(cr, node->border_color[0], node->border_color[1],
|
||||||
|
|
@ -371,15 +379,35 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
||||||
double bw = bg_w + border;
|
double bw = bg_w + border;
|
||||||
double bh = bg_h + border;
|
double bh = bg_h + border;
|
||||||
|
|
||||||
if (radius > 0.0) {
|
// 确保边框矩形不越界且宽高为正
|
||||||
double outer_radius = radius + half_lw;
|
if (bx < 0.0) {
|
||||||
if (outer_radius < 0.0)
|
bw += bx; // bx 为负,bw 缩小
|
||||||
outer_radius = 0.0;
|
bx = 0.0;
|
||||||
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
}
|
||||||
} else {
|
if (by < 0.0) {
|
||||||
cairo_rectangle(cr, bx, by, bw, bh);
|
bh += by;
|
||||||
|
by = 0.0;
|
||||||
|
}
|
||||||
|
if (bx + bw > (double)node->surface_pixel_w)
|
||||||
|
bw = (double)node->surface_pixel_w - bx;
|
||||||
|
if (by + bh > (double)node->surface_pixel_h)
|
||||||
|
bh = (double)node->surface_pixel_h - by;
|
||||||
|
if (bw < 0.0)
|
||||||
|
bw = 0.0;
|
||||||
|
if (bh < 0.0)
|
||||||
|
bh = 0.0;
|
||||||
|
|
||||||
|
if (bw > 0.0 && bh > 0.0) {
|
||||||
|
if (radius > 0.0) {
|
||||||
|
double outer_radius = radius + half_lw;
|
||||||
|
if (outer_radius < 0.0)
|
||||||
|
outer_radius = 0.0;
|
||||||
|
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
||||||
|
} else {
|
||||||
|
cairo_rectangle(cr, bx, by, bw, bh);
|
||||||
|
}
|
||||||
|
cairo_stroke(cr);
|
||||||
}
|
}
|
||||||
cairo_stroke(cr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_flush(node->surface);
|
cairo_surface_flush(node->surface);
|
||||||
|
|
@ -407,67 +435,71 @@ void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
||||||
node->logical_height);
|
node->logical_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_jump_label_node_set_focus(struct mango_jump_label_node *node,
|
void mango_jump_label_node_set_focus(MangoJumpLabel *node, bool focused) {
|
||||||
bool focused) {
|
|
||||||
if (!node || node->focused == focused)
|
if (!node || node->focused == focused)
|
||||||
return;
|
return;
|
||||||
node->focused = focused;
|
node->focused = focused;
|
||||||
// 使用缓存的文本和缩放触发重绘(如果无文本则不重绘)
|
|
||||||
if (node->cached_text && node->cached_scale > 0.0f) {
|
if (node->cached_text && node->cached_scale > 0.0f) {
|
||||||
mango_jump_label_node_update(node, node->cached_text,
|
mango_jump_label_node_update(node, node->cached_text,
|
||||||
node->cached_scale);
|
node->cached_scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mango_tab_bar_node *
|
MangoGroupBar *mango_group_bar_create(void *cdata, uint32_t type,
|
||||||
mango_tab_bar_node_create(void *mango_node_data, struct wlr_scene_tree *parent,
|
struct wlr_scene_tree *parent,
|
||||||
DecorateDrawData data, int32_t width,
|
DecorateDrawData data, int32_t width,
|
||||||
int32_t height) {
|
int32_t height) {
|
||||||
struct mango_tab_bar_node *node = calloc(1, sizeof(*node));
|
MangoGroupBar *mangobar = calloc(1, sizeof(*mangobar));
|
||||||
if (!node)
|
if (!mangobar)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
node->scene_buffer = wlr_scene_buffer_create(parent, NULL);
|
mangobar->scene_buffer = wlr_scene_buffer_create(parent, NULL);
|
||||||
if (!node->scene_buffer) {
|
if (!mangobar->scene_buffer) {
|
||||||
free(node);
|
free(mangobar);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(node->fg_color, data.fg_color, sizeof(node->fg_color));
|
memcpy(mangobar->fg_color, data.fg_color, sizeof(mangobar->fg_color));
|
||||||
memcpy(node->bg_color, data.bg_color, sizeof(node->bg_color));
|
memcpy(mangobar->bg_color, data.bg_color, sizeof(mangobar->bg_color));
|
||||||
memcpy(node->focus_fg_color, data.focus_fg_color,
|
memcpy(mangobar->focus_fg_color, data.focus_fg_color,
|
||||||
sizeof(node->focus_fg_color));
|
sizeof(mangobar->focus_fg_color));
|
||||||
memcpy(node->focus_bg_color, data.focus_bg_color,
|
memcpy(mangobar->focus_bg_color, data.focus_bg_color,
|
||||||
sizeof(node->focus_bg_color));
|
sizeof(mangobar->focus_bg_color));
|
||||||
memcpy(node->border_color, data.border_color, sizeof(node->border_color));
|
memcpy(mangobar->border_color, data.border_color,
|
||||||
node->border_width = data.border_width;
|
sizeof(mangobar->border_color));
|
||||||
node->corner_radius = data.corner_radius;
|
mangobar->border_width = data.border_width;
|
||||||
node->padding_x = data.padding_x;
|
mangobar->corner_radius = data.corner_radius;
|
||||||
node->padding_y = data.padding_y;
|
mangobar->padding_x = data.padding_x;
|
||||||
node->font_desc =
|
mangobar->padding_y = data.padding_y;
|
||||||
|
mangobar->font_desc =
|
||||||
g_strdup(data.font_desc ? data.font_desc : "monospace Bold 16");
|
g_strdup(data.font_desc ? data.font_desc : "monospace Bold 16");
|
||||||
|
|
||||||
node->target_width = width;
|
mangobar->target_width = width;
|
||||||
node->target_height = height;
|
mangobar->target_height = height;
|
||||||
node->focused = false;
|
mangobar->focused = false;
|
||||||
node->cached_focused = false;
|
mangobar->cached_focused = false;
|
||||||
|
|
||||||
node->measure_surface =
|
mangobar->measure_surface =
|
||||||
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
|
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
|
||||||
node->measure_cr = cairo_create(node->measure_surface);
|
mangobar->measure_cr = cairo_create(mangobar->measure_surface);
|
||||||
node->measure_context = pango_cairo_create_context(node->measure_cr);
|
mangobar->measure_context =
|
||||||
node->measure_layout = pango_layout_new(node->measure_context);
|
pango_cairo_create_context(mangobar->measure_cr);
|
||||||
node->measure_scale = 1.0f;
|
mangobar->measure_layout = pango_layout_new(mangobar->measure_context);
|
||||||
|
mangobar->measure_scale = 1.0f;
|
||||||
|
|
||||||
node->cached_scale = -1.0f;
|
mangobar->cached_scale = -1.0f;
|
||||||
node->last_text = NULL;
|
mangobar->last_text = NULL;
|
||||||
node->last_scale = 0.0f;
|
mangobar->last_scale = 0.0f;
|
||||||
node->scene_buffer->node.data = mango_node_data;
|
|
||||||
|
|
||||||
return node;
|
mangobar->type = type;
|
||||||
|
mangobar->node_data = cdata;
|
||||||
|
|
||||||
|
mangobar->scene_buffer->node.data = mangobar;
|
||||||
|
|
||||||
|
return mangobar;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_tab_bar_node_destroy(struct mango_tab_bar_node *node) {
|
void mango_group_bar_destroy(MangoGroupBar *node) {
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -492,19 +524,17 @@ void mango_tab_bar_node_destroy(struct mango_tab_bar_node *node) {
|
||||||
if (node->measure_cr)
|
if (node->measure_cr)
|
||||||
cairo_destroy(node->measure_cr);
|
cairo_destroy(node->measure_cr);
|
||||||
|
|
||||||
void *data = node->scene_buffer->node.data;
|
|
||||||
wlr_scene_node_destroy(&node->scene_buffer->node);
|
wlr_scene_node_destroy(&node->scene_buffer->node);
|
||||||
|
|
||||||
g_free(node->font_desc);
|
g_free(node->font_desc);
|
||||||
g_free(node->cached_text);
|
g_free(node->cached_text);
|
||||||
g_free(node->cached_font_desc);
|
g_free(node->cached_font_desc);
|
||||||
g_free(node->last_text);
|
g_free(node->last_text);
|
||||||
free(data);
|
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_tab_bar_node_set_size(struct mango_tab_bar_node *node, int32_t width,
|
void mango_group_bar_set_size(MangoGroupBar *node, int32_t width,
|
||||||
int32_t height) {
|
int32_t height) {
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -522,11 +552,11 @@ void mango_tab_bar_node_set_size(struct mango_tab_bar_node *node, int32_t width,
|
||||||
const char *redraw_text = node->last_text ? node->last_text : "";
|
const char *redraw_text = node->last_text ? node->last_text : "";
|
||||||
float redraw_scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
float redraw_scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
||||||
|
|
||||||
mango_tab_bar_node_update(node, redraw_text, redraw_scale);
|
mango_group_bar_update(node, redraw_text, redraw_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
void mango_group_bar_update(MangoGroupBar *node, const char *text,
|
||||||
const char *text, float scale) {
|
float scale) {
|
||||||
if (!node || !text)
|
if (!node || !text)
|
||||||
return;
|
return;
|
||||||
if (scale <= 0.0f)
|
if (scale <= 0.0f)
|
||||||
|
|
@ -538,7 +568,7 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||||
node->last_text = safe_text; // 所有权转移
|
node->last_text = safe_text; // 所有权转移
|
||||||
node->last_scale = scale;
|
node->last_scale = scale;
|
||||||
|
|
||||||
// 脏检查加入 focused
|
// 脏检查
|
||||||
if (node->cached_scale == scale && node->cached_font_desc &&
|
if (node->cached_scale == scale && node->cached_font_desc &&
|
||||||
strcmp(node->cached_font_desc, node->font_desc) == 0 &&
|
strcmp(node->cached_font_desc, node->font_desc) == 0 &&
|
||||||
node->cached_text && strcmp(node->cached_text, safe_text) == 0 &&
|
node->cached_text && strcmp(node->cached_text, safe_text) == 0 &&
|
||||||
|
|
@ -608,8 +638,18 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||||
if (box_logical_h < 0)
|
if (box_logical_h < 0)
|
||||||
box_logical_h = 0;
|
box_logical_h = 0;
|
||||||
|
|
||||||
|
// surface 物理尺寸包含边框,避免边框绘制越界
|
||||||
int32_t required_pixel_w = (int32_t)(node->target_width * scale + 0.5f);
|
int32_t required_pixel_w = (int32_t)(node->target_width * scale + 0.5f);
|
||||||
int32_t required_pixel_h = (int32_t)(node->target_height * scale + 0.5f);
|
int32_t required_pixel_h = (int32_t)(node->target_height * scale + 0.5f);
|
||||||
|
// 如果边框会伸出 target 区域,则扩展 surface 尺寸以完全容纳
|
||||||
|
double border_phys = node->border_width * scale;
|
||||||
|
if (border_phys > 0.0) {
|
||||||
|
// 边框描边会向外延伸 half line width,所以需要额外空间
|
||||||
|
int extra_w = (int32_t)ceil(border_phys * 0.5);
|
||||||
|
int extra_h = (int32_t)ceil(border_phys * 0.5);
|
||||||
|
required_pixel_w += extra_w;
|
||||||
|
required_pixel_h += extra_h;
|
||||||
|
}
|
||||||
if (required_pixel_w < 1)
|
if (required_pixel_w < 1)
|
||||||
required_pixel_w = 1;
|
required_pixel_w = 1;
|
||||||
if (required_pixel_h < 1)
|
if (required_pixel_h < 1)
|
||||||
|
|
@ -641,7 +681,6 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||||
cairo_paint(cr);
|
cairo_paint(cr);
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||||
|
|
||||||
double border_phys = node->border_width * scale;
|
|
||||||
double bg_x = border_phys;
|
double bg_x = border_phys;
|
||||||
double bg_y = border_phys;
|
double bg_y = border_phys;
|
||||||
double bg_w = box_logical_w * scale;
|
double bg_w = box_logical_w * scale;
|
||||||
|
|
@ -657,13 +696,15 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||||
radius = bg_w / 2.0;
|
radius = bg_w / 2.0;
|
||||||
if (radius > bg_h / 2.0)
|
if (radius > bg_h / 2.0)
|
||||||
radius = bg_h / 2.0;
|
radius = bg_h / 2.0;
|
||||||
|
if (radius < 0.0)
|
||||||
|
radius = 0.0;
|
||||||
|
|
||||||
const float *active_bg =
|
const float *active_bg =
|
||||||
node->focused ? node->focus_bg_color : node->bg_color;
|
node->focused ? node->focus_bg_color : node->bg_color;
|
||||||
const float *active_fg =
|
const float *active_fg =
|
||||||
node->focused ? node->focus_fg_color : node->fg_color;
|
node->focused ? node->focus_fg_color : node->fg_color;
|
||||||
|
|
||||||
bool draw_bg = (active_bg[3] > 0.0f);
|
bool draw_bg = (active_bg[3] > 0.0f) && (bg_w > 0.0 && bg_h > 0.0);
|
||||||
bool draw_border =
|
bool draw_border =
|
||||||
(node->border_width > 0) && (node->border_color[3] > 0.0f);
|
(node->border_width > 0) && (node->border_color[3] > 0.0f);
|
||||||
|
|
||||||
|
|
@ -679,43 +720,46 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t text_area_logical_w = box_logical_w - 2 * node->padding_x;
|
// 仅在背景区域有空间时进行
|
||||||
int32_t text_area_logical_h = box_logical_h - 2 * node->padding_y;
|
if (bg_w > 0.0 && bg_h > 0.0) {
|
||||||
if (text_area_logical_w > 0 && text_area_logical_h > 0) {
|
int32_t text_area_logical_w = box_logical_w - 2 * node->padding_x;
|
||||||
cairo_save(cr);
|
int32_t text_area_logical_h = box_logical_h - 2 * node->padding_y;
|
||||||
|
if (text_area_logical_w > 0 && text_area_logical_h > 0) {
|
||||||
|
cairo_save(cr);
|
||||||
|
|
||||||
double text_x = (node->border_width + node->padding_x) * scale;
|
double text_x = (node->border_width + node->padding_x) * scale;
|
||||||
double text_y = (node->border_width + node->padding_y) * scale;
|
double text_y = (node->border_width + node->padding_y) * scale;
|
||||||
double text_area_w = text_area_logical_w * scale;
|
double text_area_w = text_area_logical_w * scale;
|
||||||
double text_area_h = text_area_logical_h * scale;
|
double text_area_h = text_area_logical_h * scale;
|
||||||
|
|
||||||
PangoContext *ctx = pango_cairo_create_context(cr);
|
PangoContext *ctx = pango_cairo_create_context(cr);
|
||||||
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
pango_cairo_context_set_resolution(ctx, 96.0 * scale);
|
||||||
PangoLayout *layout = pango_layout_new(ctx);
|
PangoLayout *layout = pango_layout_new(ctx);
|
||||||
PangoFontDescription *desc = get_cached_font_desc(node->font_desc);
|
PangoFontDescription *desc = get_cached_font_desc(node->font_desc);
|
||||||
pango_layout_set_font_description(layout, desc);
|
pango_layout_set_font_description(layout, desc);
|
||||||
pango_layout_set_text(layout, safe_text, -1);
|
pango_layout_set_text(layout, safe_text, -1);
|
||||||
|
|
||||||
pango_layout_set_wrap(layout, PANGO_WRAP_NONE);
|
pango_layout_set_wrap(layout, PANGO_WRAP_NONE);
|
||||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||||
pango_layout_set_width(layout, (int)(text_area_w * PANGO_SCALE));
|
pango_layout_set_width(layout, (int)(text_area_w * PANGO_SCALE));
|
||||||
|
|
||||||
int text_pixel_w, text_pixel_h;
|
int text_pixel_w, text_pixel_h;
|
||||||
pango_layout_get_pixel_size(layout, &text_pixel_w, &text_pixel_h);
|
pango_layout_get_pixel_size(layout, &text_pixel_w, &text_pixel_h);
|
||||||
double y_offset = (text_area_h - text_pixel_h) / 2.0;
|
double y_offset = (text_area_h - text_pixel_h) / 2.0;
|
||||||
if (y_offset < 0)
|
if (y_offset < 0)
|
||||||
y_offset = 0;
|
y_offset = 0;
|
||||||
|
|
||||||
cairo_translate(cr, text_x, text_y + y_offset);
|
cairo_translate(cr, text_x, text_y + y_offset);
|
||||||
|
|
||||||
cairo_set_source_rgba(cr, active_fg[0], active_fg[1], active_fg[2],
|
cairo_set_source_rgba(cr, active_fg[0], active_fg[1], active_fg[2],
|
||||||
active_fg[3]);
|
active_fg[3]);
|
||||||
pango_cairo_show_layout(cr, layout);
|
pango_cairo_show_layout(cr, layout);
|
||||||
|
|
||||||
g_object_unref(layout);
|
g_object_unref(layout);
|
||||||
g_object_unref(ctx);
|
g_object_unref(ctx);
|
||||||
cairo_restore(cr);
|
cairo_restore(cr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (draw_border) {
|
if (draw_border) {
|
||||||
|
|
@ -729,15 +773,35 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||||
double bw = bg_w + border_phys;
|
double bw = bg_w + border_phys;
|
||||||
double bh = bg_h + border_phys;
|
double bh = bg_h + border_phys;
|
||||||
|
|
||||||
if (radius > 0.0) {
|
// 确保边框矩形不越界且宽高为正
|
||||||
double outer_radius = radius + half_lw;
|
if (bx < 0.0) {
|
||||||
if (outer_radius < 0.0)
|
bw += bx;
|
||||||
outer_radius = 0.0;
|
bx = 0.0;
|
||||||
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
}
|
||||||
} else {
|
if (by < 0.0) {
|
||||||
cairo_rectangle(cr, bx, by, bw, bh);
|
bh += by;
|
||||||
|
by = 0.0;
|
||||||
|
}
|
||||||
|
if (bx + bw > (double)node->surface_pixel_w)
|
||||||
|
bw = (double)node->surface_pixel_w - bx;
|
||||||
|
if (by + bh > (double)node->surface_pixel_h)
|
||||||
|
bh = (double)node->surface_pixel_h - by;
|
||||||
|
if (bw < 0.0)
|
||||||
|
bw = 0.0;
|
||||||
|
if (bh < 0.0)
|
||||||
|
bh = 0.0;
|
||||||
|
|
||||||
|
if (bw > 0.0 && bh > 0.0) {
|
||||||
|
if (radius > 0.0) {
|
||||||
|
double outer_radius = radius + half_lw;
|
||||||
|
if (outer_radius < 0.0)
|
||||||
|
outer_radius = 0.0;
|
||||||
|
draw_rounded_rect(cr, bx, by, bw, bh, outer_radius);
|
||||||
|
} else {
|
||||||
|
cairo_rectangle(cr, bx, by, bw, bh);
|
||||||
|
}
|
||||||
|
cairo_stroke(cr);
|
||||||
}
|
}
|
||||||
cairo_stroke(cr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_flush(node->surface);
|
cairo_surface_flush(node->surface);
|
||||||
|
|
@ -765,19 +829,18 @@ void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
||||||
node->logical_height);
|
node->logical_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_tab_bar_node_set_focus(struct mango_tab_bar_node *node,
|
void mango_group_bar_set_focus(MangoGroupBar *node, bool focused) {
|
||||||
bool focused) {
|
|
||||||
if (!node || node->focused == focused)
|
if (!node || node->focused == focused)
|
||||||
return;
|
return;
|
||||||
node->focused = focused;
|
node->focused = focused;
|
||||||
if (node->last_text) {
|
if (node->last_text) {
|
||||||
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
||||||
mango_tab_bar_node_update(node, node->last_text, scale);
|
mango_group_bar_update(node, node->last_text, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_tab_bar_node_set_colors(struct mango_tab_bar_node *node,
|
void mango_group_bar_set_colors(MangoGroupBar *node, const float fg[4],
|
||||||
const float fg[4], const float bg[4]) {
|
const float bg[4]) {
|
||||||
if (!node)
|
if (!node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -786,11 +849,11 @@ void mango_tab_bar_node_set_colors(struct mango_tab_bar_node *node,
|
||||||
|
|
||||||
if (!node->focused && node->last_text) {
|
if (!node->focused && node->last_text) {
|
||||||
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
||||||
mango_tab_bar_node_update(node, node->last_text, scale);
|
mango_group_bar_update(node, node->last_text, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_jump_label_node_apply_config(struct mango_jump_label_node *node,
|
void mango_jump_label_node_apply_config(MangoJumpLabel *node,
|
||||||
const DecorateDrawData *data) {
|
const DecorateDrawData *data) {
|
||||||
if (!node || !data)
|
if (!node || !data)
|
||||||
return;
|
return;
|
||||||
|
|
@ -817,8 +880,8 @@ void mango_jump_label_node_apply_config(struct mango_jump_label_node *node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mango_tab_bar_node_apply_config(struct mango_tab_bar_node *node,
|
void mango_group_bar_apply_config(MangoGroupBar *node,
|
||||||
const DecorateDrawData *data) {
|
const DecorateDrawData *data) {
|
||||||
if (!node || !data)
|
if (!node || !data)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -840,6 +903,6 @@ void mango_tab_bar_node_apply_config(struct mango_tab_bar_node *node,
|
||||||
|
|
||||||
if (node->last_text) {
|
if (node->last_text) {
|
||||||
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
float scale = node->last_scale > 0.0f ? node->last_scale : 1.0f;
|
||||||
mango_tab_bar_node_update(node, node->last_text, scale);
|
mango_group_bar_update(node, node->last_text, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -26,8 +26,7 @@ struct mango_text_buffer {
|
||||||
struct wlr_buffer base;
|
struct wlr_buffer base;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
};
|
};
|
||||||
|
typedef struct {
|
||||||
struct mango_jump_label_node {
|
|
||||||
struct wlr_scene_buffer *scene_buffer;
|
struct wlr_scene_buffer *scene_buffer;
|
||||||
struct mango_text_buffer *buffer;
|
struct mango_text_buffer *buffer;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
|
|
@ -70,13 +69,15 @@ struct mango_jump_label_node {
|
||||||
|
|
||||||
int32_t logical_width;
|
int32_t logical_width;
|
||||||
int32_t logical_height;
|
int32_t logical_height;
|
||||||
};
|
} MangoJumpLabel;
|
||||||
|
|
||||||
struct mango_tab_bar_node {
|
typedef struct {
|
||||||
|
uint32_t type; // must at first in struct
|
||||||
struct wlr_scene_buffer *scene_buffer;
|
struct wlr_scene_buffer *scene_buffer;
|
||||||
struct mango_text_buffer *buffer;
|
struct mango_text_buffer *buffer;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
int surface_pixel_w, surface_pixel_h;
|
int surface_pixel_w, surface_pixel_h;
|
||||||
|
void *node_data; // 存储窗口指针
|
||||||
|
|
||||||
// 初始配置
|
// 初始配置
|
||||||
float fg_color[4];
|
float fg_color[4];
|
||||||
|
|
@ -126,41 +127,38 @@ struct mango_tab_bar_node {
|
||||||
|
|
||||||
int32_t logical_width;
|
int32_t logical_width;
|
||||||
int32_t logical_height;
|
int32_t logical_height;
|
||||||
};
|
} MangoGroupBar;
|
||||||
|
|
||||||
void mango_text_global_finish(void);
|
void mango_text_global_finish(void);
|
||||||
struct mango_jump_label_node *
|
MangoJumpLabel *mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
||||||
mango_jump_label_node_create(struct wlr_scene_tree *parent,
|
DecorateDrawData data);
|
||||||
DecorateDrawData data);
|
void mango_jump_label_node_destroy(MangoJumpLabel *node);
|
||||||
void mango_jump_label_node_destroy(struct mango_jump_label_node *node);
|
void mango_jump_label_node_set_background(MangoJumpLabel *node, float r,
|
||||||
void mango_jump_label_node_set_background(struct mango_jump_label_node *node,
|
float g, float b, float a);
|
||||||
float r, float g, float b, float a);
|
void mango_jump_label_node_set_border(MangoJumpLabel *node, float r, float g,
|
||||||
void mango_jump_label_node_set_border(struct mango_jump_label_node *node,
|
float b, float a, int32_t width,
|
||||||
float r, float g, float b, float a,
|
int32_t radius);
|
||||||
int32_t width, int32_t radius);
|
void mango_jump_label_node_set_padding(MangoJumpLabel *node, int32_t pad_x,
|
||||||
void mango_jump_label_node_set_padding(struct mango_jump_label_node *node,
|
int32_t pad_y);
|
||||||
int32_t pad_x, int32_t pad_y);
|
void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
|
||||||
void mango_jump_label_node_update(struct mango_jump_label_node *node,
|
float scale);
|
||||||
const char *text, float scale);
|
|
||||||
|
|
||||||
struct mango_tab_bar_node *
|
MangoGroupBar *mango_group_bar_create(void *cdata, uint32_t type,
|
||||||
mango_tab_bar_node_create(void *mango_node_data, struct wlr_scene_tree *parent,
|
struct wlr_scene_tree *parent,
|
||||||
DecorateDrawData data, int32_t width, int32_t height);
|
DecorateDrawData data, int32_t width,
|
||||||
void mango_tab_bar_node_destroy(struct mango_tab_bar_node *node);
|
int32_t height);
|
||||||
void mango_tab_bar_node_set_size(struct mango_tab_bar_node *node, int32_t width,
|
void mango_group_bar_destroy(MangoGroupBar *node);
|
||||||
int32_t height);
|
void mango_group_bar_set_size(MangoGroupBar *node, int32_t width,
|
||||||
void mango_tab_bar_node_update(struct mango_tab_bar_node *node,
|
int32_t height);
|
||||||
const char *text, float scale);
|
void mango_group_bar_update(MangoGroupBar *node, const char *text, float scale);
|
||||||
|
|
||||||
void mango_jump_label_node_set_focus(struct mango_jump_label_node *node,
|
void mango_jump_label_node_set_focus(MangoJumpLabel *node, bool focused);
|
||||||
bool focused);
|
void mango_group_bar_set_focus(MangoGroupBar *node, bool focused);
|
||||||
void mango_tab_bar_node_set_focus(struct mango_tab_bar_node *node,
|
|
||||||
bool focused);
|
|
||||||
|
|
||||||
void mango_tab_bar_node_set_colors(struct mango_tab_bar_node *node,
|
void mango_group_bar_set_colors(MangoGroupBar *node, const float fg[4],
|
||||||
const float fg[4], const float bg[4]);
|
const float bg[4]);
|
||||||
void mango_jump_label_node_apply_config(struct mango_jump_label_node *node,
|
void mango_jump_label_node_apply_config(MangoJumpLabel *node,
|
||||||
const DecorateDrawData *data);
|
const DecorateDrawData *data);
|
||||||
void mango_tab_bar_node_apply_config(struct mango_tab_bar_node *node,
|
void mango_group_bar_apply_config(MangoGroupBar *node,
|
||||||
const DecorateDrawData *data);
|
const DecorateDrawData *data);
|
||||||
#endif // jump_label_node_H
|
#endif // jump_label_node_H
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "dwl-ipc.h"
|
|
||||||
#include "ext-workspace.h"
|
#include "ext-workspace.h"
|
||||||
#include "foreign-toplevel.h"
|
#include "foreign-toplevel.h"
|
||||||
|
#include "hdr.h"
|
||||||
#include "tablet.h"
|
#include "tablet.h"
|
||||||
#include "tearing.h"
|
#include "tearing.h"
|
||||||
#include "text-input.h"
|
#include "text-input.h"
|
||||||
|
|
|
||||||
|
|
@ -1,309 +0,0 @@
|
||||||
#include "dwl-ipc-unstable-v2-protocol.h"
|
|
||||||
|
|
||||||
static void dwl_ipc_manager_bind(struct wl_client *client, void *data,
|
|
||||||
uint32_t version, uint32_t id);
|
|
||||||
static void dwl_ipc_manager_destroy(struct wl_resource *resource);
|
|
||||||
static void dwl_ipc_manager_get_output(struct wl_client *client,
|
|
||||||
struct wl_resource *resource,
|
|
||||||
uint32_t id, struct wl_resource *output);
|
|
||||||
static void dwl_ipc_manager_release(struct wl_client *client,
|
|
||||||
struct wl_resource *resource);
|
|
||||||
static void dwl_ipc_output_destroy(struct wl_resource *resource);
|
|
||||||
static void dwl_ipc_output_printstatus(Monitor *monitor);
|
|
||||||
static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output);
|
|
||||||
static void dwl_ipc_output_set_client_tags(struct wl_client *client,
|
|
||||||
struct wl_resource *resource,
|
|
||||||
uint32_t and_tags,
|
|
||||||
uint32_t xor_tags);
|
|
||||||
static void dwl_ipc_output_set_layout(struct wl_client *client,
|
|
||||||
struct wl_resource *resource,
|
|
||||||
uint32_t index);
|
|
||||||
static void dwl_ipc_output_set_tags(struct wl_client *client,
|
|
||||||
struct wl_resource *resource,
|
|
||||||
uint32_t tagmask, uint32_t toggle_tagset);
|
|
||||||
static void dwl_ipc_output_quit(struct wl_client *client,
|
|
||||||
struct wl_resource *resource);
|
|
||||||
static void dwl_ipc_output_dispatch(struct wl_client *client,
|
|
||||||
struct wl_resource *resource,
|
|
||||||
const char *dispatch, const char *arg1,
|
|
||||||
const char *arg2, const char *arg3,
|
|
||||||
const char *arg4, const char *arg5);
|
|
||||||
static void dwl_ipc_output_release(struct wl_client *client,
|
|
||||||
struct wl_resource *resource);
|
|
||||||
|
|
||||||
/* global event handlers */
|
|
||||||
static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {
|
|
||||||
.release = dwl_ipc_manager_release,
|
|
||||||
.get_output = dwl_ipc_manager_get_output};
|
|
||||||
static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {
|
|
||||||
.release = dwl_ipc_output_release,
|
|
||||||
.set_tags = dwl_ipc_output_set_tags,
|
|
||||||
.quit = dwl_ipc_output_quit,
|
|
||||||
.dispatch = dwl_ipc_output_dispatch,
|
|
||||||
.set_layout = dwl_ipc_output_set_layout,
|
|
||||||
.set_client_tags = dwl_ipc_output_set_client_tags};
|
|
||||||
|
|
||||||
void dwl_ipc_manager_bind(struct wl_client *client, void *data,
|
|
||||||
uint32_t version, uint32_t id) {
|
|
||||||
struct wl_resource *manager_resource =
|
|
||||||
wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id);
|
|
||||||
if (!manager_resource) {
|
|
||||||
wl_client_post_no_memory(client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wl_resource_set_implementation(manager_resource,
|
|
||||||
&dwl_manager_implementation, NULL,
|
|
||||||
dwl_ipc_manager_destroy);
|
|
||||||
|
|
||||||
zdwl_ipc_manager_v2_send_tags(manager_resource, LENGTH(tags));
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < LENGTH(layouts); i++)
|
|
||||||
zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_manager_destroy(struct wl_resource *resource) {
|
|
||||||
/* No state to destroy */
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_manager_get_output(struct wl_client *client,
|
|
||||||
struct wl_resource *resource, uint32_t id,
|
|
||||||
struct wl_resource *output) {
|
|
||||||
DwlIpcOutput *ipc_output;
|
|
||||||
struct wlr_output *op = wlr_output_from_resource(output);
|
|
||||||
if (!op)
|
|
||||||
return;
|
|
||||||
Monitor *monitor = op->data;
|
|
||||||
struct wl_resource *output_resource =
|
|
||||||
wl_resource_create(client, &zdwl_ipc_output_v2_interface,
|
|
||||||
wl_resource_get_version(resource), id);
|
|
||||||
if (!output_resource)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ipc_output = ecalloc(1, sizeof(*ipc_output));
|
|
||||||
ipc_output->resource = output_resource;
|
|
||||||
ipc_output->mon = monitor;
|
|
||||||
wl_resource_set_implementation(output_resource, &dwl_output_implementation,
|
|
||||||
ipc_output, dwl_ipc_output_destroy);
|
|
||||||
wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link);
|
|
||||||
dwl_ipc_output_printstatus_to(ipc_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_manager_release(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dwl_ipc_output_destroy(struct wl_resource *resource) {
|
|
||||||
DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource);
|
|
||||||
wl_list_remove(&ipc_output->link);
|
|
||||||
free(ipc_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改IPC输出函数,接受掩码参数
|
|
||||||
void dwl_ipc_output_printstatus(Monitor *monitor) {
|
|
||||||
DwlIpcOutput *ipc_output;
|
|
||||||
wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link)
|
|
||||||
dwl_ipc_output_printstatus_to(ipc_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改主IPC输出函数,根据掩码发送相应事件
|
|
||||||
void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) {
|
|
||||||
Monitor *monitor = ipc_output->mon;
|
|
||||||
Client *c = NULL, *focused = NULL;
|
|
||||||
struct wlr_keyboard *keyboard;
|
|
||||||
xkb_layout_index_t current;
|
|
||||||
int32_t tagmask, state, numclients, focused_client, tag;
|
|
||||||
const char *title, *appid, *symbol;
|
|
||||||
char kb_layout[32];
|
|
||||||
focused = focustop(monitor);
|
|
||||||
zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
|
|
||||||
|
|
||||||
for (tag = 0; tag < LENGTH(tags); tag++) {
|
|
||||||
numclients = state = focused_client = 0;
|
|
||||||
tagmask = 1 << tag;
|
|
||||||
if ((tagmask & monitor->tagset[monitor->seltags]) != 0)
|
|
||||||
state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE;
|
|
||||||
wl_list_for_each(c, &clients, link) {
|
|
||||||
if (c->mon != monitor)
|
|
||||||
continue;
|
|
||||||
if (!(c->tags & tagmask))
|
|
||||||
continue;
|
|
||||||
if (c == focused)
|
|
||||||
focused_client = 1;
|
|
||||||
if (c->isurgent)
|
|
||||||
state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT;
|
|
||||||
numclients++;
|
|
||||||
}
|
|
||||||
zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state,
|
|
||||||
numclients, focused_client);
|
|
||||||
}
|
|
||||||
|
|
||||||
title = focused ? client_get_title(focused) : "";
|
|
||||||
appid = focused ? client_get_appid(focused) : "";
|
|
||||||
|
|
||||||
if (monitor->isoverview) {
|
|
||||||
symbol = overviewlayout.symbol;
|
|
||||||
} else {
|
|
||||||
symbol = monitor->pertag->ltidxs[monitor->pertag->curtag]->symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard = &kb_group->wlr_group->keyboard;
|
|
||||||
current = xkb_state_serialize_layout(keyboard->xkb_state,
|
|
||||||
XKB_STATE_LAYOUT_EFFECTIVE);
|
|
||||||
get_layout_abbr(kb_layout,
|
|
||||||
xkb_keymap_layout_get_name(keyboard->keymap, current));
|
|
||||||
|
|
||||||
zdwl_ipc_output_v2_send_layout(
|
|
||||||
ipc_output->resource,
|
|
||||||
monitor->pertag->ltidxs[monitor->pertag->curtag] - layouts);
|
|
||||||
zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken);
|
|
||||||
zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken);
|
|
||||||
zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, symbol);
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource,
|
|
||||||
focused ? focused->isfullscreen : 0);
|
|
||||||
}
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_floating(ipc_output->resource,
|
|
||||||
focused ? focused->isfloating : 0);
|
|
||||||
}
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_X_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_x(ipc_output->resource,
|
|
||||||
focused ? focused->geom.x : 0);
|
|
||||||
}
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_Y_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_y(ipc_output->resource,
|
|
||||||
focused ? focused->geom.y : 0);
|
|
||||||
}
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_WIDTH_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_width(ipc_output->resource,
|
|
||||||
focused ? focused->geom.width : 0);
|
|
||||||
}
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_HEIGHT_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_height(ipc_output->resource,
|
|
||||||
focused ? focused->geom.height : 0);
|
|
||||||
}
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_LAST_LAYER_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_last_layer(ipc_output->resource,
|
|
||||||
monitor->last_open_surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_KB_LAYOUT_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_kb_layout(ipc_output->resource, kb_layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_KEYMODE_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_keymode(ipc_output->resource, keymode.mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wl_resource_get_version(ipc_output->resource) >=
|
|
||||||
ZDWL_IPC_OUTPUT_V2_SCALEFACTOR_SINCE_VERSION) {
|
|
||||||
zdwl_ipc_output_v2_send_scalefactor(ipc_output->resource,
|
|
||||||
monitor->wlr_output->scale * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
zdwl_ipc_output_v2_send_frame(ipc_output->resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_output_set_client_tags(struct wl_client *client,
|
|
||||||
struct wl_resource *resource,
|
|
||||||
uint32_t and_tags, uint32_t xor_tags) {
|
|
||||||
DwlIpcOutput *ipc_output;
|
|
||||||
Monitor *monitor = NULL;
|
|
||||||
Client *selected_client = NULL;
|
|
||||||
uint32_t newtags = 0;
|
|
||||||
|
|
||||||
ipc_output = wl_resource_get_user_data(resource);
|
|
||||||
if (!ipc_output)
|
|
||||||
return;
|
|
||||||
|
|
||||||
monitor = ipc_output->mon;
|
|
||||||
selected_client = focustop(monitor);
|
|
||||||
if (!selected_client)
|
|
||||||
return;
|
|
||||||
|
|
||||||
newtags = (selected_client->tags & and_tags) ^ xor_tags;
|
|
||||||
if (!newtags)
|
|
||||||
return;
|
|
||||||
|
|
||||||
selected_client->tags = newtags;
|
|
||||||
if (selmon == monitor)
|
|
||||||
focusclient(focustop(monitor), 1);
|
|
||||||
arrange(selmon, false, false);
|
|
||||||
printstatus(IPC_WATCH_ARRANGGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_output_set_layout(struct wl_client *client,
|
|
||||||
struct wl_resource *resource, uint32_t index) {
|
|
||||||
DwlIpcOutput *ipc_output;
|
|
||||||
Monitor *monitor = NULL;
|
|
||||||
|
|
||||||
ipc_output = wl_resource_get_user_data(resource);
|
|
||||||
if (!ipc_output)
|
|
||||||
return;
|
|
||||||
|
|
||||||
monitor = ipc_output->mon;
|
|
||||||
if (index >= LENGTH(layouts))
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
monitor->pertag->ltidxs[monitor->pertag->curtag] = &layouts[index];
|
|
||||||
clear_fullscreen_and_maximized_state(monitor);
|
|
||||||
arrange(monitor, false, false);
|
|
||||||
printstatus(IPC_WATCH_ARRANGGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_output_set_tags(struct wl_client *client,
|
|
||||||
struct wl_resource *resource, uint32_t tagmask,
|
|
||||||
uint32_t toggle_tagset) {
|
|
||||||
DwlIpcOutput *ipc_output;
|
|
||||||
Monitor *monitor = NULL;
|
|
||||||
uint32_t newtags = tagmask & TAGMASK;
|
|
||||||
|
|
||||||
ipc_output = wl_resource_get_user_data(resource);
|
|
||||||
if (!ipc_output)
|
|
||||||
return;
|
|
||||||
monitor = ipc_output->mon;
|
|
||||||
|
|
||||||
view_in_mon(&(Arg){.ui = newtags}, true, monitor, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_output_quit(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
quit(&(Arg){0});
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_output_dispatch(struct wl_client *client,
|
|
||||||
struct wl_resource *resource, const char *dispatch,
|
|
||||||
const char *arg1, const char *arg2,
|
|
||||||
const char *arg3, const char *arg4,
|
|
||||||
const char *arg5) {
|
|
||||||
|
|
||||||
int32_t (*func)(const Arg *);
|
|
||||||
Arg arg;
|
|
||||||
func = parse_func_name((char *)dispatch, &arg, (char *)arg1, (char *)arg2,
|
|
||||||
(char *)arg3, (char *)arg4, (char *)arg5);
|
|
||||||
if (func) {
|
|
||||||
func(&arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.v)
|
|
||||||
free(arg.v);
|
|
||||||
if (arg.v2)
|
|
||||||
free(arg.v2);
|
|
||||||
if (arg.v3)
|
|
||||||
free(arg.v3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dwl_ipc_output_release(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#include "wlr_ext_workspace_v1.h"
|
#include <wlr/types/wlr_ext_workspace_v1.h>
|
||||||
|
|
||||||
#define EXT_WORKSPACE_ENABLE_CAPS \
|
#define EXT_WORKSPACE_ENABLE_CAPS \
|
||||||
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
|
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
|
||||||
|
|
@ -148,7 +148,7 @@ static void add_workspace_by_tag(int32_t tag, Monitor *m) {
|
||||||
wlr_ext_workspace_handle_v1_set_name(workspace->ext_workspace, name);
|
wlr_ext_workspace_handle_v1_set_name(workspace->ext_workspace, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dwl_ext_workspace_printstatus(Monitor *m) {
|
void mango_ext_workspace_printstatus(Monitor *m) {
|
||||||
struct workspace *w;
|
struct workspace *w;
|
||||||
uint32_t tag_status = 0;
|
uint32_t tag_status = 0;
|
||||||
|
|
||||||
|
|
@ -199,7 +199,7 @@ void refresh_monitors_workspaces_status(Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dwl_ext_workspace_printstatus(m);
|
mango_ext_workspace_printstatus(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void workspaces_init() {
|
void workspaces_init() {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ void handle_foreign_maximize_request(struct wl_listener *listener, void *data) {
|
||||||
Client *c = wl_container_of(listener, c, foreign_maximize_request);
|
Client *c = wl_container_of(listener, c, foreign_maximize_request);
|
||||||
struct wlr_foreign_toplevel_handle_v1_maximized_event *event = data;
|
struct wlr_foreign_toplevel_handle_v1_maximized_event *event = data;
|
||||||
|
|
||||||
if (c->swallowing || !c->mon)
|
if (c->swallowdby || !c->mon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c->ismaximizescreen && !event->maximized) {
|
if (c->ismaximizescreen && !event->maximized) {
|
||||||
|
|
@ -30,7 +30,7 @@ void handle_foreign_minimize_request(struct wl_listener *listener, void *data) {
|
||||||
Client *c = wl_container_of(listener, c, foreign_minimize_request);
|
Client *c = wl_container_of(listener, c, foreign_minimize_request);
|
||||||
struct wlr_foreign_toplevel_handle_v1_minimized_event *event = data;
|
struct wlr_foreign_toplevel_handle_v1_minimized_event *event = data;
|
||||||
|
|
||||||
if (c->swallowing || !c->mon)
|
if (c->swallowdby || !c->mon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!c->isminimized && event->minimized) {
|
if (!c->isminimized && event->minimized) {
|
||||||
|
|
@ -55,7 +55,7 @@ void handle_foreign_fullscreen_request(struct wl_listener *listener,
|
||||||
Client *c = wl_container_of(listener, c, foreign_fullscreen_request);
|
Client *c = wl_container_of(listener, c, foreign_fullscreen_request);
|
||||||
struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
|
struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
|
||||||
|
|
||||||
if (c->swallowing || !c->mon)
|
if (c->swallowdby || !c->mon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c->isfullscreen && !event->fullscreen) {
|
if (c->isfullscreen && !event->fullscreen) {
|
||||||
|
|
|
||||||
131
src/ext-protocol/hdr.h
Normal file
131
src/ext-protocol/hdr.h
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
#include <drm_fourcc.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
|
static uint32_t output_formats_8bit[] = {
|
||||||
|
DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, DRM_FORMAT_RGBX8888,
|
||||||
|
DRM_FORMAT_BGRX8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
|
||||||
|
DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_RGB888,
|
||||||
|
DRM_FORMAT_BGR888,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t output_formats_10bit[] = {
|
||||||
|
DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_RGBX1010102,
|
||||||
|
DRM_FORMAT_BGRX1010102, DRM_FORMAT_ARGB2101010, DRM_FORMAT_ABGR2101010,
|
||||||
|
DRM_FORMAT_RGBA1010102, DRM_FORMAT_BGRA1010102,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool output_set_render_format(Monitor *m, uint32_t candidates[],
|
||||||
|
size_t count,
|
||||||
|
struct wlr_output_state *state) {
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
wlr_output_state_set_render_format(state, candidates[i]);
|
||||||
|
if (wlr_output_test_state(m->wlr_output, state))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool output_format_in_candidates(uint32_t format, uint32_t candidates[],
|
||||||
|
size_t count) {
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
if (candidates[i] == format)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum render_bit_depth bit_depth_from_format(uint32_t render_format) {
|
||||||
|
if (output_format_in_candidates(render_format, output_formats_10bit,
|
||||||
|
ARRAY_SIZE(output_formats_10bit)))
|
||||||
|
return MANGO_RENDER_BIT_DEPTH_10;
|
||||||
|
if (output_format_in_candidates(render_format, output_formats_8bit,
|
||||||
|
ARRAY_SIZE(output_formats_8bit)))
|
||||||
|
return MANGO_RENDER_BIT_DEPTH_8;
|
||||||
|
return MANGO_RENDER_BIT_DEPTH_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool output_supports_hdr(const struct wlr_output *output,
|
||||||
|
const char **reason) {
|
||||||
|
const char *r = NULL;
|
||||||
|
if (!(output->supported_primaries & WLR_COLOR_NAMED_PRIMARIES_BT2020))
|
||||||
|
r = "BT2020 primaries not supported";
|
||||||
|
else if (!(output->supported_transfer_functions &
|
||||||
|
WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ))
|
||||||
|
r = "PQ transfer function not supported";
|
||||||
|
else if (!drw->features.output_color_transform)
|
||||||
|
r = "renderer doesn't support output color transforms";
|
||||||
|
if (reason)
|
||||||
|
*reason = r;
|
||||||
|
return !r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_enable_hdr(Monitor *m, struct wlr_output_state *os, bool enabled,
|
||||||
|
bool silent) {
|
||||||
|
if (enabled && !output_supports_hdr(m->wlr_output, NULL))
|
||||||
|
enabled = false;
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
if (m->wlr_output->supported_primaries ||
|
||||||
|
m->wlr_output->supported_transfer_functions) {
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_DEBUG, "Disabling HDR on output %s",
|
||||||
|
m->wlr_output->name);
|
||||||
|
wlr_output_state_set_image_description(os, NULL);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_DEBUG, "Enabling HDR on output %s", m->wlr_output->name);
|
||||||
|
struct wlr_output_image_description desc = {
|
||||||
|
.primaries = WLR_COLOR_NAMED_PRIMARIES_BT2020,
|
||||||
|
.transfer_function = WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ,
|
||||||
|
};
|
||||||
|
wlr_output_state_set_image_description(os, &desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_state_setup_hdr(Monitor *m, bool silent,
|
||||||
|
struct wlr_output_state *state) {
|
||||||
|
uint32_t render_format = m->wlr_output->render_format;
|
||||||
|
const char *unsupported_reason = NULL;
|
||||||
|
bool hdr_supported =
|
||||||
|
output_supports_hdr(m->wlr_output, &unsupported_reason);
|
||||||
|
bool hdr_succeeded = false;
|
||||||
|
|
||||||
|
enum render_bit_depth depth = config.hdr_depth;
|
||||||
|
if (depth == MANGO_RENDER_BIT_DEPTH_DEFAULT)
|
||||||
|
depth = bit_depth_from_format(render_format);
|
||||||
|
|
||||||
|
if (!hdr_supported && depth == MANGO_RENDER_BIT_DEPTH_10) {
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_INFO, "Cannot enable HDR on output %s: %s",
|
||||||
|
m->wlr_output->name, unsupported_reason);
|
||||||
|
depth = MANGO_RENDER_BIT_DEPTH_8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth == MANGO_RENDER_BIT_DEPTH_10 &&
|
||||||
|
bit_depth_from_format(render_format) == depth) {
|
||||||
|
hdr_succeeded = true; // 上次已经成功设置10位,直接复用
|
||||||
|
} else if (depth == MANGO_RENDER_BIT_DEPTH_10) {
|
||||||
|
hdr_succeeded = output_set_render_format(
|
||||||
|
m, output_formats_10bit, ARRAY_SIZE(output_formats_10bit), state);
|
||||||
|
if (!hdr_succeeded) {
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_INFO,
|
||||||
|
"No 10 bit color formats supported, HDR disabled.");
|
||||||
|
if (!output_set_render_format(m, output_formats_8bit,
|
||||||
|
ARRAY_SIZE(output_formats_8bit),
|
||||||
|
state))
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_ERROR, "No 8 bit color formats either!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 明确要求8位或自动降级
|
||||||
|
if (!output_set_render_format(m, output_formats_8bit,
|
||||||
|
ARRAY_SIZE(output_formats_8bit), state))
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_ERROR, "No 8 bit color formats supported!");
|
||||||
|
}
|
||||||
|
|
||||||
|
output_enable_hdr(m, state, hdr_succeeded, silent);
|
||||||
|
}
|
||||||
|
|
@ -281,7 +281,7 @@ void tablettoolmotion(struct TabletTool *tool, bool change_x, bool change_y,
|
||||||
if (config.sloppyfocus)
|
if (config.sloppyfocus)
|
||||||
selmon = xytomon(cursor->x, cursor->y);
|
selmon = xytomon(cursor->x, cursor->y);
|
||||||
|
|
||||||
xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
|
xytonode(cursor->x, cursor->y, &surface, &c, NULL, NULL, &sx, &sy);
|
||||||
if (cursor_mode == CurPressed && !seat->drag &&
|
if (cursor_mode == CurPressed && !seat->drag &&
|
||||||
surface != seat->pointer_state.focused_surface &&
|
surface != seat->pointer_state.focused_surface &&
|
||||||
toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w,
|
toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <stdbool.h>
|
||||||
#include <wlr/types/wlr_tearing_control_v1.h>
|
#include <wlr/types/wlr_tearing_control_v1.h>
|
||||||
|
|
||||||
struct tearing_controller {
|
struct tearing_controller {
|
||||||
|
|
@ -64,6 +65,9 @@ bool check_tearing_frame_allow(Monitor *m) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!selmon)
|
||||||
|
return false;
|
||||||
|
|
||||||
Client *c = selmon->sel;
|
Client *c = selmon->sel;
|
||||||
|
|
||||||
/* tearing is only allowed for the output with the active client */
|
/* tearing is only allowed for the output with the active client */
|
||||||
|
|
@ -94,79 +98,3 @@ bool check_tearing_frame_allow(Monitor *m) {
|
||||||
/* honor tearing as requested by action */
|
/* honor tearing as requested by action */
|
||||||
return c->force_tearing == STATE_ENABLED;
|
return c->force_tearing == STATE_ENABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool custom_wlr_scene_output_commit(struct wlr_scene_output *scene_output,
|
|
||||||
struct wlr_output_state *state) {
|
|
||||||
struct wlr_output *wlr_output = scene_output->output;
|
|
||||||
Monitor *m = wlr_output->data;
|
|
||||||
|
|
||||||
// 检查是否需要帧
|
|
||||||
if (!wlr_scene_output_needs_frame(scene_output)) {
|
|
||||||
wlr_log(WLR_DEBUG, "No frame needed for output %s", wlr_output->name);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建输出状态
|
|
||||||
if (!wlr_scene_output_build_state(scene_output, state, NULL)) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to build output state for %s",
|
|
||||||
wlr_output->name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 测试撕裂翻页
|
|
||||||
if (state->tearing_page_flip) {
|
|
||||||
if (!wlr_output_test_state(wlr_output, state)) {
|
|
||||||
state->tearing_page_flip = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 尝试提交
|
|
||||||
bool committed = wlr_output_commit_state(wlr_output, state);
|
|
||||||
|
|
||||||
// 如果启用撕裂翻页但提交失败,重试禁用撕裂翻页
|
|
||||||
if (!committed && state->tearing_page_flip) {
|
|
||||||
wlr_log(WLR_DEBUG, "Retrying commit without tearing for %s",
|
|
||||||
wlr_output->name);
|
|
||||||
state->tearing_page_flip = false;
|
|
||||||
committed = wlr_output_commit_state(wlr_output, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理状态清理
|
|
||||||
if (committed) {
|
|
||||||
wlr_log(WLR_DEBUG, "Successfully committed output %s",
|
|
||||||
wlr_output->name);
|
|
||||||
if (state == &m->pending) {
|
|
||||||
wlr_output_state_finish(&m->pending);
|
|
||||||
wlr_output_state_init(&m->pending);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to commit output %s", wlr_output->name);
|
|
||||||
// 即使提交失败,也清理状态避免积累
|
|
||||||
if (state == &m->pending) {
|
|
||||||
wlr_output_state_finish(&m->pending);
|
|
||||||
wlr_output_state_init(&m->pending);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void apply_tear_state(Monitor *m) {
|
|
||||||
if (wlr_scene_output_needs_frame(m->scene_output)) {
|
|
||||||
wlr_output_state_init(&m->pending);
|
|
||||||
if (wlr_scene_output_build_state(m->scene_output, &m->pending, NULL)) {
|
|
||||||
struct wlr_output_state *pending = &m->pending;
|
|
||||||
pending->tearing_page_flip = true;
|
|
||||||
|
|
||||||
if (!custom_wlr_scene_output_commit(m->scene_output, pending)) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to commit output %s",
|
|
||||||
m->scene_output->output->name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to build state for output %s",
|
|
||||||
m->scene_output->output->name);
|
|
||||||
wlr_output_state_finish(&m->pending);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include <wlr/types/wlr_input_method_v2.h>
|
#include <wlr/types/wlr_input_method_v2.h>
|
||||||
#include <wlr/types/wlr_text_input_v3.h>
|
#include <wlr/types/wlr_text_input_v3.h>
|
||||||
|
|
||||||
struct dwl_input_method_relay {
|
struct mango_input_method_relay {
|
||||||
struct wl_list text_inputs;
|
struct wl_list text_inputs;
|
||||||
struct wlr_input_method_v2 *input_method;
|
struct wlr_input_method_v2 *input_method;
|
||||||
struct wlr_surface *focused_surface;
|
struct wlr_surface *focused_surface;
|
||||||
|
|
@ -26,11 +26,12 @@ struct dwl_input_method_relay {
|
||||||
struct wl_listener focused_surface_destroy;
|
struct wl_listener focused_surface_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dwl_input_method_popup {
|
struct mango_input_method_popup {
|
||||||
|
uint32_t type; // must at first in struct
|
||||||
struct wlr_input_popup_surface_v2 *popup_surface;
|
struct wlr_input_popup_surface_v2 *popup_surface;
|
||||||
struct wlr_scene_tree *tree;
|
struct wlr_scene_tree *tree;
|
||||||
struct wlr_scene_tree *scene_surface;
|
struct wlr_scene_tree *scene_surface;
|
||||||
struct dwl_input_method_relay *relay;
|
struct mango_input_method_relay *relay;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
|
|
@ -38,7 +39,7 @@ struct dwl_input_method_popup {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct text_input {
|
struct text_input {
|
||||||
struct dwl_input_method_relay *relay;
|
struct mango_input_method_relay *relay;
|
||||||
struct wlr_text_input_v3 *input;
|
struct wlr_text_input_v3 *input;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
|
||||||
|
|
@ -50,20 +51,20 @@ struct text_input {
|
||||||
|
|
||||||
struct wlr_input_method_manager_v2 *input_method_manager;
|
struct wlr_input_method_manager_v2 *input_method_manager;
|
||||||
struct wlr_text_input_manager_v3 *text_input_manager;
|
struct wlr_text_input_manager_v3 *text_input_manager;
|
||||||
struct dwl_input_method_relay *dwl_input_method_relay;
|
struct mango_input_method_relay *mango_input_method_relay;
|
||||||
|
|
||||||
/*-------------------封装给外部调用-------------------------------*/
|
/*-------------------封装给外部调用-------------------------------*/
|
||||||
bool dwl_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
bool mango_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
||||||
struct wlr_keyboard_key_event *event);
|
struct wlr_keyboard_key_event *event);
|
||||||
|
|
||||||
bool dwl_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard);
|
bool mango_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard);
|
||||||
|
|
||||||
struct dwl_input_method_relay *dwl_im_relay_create();
|
struct mango_input_method_relay *mango_im_relay_create();
|
||||||
|
|
||||||
void dwl_im_relay_finish(struct dwl_input_method_relay *relay);
|
void mango_im_relay_finish(struct mango_input_method_relay *relay);
|
||||||
|
|
||||||
void dwl_im_relay_set_focus(struct dwl_input_method_relay *relay,
|
void mango_im_relay_set_focus(struct mango_input_method_relay *relay,
|
||||||
struct wlr_surface *surface);
|
struct wlr_surface *surface);
|
||||||
/*----------------------------------------------------------*/
|
/*----------------------------------------------------------*/
|
||||||
|
|
||||||
/*------------------协议内部代码------------------------------*/
|
/*------------------协议内部代码------------------------------*/
|
||||||
|
|
@ -97,7 +98,7 @@ is_keyboard_emulated_by_input_method(struct wlr_keyboard *keyboard,
|
||||||
static struct wlr_input_method_keyboard_grab_v2 *
|
static struct wlr_input_method_keyboard_grab_v2 *
|
||||||
get_keyboard_grab(KeyboardGroup *keyboard) {
|
get_keyboard_grab(KeyboardGroup *keyboard) {
|
||||||
struct wlr_input_method_v2 *input_method =
|
struct wlr_input_method_v2 *input_method =
|
||||||
dwl_input_method_relay->input_method;
|
mango_input_method_relay->input_method;
|
||||||
if (!input_method || !input_method->keyboard_grab) {
|
if (!input_method || !input_method->keyboard_grab) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +115,7 @@ get_keyboard_grab(KeyboardGroup *keyboard) {
|
||||||
return input_method->keyboard_grab;
|
return input_method->keyboard_grab;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dwl_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard) {
|
bool mango_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard) {
|
||||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||||
get_keyboard_grab(keyboard);
|
get_keyboard_grab(keyboard);
|
||||||
|
|
||||||
|
|
@ -132,8 +133,8 @@ bool dwl_im_keyboard_grab_forward_modifiers(KeyboardGroup *keyboard) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dwl_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
bool mango_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
||||||
struct wlr_keyboard_key_event *event) {
|
struct wlr_keyboard_key_event *event) {
|
||||||
|
|
||||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||||
get_keyboard_grab(keyboard);
|
get_keyboard_grab(keyboard);
|
||||||
|
|
@ -149,7 +150,7 @@ bool dwl_im_keyboard_grab_forward_key(KeyboardGroup *keyboard,
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct text_input *
|
static struct text_input *
|
||||||
get_active_text_input(struct dwl_input_method_relay *relay) {
|
get_active_text_input(struct mango_input_method_relay *relay) {
|
||||||
struct text_input *text_input;
|
struct text_input *text_input;
|
||||||
|
|
||||||
if (!relay->input_method) {
|
if (!relay->input_method) {
|
||||||
|
|
@ -164,7 +165,7 @@ get_active_text_input(struct dwl_input_method_relay *relay) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_active_text_input(struct dwl_input_method_relay *relay) {
|
static void update_active_text_input(struct mango_input_method_relay *relay) {
|
||||||
struct text_input *active_text_input = get_active_text_input(relay);
|
struct text_input *active_text_input = get_active_text_input(relay);
|
||||||
|
|
||||||
if (relay->input_method && relay->active_text_input != active_text_input) {
|
if (relay->input_method && relay->active_text_input != active_text_input) {
|
||||||
|
|
@ -180,7 +181,7 @@ static void update_active_text_input(struct dwl_input_method_relay *relay) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_text_inputs_focused_surface(struct dwl_input_method_relay *relay) {
|
update_text_inputs_focused_surface(struct mango_input_method_relay *relay) {
|
||||||
struct text_input *text_input;
|
struct text_input *text_input;
|
||||||
wl_list_for_each(text_input, &relay->text_inputs, link) {
|
wl_list_for_each(text_input, &relay->text_inputs, link) {
|
||||||
struct wlr_text_input_v3 *input = text_input->input;
|
struct wlr_text_input_v3 *input = text_input->input;
|
||||||
|
|
@ -206,8 +207,8 @@ update_text_inputs_focused_surface(struct dwl_input_method_relay *relay) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_popup_position(struct dwl_input_method_popup *popup) {
|
static void update_popup_position(struct mango_input_method_popup *popup) {
|
||||||
struct dwl_input_method_relay *relay = popup->relay;
|
struct mango_input_method_relay *relay = popup->relay;
|
||||||
struct text_input *text_input = relay->active_text_input;
|
struct text_input *text_input = relay->active_text_input;
|
||||||
struct wlr_box cursor_rect;
|
struct wlr_box cursor_rect;
|
||||||
struct wlr_xdg_surface *xdg_surface;
|
struct wlr_xdg_surface *xdg_surface;
|
||||||
|
|
@ -281,8 +282,8 @@ static void update_popup_position(struct dwl_input_method_popup *popup) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_popups_position(struct dwl_input_method_relay *relay) {
|
static void update_popups_position(struct mango_input_method_relay *relay) {
|
||||||
struct dwl_input_method_popup *popup;
|
struct mango_input_method_popup *popup;
|
||||||
wl_list_for_each(popup, &relay->popups, link) {
|
wl_list_for_each(popup, &relay->popups, link) {
|
||||||
update_popup_position(popup);
|
update_popup_position(popup);
|
||||||
}
|
}
|
||||||
|
|
@ -290,11 +291,10 @@ static void update_popups_position(struct dwl_input_method_relay *relay) {
|
||||||
|
|
||||||
static void handle_input_method_commit(struct wl_listener *listener,
|
static void handle_input_method_commit(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_commit);
|
wl_container_of(listener, relay, input_method_commit);
|
||||||
struct wlr_input_method_v2 *input_method = data;
|
|
||||||
struct text_input *text_input;
|
struct text_input *text_input;
|
||||||
assert(relay->input_method == input_method);
|
struct wlr_input_method_v2 *input_method = relay->input_method;
|
||||||
|
|
||||||
text_input = relay->active_text_input;
|
text_input = relay->active_text_input;
|
||||||
if (!text_input) {
|
if (!text_input) {
|
||||||
|
|
@ -322,9 +322,10 @@ static void handle_input_method_commit(struct wl_listener *listener,
|
||||||
|
|
||||||
static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, keyboard_grab_destroy);
|
wl_container_of(listener, relay, keyboard_grab_destroy);
|
||||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||||
|
relay->input_method->keyboard_grab;
|
||||||
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
||||||
|
|
||||||
if (keyboard_grab->keyboard) {
|
if (keyboard_grab->keyboard) {
|
||||||
|
|
@ -335,7 +336,7 @@ static void handle_keyboard_grab_destroy(struct wl_listener *listener,
|
||||||
|
|
||||||
static void handle_input_method_grab_keyboard(struct wl_listener *listener,
|
static void handle_input_method_grab_keyboard(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_grab_keyboard);
|
wl_container_of(listener, relay, input_method_grab_keyboard);
|
||||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||||
|
|
||||||
|
|
@ -354,9 +355,8 @@ static void handle_input_method_grab_keyboard(struct wl_listener *listener,
|
||||||
|
|
||||||
static void handle_input_method_destroy(struct wl_listener *listener,
|
static void handle_input_method_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_destroy);
|
wl_container_of(listener, relay, input_method_destroy);
|
||||||
assert(relay->input_method == data);
|
|
||||||
wl_list_remove(&relay->input_method_commit.link);
|
wl_list_remove(&relay->input_method_commit.link);
|
||||||
wl_list_remove(&relay->input_method_grab_keyboard.link);
|
wl_list_remove(&relay->input_method_grab_keyboard.link);
|
||||||
wl_list_remove(&relay->input_method_new_popup_surface.link);
|
wl_list_remove(&relay->input_method_new_popup_surface.link);
|
||||||
|
|
@ -369,7 +369,7 @@ static void handle_input_method_destroy(struct wl_listener *listener,
|
||||||
|
|
||||||
static void handle_popup_surface_destroy(struct wl_listener *listener,
|
static void handle_popup_surface_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_popup *popup =
|
struct mango_input_method_popup *popup =
|
||||||
wl_container_of(listener, popup, destroy);
|
wl_container_of(listener, popup, destroy);
|
||||||
wlr_scene_node_destroy(&popup->tree->node);
|
wlr_scene_node_destroy(&popup->tree->node);
|
||||||
wl_list_remove(&popup->destroy.link);
|
wl_list_remove(&popup->destroy.link);
|
||||||
|
|
@ -380,18 +380,18 @@ static void handle_popup_surface_destroy(struct wl_listener *listener,
|
||||||
|
|
||||||
static void handle_popup_surface_commit(struct wl_listener *listener,
|
static void handle_popup_surface_commit(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_popup *popup =
|
struct mango_input_method_popup *popup =
|
||||||
wl_container_of(listener, popup, commit);
|
wl_container_of(listener, popup, commit);
|
||||||
update_popup_position(popup);
|
update_popup_position(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, input_method_new_popup_surface);
|
wl_container_of(listener, relay, input_method_new_popup_surface);
|
||||||
|
|
||||||
struct dwl_input_method_popup *popup =
|
struct mango_input_method_popup *popup =
|
||||||
ecalloc(1, sizeof(struct dwl_input_method_popup));
|
ecalloc(1, sizeof(struct mango_input_method_popup));
|
||||||
popup->popup_surface = data;
|
popup->popup_surface = data;
|
||||||
popup->relay = relay;
|
popup->relay = relay;
|
||||||
|
|
||||||
|
|
@ -405,6 +405,8 @@ static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
||||||
popup->tree = wlr_scene_tree_create(layers[LyrIMPopup]);
|
popup->tree = wlr_scene_tree_create(layers[LyrIMPopup]);
|
||||||
popup->scene_surface = wlr_scene_subsurface_tree_create(
|
popup->scene_surface = wlr_scene_subsurface_tree_create(
|
||||||
popup->tree, popup->popup_surface->surface);
|
popup->tree, popup->popup_surface->surface);
|
||||||
|
|
||||||
|
popup->type = XdgImPopup;
|
||||||
popup->scene_surface->node.data = popup;
|
popup->scene_surface->node.data = popup;
|
||||||
|
|
||||||
wl_list_insert(&relay->popups, &popup->link);
|
wl_list_insert(&relay->popups, &popup->link);
|
||||||
|
|
@ -413,7 +415,7 @@ static void handle_input_method_new_popup_surface(struct wl_listener *listener,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_new_input_method(struct wl_listener *listener, void *data) {
|
static void handle_new_input_method(struct wl_listener *listener, void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, new_input_method);
|
wl_container_of(listener, relay, new_input_method);
|
||||||
struct wlr_input_method_v2 *input_method = data;
|
struct wlr_input_method_v2 *input_method = data;
|
||||||
if (seat != input_method->seat) {
|
if (seat != input_method->seat) {
|
||||||
|
|
@ -449,7 +451,7 @@ static void handle_new_input_method(struct wl_listener *listener, void *data) {
|
||||||
update_active_text_input(relay);
|
update_active_text_input(relay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_state_to_input_method(struct dwl_input_method_relay *relay) {
|
static void send_state_to_input_method(struct mango_input_method_relay *relay) {
|
||||||
|
|
||||||
struct wlr_input_method_v2 *input_method = relay->input_method;
|
struct wlr_input_method_v2 *input_method = relay->input_method;
|
||||||
struct wlr_text_input_v3 *input = relay->active_text_input->input;
|
struct wlr_text_input_v3 *input = relay->active_text_input->input;
|
||||||
|
|
@ -474,7 +476,7 @@ static void send_state_to_input_method(struct dwl_input_method_relay *relay) {
|
||||||
static void handle_text_input_enable(struct wl_listener *listener, void *data) {
|
static void handle_text_input_enable(struct wl_listener *listener, void *data) {
|
||||||
struct text_input *text_input =
|
struct text_input *text_input =
|
||||||
wl_container_of(listener, text_input, enable);
|
wl_container_of(listener, text_input, enable);
|
||||||
struct dwl_input_method_relay *relay = text_input->relay;
|
struct mango_input_method_relay *relay = text_input->relay;
|
||||||
|
|
||||||
update_active_text_input(relay);
|
update_active_text_input(relay);
|
||||||
if (relay->active_text_input == text_input) {
|
if (relay->active_text_input == text_input) {
|
||||||
|
|
@ -495,7 +497,7 @@ static void handle_text_input_disable(struct wl_listener *listener,
|
||||||
static void handle_text_input_commit(struct wl_listener *listener, void *data) {
|
static void handle_text_input_commit(struct wl_listener *listener, void *data) {
|
||||||
struct text_input *text_input =
|
struct text_input *text_input =
|
||||||
wl_container_of(listener, text_input, commit);
|
wl_container_of(listener, text_input, commit);
|
||||||
struct dwl_input_method_relay *relay = text_input->relay;
|
struct mango_input_method_relay *relay = text_input->relay;
|
||||||
|
|
||||||
if (relay->active_text_input == text_input) {
|
if (relay->active_text_input == text_input) {
|
||||||
update_popups_position(relay);
|
update_popups_position(relay);
|
||||||
|
|
@ -517,7 +519,7 @@ static void handle_text_input_destroy(struct wl_listener *listener,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_new_text_input(struct wl_listener *listener, void *data) {
|
static void handle_new_text_input(struct wl_listener *listener, void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, new_text_input);
|
wl_container_of(listener, relay, new_text_input);
|
||||||
struct wlr_text_input_v3 *wlr_text_input = data;
|
struct wlr_text_input_v3 *wlr_text_input = data;
|
||||||
struct text_input *text_input = ecalloc(1, sizeof(struct text_input));
|
struct text_input *text_input = ecalloc(1, sizeof(struct text_input));
|
||||||
|
|
@ -547,26 +549,26 @@ static void handle_new_text_input(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
static void handle_focused_surface_destroy(struct wl_listener *listener,
|
static void handle_focused_surface_destroy(struct wl_listener *listener,
|
||||||
void *data) {
|
void *data) {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, focused_surface_destroy);
|
wl_container_of(listener, relay, focused_surface_destroy);
|
||||||
assert(relay->focused_surface == data);
|
assert(relay->focused_surface == data);
|
||||||
|
|
||||||
dwl_im_relay_set_focus(relay, NULL);
|
mango_im_relay_set_focus(relay, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dwl_input_method_relay *dwl_im_relay_create() {
|
struct mango_input_method_relay *mango_im_relay_create() {
|
||||||
struct dwl_input_method_relay *relay =
|
struct mango_input_method_relay *relay =
|
||||||
ecalloc(1, sizeof(struct dwl_input_method_relay));
|
ecalloc(1, sizeof(struct mango_input_method_relay));
|
||||||
wl_list_init(&relay->text_inputs);
|
wl_list_init(&relay->text_inputs);
|
||||||
wl_list_init(&relay->popups);
|
wl_list_init(&relay->popups);
|
||||||
relay->popup_tree = wlr_scene_tree_create(&scene->tree);
|
relay->popup_tree = wlr_scene_tree_create(&scene->tree);
|
||||||
|
|
||||||
relay->new_text_input.notify = handle_new_text_input;
|
relay->new_text_input.notify = handle_new_text_input;
|
||||||
wl_signal_add(&text_input_manager->events.text_input,
|
wl_signal_add(&text_input_manager->events.new_text_input,
|
||||||
&relay->new_text_input);
|
&relay->new_text_input);
|
||||||
|
|
||||||
relay->new_input_method.notify = handle_new_input_method;
|
relay->new_input_method.notify = handle_new_input_method;
|
||||||
wl_signal_add(&input_method_manager->events.input_method,
|
wl_signal_add(&input_method_manager->events.new_input_method,
|
||||||
&relay->new_input_method);
|
&relay->new_input_method);
|
||||||
|
|
||||||
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
||||||
|
|
@ -574,14 +576,14 @@ struct dwl_input_method_relay *dwl_im_relay_create() {
|
||||||
return relay;
|
return relay;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dwl_im_relay_finish(struct dwl_input_method_relay *relay) {
|
void mango_im_relay_finish(struct mango_input_method_relay *relay) {
|
||||||
wl_list_remove(&relay->new_text_input.link);
|
wl_list_remove(&relay->new_text_input.link);
|
||||||
wl_list_remove(&relay->new_input_method.link);
|
wl_list_remove(&relay->new_input_method.link);
|
||||||
free(relay);
|
free(relay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dwl_im_relay_set_focus(struct dwl_input_method_relay *relay,
|
void mango_im_relay_set_focus(struct mango_input_method_relay *relay,
|
||||||
struct wlr_surface *surface) {
|
struct wlr_surface *surface) {
|
||||||
if (relay->focused_surface == surface) {
|
if (relay->focused_surface == surface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,975 +0,0 @@
|
||||||
#include "wlr_ext_workspace_v1.h"
|
|
||||||
#include "ext-workspace-v1-protocol.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <wlr/types/wlr_output.h>
|
|
||||||
|
|
||||||
#define EXT_WORKSPACE_V1_VERSION 1
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_group_output {
|
|
||||||
struct wlr_output *output;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
|
||||||
struct wl_listener output_bind;
|
|
||||||
struct wl_listener output_destroy;
|
|
||||||
struct wl_list link;
|
|
||||||
};
|
|
||||||
|
|
||||||
// These structs wrap wl_resource of each interface to access the request queue
|
|
||||||
// (wlr_ext_workspace_manager_v1_resource.requests) assigned per manager
|
|
||||||
// resource
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource {
|
|
||||||
struct wl_resource *resource;
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager;
|
|
||||||
struct wl_list requests; // wlr_ext_workspace_v1_request.link
|
|
||||||
struct wl_list workspace_resources; // wlr_ext_workspace_v1_resource.link
|
|
||||||
struct wl_list group_resources; // wlr_ext_workspace_group_v1_resource.link
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1.resources
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource {
|
|
||||||
struct wl_resource *resource;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager;
|
|
||||||
struct wl_list link; // wlr_ext_workspace_group_v1.resources
|
|
||||||
struct wl_list
|
|
||||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.group_resources
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource {
|
|
||||||
struct wl_resource *resource;
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager;
|
|
||||||
struct wl_list link; // wlr_ext_workspace_v1.resources
|
|
||||||
struct wl_list
|
|
||||||
manager_resource_link; // wlr_ext_workspace_manager_v1_resource.workspace_resources
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct ext_workspace_group_handle_v1_interface group_impl;
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_group_v1_resource *
|
|
||||||
group_resource_from_resource(struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(
|
|
||||||
resource, &ext_workspace_group_handle_v1_interface, &group_impl));
|
|
||||||
return wl_resource_get_user_data(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_handle_v1_interface workspace_impl;
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_resource *
|
|
||||||
workspace_resource_from_resource(struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(resource, &ext_workspace_handle_v1_interface,
|
|
||||||
&workspace_impl));
|
|
||||||
return wl_resource_get_user_data(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_manager_v1_interface manager_impl;
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_manager_v1_resource *
|
|
||||||
manager_resource_from_resource(struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(
|
|
||||||
resource, &ext_workspace_manager_v1_interface, &manager_impl));
|
|
||||||
return wl_resource_get_user_data(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_handle_destroy(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_handle_activate(struct wl_client *client,
|
|
||||||
struct wl_resource *workspace_resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(workspace_resource);
|
|
||||||
if (!workspace_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(workspace_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE;
|
|
||||||
req->activate.workspace = workspace_res->workspace;
|
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
workspace_handle_deactivate(struct wl_client *client,
|
|
||||||
struct wl_resource *workspace_resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(workspace_resource);
|
|
||||||
if (!workspace_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(workspace_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE;
|
|
||||||
req->deactivate.workspace = workspace_res->workspace;
|
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_handle_assign(struct wl_client *client,
|
|
||||||
struct wl_resource *workspace_resource,
|
|
||||||
struct wl_resource *group_resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(workspace_resource);
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
group_resource_from_resource(group_resource);
|
|
||||||
if (!workspace_res || !group_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(workspace_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN;
|
|
||||||
req->assign.group = group_res->group;
|
|
||||||
req->assign.workspace = workspace_res->workspace;
|
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_handle_remove(struct wl_client *client,
|
|
||||||
struct wl_resource *workspace_resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(workspace_resource);
|
|
||||||
if (!workspace_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(workspace_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE;
|
|
||||||
req->remove.workspace = workspace_res->workspace;
|
|
||||||
wl_list_insert(workspace_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_handle_v1_interface workspace_impl = {
|
|
||||||
.destroy = workspace_handle_destroy,
|
|
||||||
.activate = workspace_handle_activate,
|
|
||||||
.deactivate = workspace_handle_deactivate,
|
|
||||||
.assign = workspace_handle_assign,
|
|
||||||
.remove = workspace_handle_remove,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void group_handle_create_workspace(struct wl_client *client,
|
|
||||||
struct wl_resource *group_resource,
|
|
||||||
const char *name) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
group_resource_from_resource(group_resource);
|
|
||||||
if (!group_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request *req = calloc(1, sizeof(*req));
|
|
||||||
if (!req) {
|
|
||||||
wl_resource_post_no_memory(group_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->create_workspace.name = strdup(name);
|
|
||||||
if (!req->create_workspace.name) {
|
|
||||||
free(req);
|
|
||||||
wl_resource_post_no_memory(group_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->type = WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE;
|
|
||||||
req->create_workspace.group = group_res->group;
|
|
||||||
wl_list_insert(group_res->manager->requests.prev, &req->link);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void group_handle_destroy(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_group_handle_v1_interface group_impl = {
|
|
||||||
.create_workspace = group_handle_create_workspace,
|
|
||||||
.destroy = group_handle_destroy,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void destroy_workspace_resource(
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res) {
|
|
||||||
wl_list_remove(&workspace_res->link);
|
|
||||||
wl_list_remove(&workspace_res->manager_resource_link);
|
|
||||||
wl_resource_set_user_data(workspace_res->resource, NULL);
|
|
||||||
free(workspace_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_resource_destroy(struct wl_resource *resource) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
workspace_resource_from_resource(resource);
|
|
||||||
if (workspace_res) {
|
|
||||||
destroy_workspace_resource(workspace_res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_resource *create_workspace_resource(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
calloc(1, sizeof(*workspace_res));
|
|
||||||
if (!workspace_res) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_client *client = wl_resource_get_client(manager_res->resource);
|
|
||||||
workspace_res->resource =
|
|
||||||
wl_resource_create(client, &ext_workspace_handle_v1_interface,
|
|
||||||
wl_resource_get_version(manager_res->resource), 0);
|
|
||||||
if (!workspace_res->resource) {
|
|
||||||
free(workspace_res);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
wl_resource_set_implementation(workspace_res->resource, &workspace_impl,
|
|
||||||
workspace_res, workspace_resource_destroy);
|
|
||||||
|
|
||||||
workspace_res->workspace = workspace;
|
|
||||||
workspace_res->manager = manager_res;
|
|
||||||
wl_list_insert(&workspace->resources, &workspace_res->link);
|
|
||||||
wl_list_insert(&manager_res->workspace_resources,
|
|
||||||
&workspace_res->manager_resource_link);
|
|
||||||
|
|
||||||
return workspace_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_group_resource(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
|
||||||
wl_list_remove(&group_res->link);
|
|
||||||
wl_list_remove(&group_res->manager_resource_link);
|
|
||||||
wl_resource_set_user_data(group_res->resource, NULL);
|
|
||||||
free(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void group_handle_resource_destroy(struct wl_resource *resource) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
group_resource_from_resource(resource);
|
|
||||||
if (group_res) {
|
|
||||||
destroy_group_resource(group_res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_group_v1_resource *create_group_resource(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
calloc(1, sizeof(*group_res));
|
|
||||||
if (!group_res) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_client *client = wl_resource_get_client(manager_res->resource);
|
|
||||||
uint32_t version = wl_resource_get_version(manager_res->resource);
|
|
||||||
group_res->resource = wl_resource_create(
|
|
||||||
client, &ext_workspace_group_handle_v1_interface, version, 0);
|
|
||||||
if (group_res->resource == NULL) {
|
|
||||||
free(group_res);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
wl_resource_set_implementation(group_res->resource, &group_impl, group_res,
|
|
||||||
group_handle_resource_destroy);
|
|
||||||
|
|
||||||
group_res->group = group;
|
|
||||||
group_res->manager = manager_res;
|
|
||||||
wl_list_insert(&group->resources, &group_res->link);
|
|
||||||
wl_list_insert(&manager_res->group_resources,
|
|
||||||
&group_res->manager_resource_link);
|
|
||||||
|
|
||||||
return group_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_requests(struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
|
||||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
|
||||||
if (req->type == WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE) {
|
|
||||||
free(req->create_workspace.name);
|
|
||||||
}
|
|
||||||
wl_list_remove(&req->link);
|
|
||||||
free(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clear_requests_by(struct wlr_ext_workspace_manager_v1_resource *manager_res,
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace) {
|
|
||||||
struct wlr_ext_workspace_v1_request *req, *tmp;
|
|
||||||
wl_list_for_each_safe(req, tmp, &manager_res->requests, link) {
|
|
||||||
switch (req->type) {
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE:
|
|
||||||
if (group && req->create_workspace.group == group) {
|
|
||||||
req->create_workspace.group = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE:
|
|
||||||
if (workspace && req->activate.workspace == workspace) {
|
|
||||||
req->activate.workspace = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE:
|
|
||||||
if (workspace && req->deactivate.workspace == workspace) {
|
|
||||||
req->deactivate.workspace = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN:
|
|
||||||
if (workspace && req->assign.workspace == workspace) {
|
|
||||||
req->assign.workspace = NULL;
|
|
||||||
}
|
|
||||||
if (group && req->assign.group == group) {
|
|
||||||
req->assign.group = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE:
|
|
||||||
if (workspace && req->remove.workspace == workspace) {
|
|
||||||
req->remove.workspace = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_handle_commit(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
|
||||||
manager_resource_from_resource(resource);
|
|
||||||
if (!manager_res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_commit_event commit_event = {
|
|
||||||
.requests = &manager_res->requests,
|
|
||||||
};
|
|
||||||
wl_signal_emit_mutable(&manager_res->manager->events.commit, &commit_event);
|
|
||||||
destroy_requests(manager_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_idle(void *data) {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
|
||||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
|
||||||
}
|
|
||||||
manager->idle_source = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
manager_schedule_done(struct wlr_ext_workspace_manager_v1 *manager) {
|
|
||||||
if (!manager->idle_source) {
|
|
||||||
manager->idle_source =
|
|
||||||
wl_event_loop_add_idle(manager->event_loop, handle_idle, manager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
workspace_send_details(struct wlr_ext_workspace_v1_resource *workspace_res) {
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace = workspace_res->workspace;
|
|
||||||
struct wl_resource *resource = workspace_res->resource;
|
|
||||||
|
|
||||||
ext_workspace_handle_v1_send_capabilities(resource, workspace->caps);
|
|
||||||
if (workspace->coordinates.size > 0) {
|
|
||||||
ext_workspace_handle_v1_send_coordinates(resource,
|
|
||||||
&workspace->coordinates);
|
|
||||||
}
|
|
||||||
if (workspace->name) {
|
|
||||||
ext_workspace_handle_v1_send_name(resource, workspace->name);
|
|
||||||
}
|
|
||||||
if (workspace->id) {
|
|
||||||
ext_workspace_handle_v1_send_id(resource, workspace->id);
|
|
||||||
}
|
|
||||||
ext_workspace_handle_v1_send_state(resource, workspace->state);
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_handle_stop(struct wl_client *client,
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
ext_workspace_manager_v1_send_finished(resource);
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct ext_workspace_manager_v1_interface manager_impl = {
|
|
||||||
.commit = manager_handle_commit,
|
|
||||||
.stop = manager_handle_stop,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void destroy_manager_resource(
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res) {
|
|
||||||
destroy_requests(manager_res);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp2;
|
|
||||||
wl_list_for_each_safe(workspace_res, tmp2,
|
|
||||||
&manager_res->workspace_resources,
|
|
||||||
manager_resource_link) {
|
|
||||||
destroy_workspace_resource(workspace_res);
|
|
||||||
}
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp3;
|
|
||||||
wl_list_for_each_safe(group_res, tmp3, &manager_res->group_resources,
|
|
||||||
manager_resource_link) {
|
|
||||||
destroy_group_resource(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_remove(&manager_res->link);
|
|
||||||
wl_resource_set_user_data(manager_res->resource, NULL);
|
|
||||||
free(manager_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_resource_destroy(struct wl_resource *resource) {
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
|
||||||
manager_resource_from_resource(resource);
|
|
||||||
if (manager_res) {
|
|
||||||
destroy_manager_resource(manager_res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
group_send_details(struct wlr_ext_workspace_group_v1_resource *group_res) {
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group = group_res->group;
|
|
||||||
struct wl_resource *resource = group_res->resource;
|
|
||||||
struct wl_client *client = wl_resource_get_client(resource);
|
|
||||||
|
|
||||||
ext_workspace_group_handle_v1_send_capabilities(resource, group->caps);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
|
||||||
wl_list_for_each(group_output, &group->outputs, link) {
|
|
||||||
struct wl_resource *output_resource;
|
|
||||||
wl_resource_for_each(output_resource,
|
|
||||||
&group_output->output->resources) {
|
|
||||||
if (wl_resource_get_client(output_resource) == client) {
|
|
||||||
ext_workspace_group_handle_v1_send_output_enter(
|
|
||||||
resource, output_resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(group->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_bind(struct wl_client *client, void *data, uint32_t version,
|
|
||||||
uint32_t id) {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager = data;
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res =
|
|
||||||
calloc(1, sizeof(*manager_res));
|
|
||||||
if (!manager_res) {
|
|
||||||
wl_client_post_no_memory(client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_res->manager = manager;
|
|
||||||
wl_list_init(&manager_res->requests);
|
|
||||||
wl_list_init(&manager_res->workspace_resources);
|
|
||||||
wl_list_init(&manager_res->group_resources);
|
|
||||||
|
|
||||||
manager_res->resource = wl_resource_create(
|
|
||||||
client, &ext_workspace_manager_v1_interface, version, id);
|
|
||||||
if (!manager_res->resource) {
|
|
||||||
free(manager_res);
|
|
||||||
wl_client_post_no_memory(client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wl_resource_set_implementation(manager_res->resource, &manager_impl,
|
|
||||||
manager_res, manager_resource_destroy);
|
|
||||||
wl_list_insert(&manager->resources, &manager_res->link);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group;
|
|
||||||
wl_list_for_each(group, &manager->groups, link) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
create_group_resource(group, manager_res);
|
|
||||||
if (!group_res) {
|
|
||||||
wl_resource_post_no_memory(manager_res->resource);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
|
|
||||||
group_res->resource);
|
|
||||||
group_send_details(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
|
||||||
wl_list_for_each(workspace, &manager->workspaces, link) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
create_workspace_resource(workspace, manager_res);
|
|
||||||
if (!workspace_res) {
|
|
||||||
wl_resource_post_no_memory(manager_res->resource);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ext_workspace_manager_v1_send_workspace(manager_res->resource,
|
|
||||||
workspace_res->resource);
|
|
||||||
workspace_send_details(workspace_res);
|
|
||||||
|
|
||||||
if (!workspace->group) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
|
||||||
wl_list_for_each(group_res, &workspace->group->resources, link) {
|
|
||||||
if (group_res->manager == manager_res) {
|
|
||||||
ext_workspace_group_handle_v1_send_workspace_enter(
|
|
||||||
group_res->resource, workspace_res->resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ext_workspace_manager_v1_send_done(manager_res->resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void manager_handle_display_destroy(struct wl_listener *listener,
|
|
||||||
void *data) {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager =
|
|
||||||
wl_container_of(listener, manager, display_destroy);
|
|
||||||
|
|
||||||
wl_signal_emit_mutable(&manager->events.destroy, NULL);
|
|
||||||
assert(wl_list_empty(&manager->events.commit.listener_list));
|
|
||||||
assert(wl_list_empty(&manager->events.destroy.listener_list));
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group, *tmp;
|
|
||||||
wl_list_for_each_safe(group, tmp, &manager->groups, link) {
|
|
||||||
wlr_ext_workspace_group_handle_v1_destroy(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, *tmp2;
|
|
||||||
wl_list_for_each_safe(workspace, tmp2, &manager->workspaces, link) {
|
|
||||||
wlr_ext_workspace_handle_v1_destroy(workspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res, *tmp3;
|
|
||||||
wl_list_for_each_safe(manager_res, tmp3, &manager->resources, link) {
|
|
||||||
destroy_manager_resource(manager_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manager->idle_source) {
|
|
||||||
wl_event_source_remove(manager->idle_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_remove(&manager->display_destroy.link);
|
|
||||||
wl_global_destroy(manager->global);
|
|
||||||
free(manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 *
|
|
||||||
wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
|
||||||
uint32_t version) {
|
|
||||||
assert(version <= EXT_WORKSPACE_V1_VERSION);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager = calloc(1, sizeof(*manager));
|
|
||||||
if (!manager) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->global =
|
|
||||||
wl_global_create(display, &ext_workspace_manager_v1_interface, version,
|
|
||||||
manager, manager_bind);
|
|
||||||
if (!manager->global) {
|
|
||||||
free(manager);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->event_loop = wl_display_get_event_loop(display);
|
|
||||||
|
|
||||||
manager->display_destroy.notify = manager_handle_display_destroy;
|
|
||||||
wl_display_add_destroy_listener(display, &manager->display_destroy);
|
|
||||||
|
|
||||||
wl_list_init(&manager->groups);
|
|
||||||
wl_list_init(&manager->workspaces);
|
|
||||||
wl_list_init(&manager->resources);
|
|
||||||
wl_signal_init(&manager->events.commit);
|
|
||||||
wl_signal_init(&manager->events.destroy);
|
|
||||||
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *
|
|
||||||
wlr_ext_workspace_group_handle_v1_create(
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps) {
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group = calloc(1, sizeof(*group));
|
|
||||||
if (!group) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
group->manager = manager;
|
|
||||||
group->caps = caps;
|
|
||||||
|
|
||||||
wl_list_init(&group->outputs);
|
|
||||||
wl_list_init(&group->resources);
|
|
||||||
wl_signal_init(&group->events.destroy);
|
|
||||||
|
|
||||||
wl_list_insert(manager->groups.prev, &group->link);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res =
|
|
||||||
create_group_resource(group, manager_res);
|
|
||||||
if (!group_res) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ext_workspace_manager_v1_send_workspace_group(manager_res->resource,
|
|
||||||
group_res->resource);
|
|
||||||
group_send_details(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(manager);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
workspace_send_group(struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
bool enter) {
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
|
||||||
wl_list_for_each(group_res, &group->resources, link) {
|
|
||||||
if (group_res->manager != workspace_res->manager) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (enter) {
|
|
||||||
ext_workspace_group_handle_v1_send_workspace_enter(
|
|
||||||
group_res->resource, workspace_res->resource);
|
|
||||||
} else {
|
|
||||||
ext_workspace_group_handle_v1_send_workspace_leave(
|
|
||||||
group_res->resource, workspace_res->resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_group_output(struct wlr_ext_workspace_v1_group_output *group_output) {
|
|
||||||
wl_list_remove(&group_output->output_bind.link);
|
|
||||||
wl_list_remove(&group_output->output_destroy.link);
|
|
||||||
wl_list_remove(&group_output->link);
|
|
||||||
free(group_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void group_send_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_output *output, bool enter) {
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
|
||||||
wl_list_for_each(group_res, &group->resources, link) {
|
|
||||||
struct wl_client *client = wl_resource_get_client(group_res->resource);
|
|
||||||
|
|
||||||
struct wl_resource *output_resource;
|
|
||||||
wl_resource_for_each(output_resource, &output->resources) {
|
|
||||||
if (wl_resource_get_client(output_resource) != client) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (enter) {
|
|
||||||
ext_workspace_group_handle_v1_send_output_enter(
|
|
||||||
group_res->resource, output_resource);
|
|
||||||
} else {
|
|
||||||
ext_workspace_group_handle_v1_send_output_leave(
|
|
||||||
group_res->resource, output_resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(group->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_group_handle_v1_destroy(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group) {
|
|
||||||
if (!group) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_signal_emit_mutable(&group->events.destroy, NULL);
|
|
||||||
|
|
||||||
assert(wl_list_empty(&group->events.destroy.listener_list));
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace;
|
|
||||||
wl_list_for_each(workspace, &group->manager->workspaces, link) {
|
|
||||||
if (workspace->group == group) {
|
|
||||||
workspace_send_group(workspace, group, false);
|
|
||||||
workspace->group = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res, *tmp;
|
|
||||||
wl_list_for_each_safe(group_res, tmp, &group->resources, link) {
|
|
||||||
ext_workspace_group_handle_v1_send_removed(group_res->resource);
|
|
||||||
destroy_group_resource(group_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &group->manager->resources, link) {
|
|
||||||
clear_requests_by(manager_res, group, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output, *tmp3;
|
|
||||||
wl_list_for_each_safe(group_output, tmp3, &group->outputs, link) {
|
|
||||||
group_send_output(group, group_output->output, false);
|
|
||||||
destroy_group_output(group_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(group->manager);
|
|
||||||
|
|
||||||
wl_list_remove(&group->link);
|
|
||||||
free(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_output_bind(struct wl_listener *listener, void *data) {
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
|
||||||
wl_container_of(listener, group_output, output_bind);
|
|
||||||
struct wlr_output_event_bind *event = data;
|
|
||||||
struct wl_client *client = wl_resource_get_client(event->resource);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_v1_resource *group_res;
|
|
||||||
wl_list_for_each(group_res, &group_output->group->resources, link) {
|
|
||||||
if (wl_resource_get_client(group_res->resource) == client) {
|
|
||||||
ext_workspace_group_handle_v1_send_output_enter(group_res->resource,
|
|
||||||
event->resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(group_output->group->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
|
||||||
wl_container_of(listener, group_output, output_destroy);
|
|
||||||
group_send_output(group_output->group, group_output->output, false);
|
|
||||||
destroy_group_output(group_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_ext_workspace_v1_group_output *
|
|
||||||
get_group_output(struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_output *output) {
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output;
|
|
||||||
wl_list_for_each(group_output, &group->outputs, link) {
|
|
||||||
if (group_output->output == output) {
|
|
||||||
return group_output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_group_handle_v1_output_enter(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_output *output) {
|
|
||||||
if (get_group_output(group, output)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
|
||||||
calloc(1, sizeof(*group_output));
|
|
||||||
if (!group_output) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
group_output->output = output;
|
|
||||||
group_output->group = group;
|
|
||||||
wl_list_insert(&group->outputs, &group_output->link);
|
|
||||||
|
|
||||||
group_output->output_bind.notify = handle_output_bind;
|
|
||||||
wl_signal_add(&output->events.bind, &group_output->output_bind);
|
|
||||||
group_output->output_destroy.notify = handle_output_destroy;
|
|
||||||
wl_signal_add(&output->events.destroy, &group_output->output_destroy);
|
|
||||||
|
|
||||||
group_send_output(group, output, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_group_handle_v1_output_leave(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group,
|
|
||||||
struct wlr_output *output) {
|
|
||||||
struct wlr_ext_workspace_v1_group_output *group_output =
|
|
||||||
get_group_output(group, output);
|
|
||||||
if (!group_output) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
group_send_output(group, output, false);
|
|
||||||
destroy_group_output(group_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *
|
|
||||||
wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
|
||||||
const char *id, uint32_t caps) {
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace =
|
|
||||||
calloc(1, sizeof(*workspace));
|
|
||||||
if (!workspace) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
workspace->manager = manager;
|
|
||||||
workspace->caps = caps;
|
|
||||||
|
|
||||||
if (id) {
|
|
||||||
workspace->id = strdup(id);
|
|
||||||
if (!workspace->id) {
|
|
||||||
free(workspace);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_init(&workspace->resources);
|
|
||||||
wl_array_init(&workspace->coordinates);
|
|
||||||
wl_signal_init(&workspace->events.destroy);
|
|
||||||
|
|
||||||
wl_list_insert(manager->workspaces.prev, &workspace->link);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &manager->resources, link) {
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res =
|
|
||||||
create_workspace_resource(workspace, manager_res);
|
|
||||||
if (!workspace_res) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ext_workspace_manager_v1_send_workspace(manager_res->resource,
|
|
||||||
workspace_res->resource);
|
|
||||||
workspace_send_details(workspace_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(manager);
|
|
||||||
|
|
||||||
return workspace;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_destroy(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace) {
|
|
||||||
if (!workspace) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_signal_emit_mutable(&workspace->events.destroy, NULL);
|
|
||||||
|
|
||||||
assert(wl_list_empty(&workspace->events.destroy.listener_list));
|
|
||||||
|
|
||||||
if (workspace->group) {
|
|
||||||
workspace_send_group(workspace, workspace->group, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res, *tmp;
|
|
||||||
wl_list_for_each_safe(workspace_res, tmp, &workspace->resources, link) {
|
|
||||||
ext_workspace_handle_v1_send_removed(workspace_res->resource);
|
|
||||||
destroy_workspace_resource(workspace_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1_resource *manager_res;
|
|
||||||
wl_list_for_each(manager_res, &workspace->manager->resources, link) {
|
|
||||||
clear_requests_by(manager_res, NULL, workspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
|
|
||||||
wl_list_remove(&workspace->link);
|
|
||||||
wl_array_release(&workspace->coordinates);
|
|
||||||
free(workspace->id);
|
|
||||||
free(workspace->name);
|
|
||||||
free(workspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_group(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group) {
|
|
||||||
if (workspace->group == group) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workspace->group) {
|
|
||||||
workspace_send_group(workspace, workspace->group, false);
|
|
||||||
}
|
|
||||||
workspace->group = group;
|
|
||||||
if (group) {
|
|
||||||
workspace_send_group(workspace, group, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_name(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name) {
|
|
||||||
assert(name);
|
|
||||||
|
|
||||||
if (workspace->name && strcmp(workspace->name, name) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(workspace->name);
|
|
||||||
workspace->name = strdup(name);
|
|
||||||
if (workspace->name == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
|
||||||
ext_workspace_handle_v1_send_name(workspace_res->resource,
|
|
||||||
workspace->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords,
|
|
||||||
size_t coords_len) {
|
|
||||||
size_t size = coords_len * sizeof(coords[0]);
|
|
||||||
if (size == workspace->coordinates.size &&
|
|
||||||
(size == 0 || memcmp(workspace->coordinates.data, coords, size) == 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_array_release(&workspace->coordinates);
|
|
||||||
wl_array_init(&workspace->coordinates);
|
|
||||||
struct wl_array arr = {
|
|
||||||
.data = (void *)coords,
|
|
||||||
.size = size,
|
|
||||||
};
|
|
||||||
wl_array_copy(&workspace->coordinates, &arr);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
|
||||||
ext_workspace_handle_v1_send_coordinates(workspace_res->resource,
|
|
||||||
&workspace->coordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workspace_set_state(struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
enum ext_workspace_handle_v1_state state,
|
|
||||||
bool enabled) {
|
|
||||||
uint32_t old_state = workspace->state;
|
|
||||||
if (enabled) {
|
|
||||||
workspace->state |= state;
|
|
||||||
} else {
|
|
||||||
workspace->state &= ~state;
|
|
||||||
}
|
|
||||||
if (old_state == workspace->state) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_resource *workspace_res;
|
|
||||||
wl_list_for_each(workspace_res, &workspace->resources, link) {
|
|
||||||
ext_workspace_handle_v1_send_state(workspace_res->resource,
|
|
||||||
workspace->state);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_schedule_done(workspace->manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_active(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
|
||||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE,
|
|
||||||
enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
|
||||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_URGENT,
|
|
||||||
enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled) {
|
|
||||||
workspace_set_state(workspace, EXT_WORKSPACE_HANDLE_V1_STATE_HIDDEN,
|
|
||||||
enabled);
|
|
||||||
}
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
/*
|
|
||||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
|
||||||
* future consistency of this API.
|
|
||||||
*/
|
|
||||||
#ifndef WLR_USE_UNSTABLE
|
|
||||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
|
|
||||||
#define WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
|
|
||||||
|
|
||||||
#include <wayland-protocols/ext-workspace-v1-enum.h>
|
|
||||||
#include <wayland-server-core.h>
|
|
||||||
|
|
||||||
struct wlr_output;
|
|
||||||
|
|
||||||
enum wlr_ext_workspace_v1_request_type {
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN,
|
|
||||||
WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_request {
|
|
||||||
enum wlr_ext_workspace_v1_request_type type;
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
char *name;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1
|
|
||||||
*group; // NULL if destroyed
|
|
||||||
} create_workspace;
|
|
||||||
struct {
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
|
||||||
} activate;
|
|
||||||
struct {
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
|
||||||
} deactivate;
|
|
||||||
struct {
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
|
||||||
struct wlr_ext_workspace_group_handle_v1
|
|
||||||
*group; // NULL if destroyed
|
|
||||||
} assign;
|
|
||||||
struct {
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
|
|
||||||
} remove;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_v1_commit_event {
|
|
||||||
struct wl_list *requests; // wlr_ext_workspace_v1_request.link
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 {
|
|
||||||
struct wl_global *global;
|
|
||||||
struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link
|
|
||||||
struct wl_list workspaces; // wlr_ext_workspace_handle_v1.link
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_signal commit; // wlr_ext_workspace_v1_commit_event
|
|
||||||
struct wl_signal destroy;
|
|
||||||
} events;
|
|
||||||
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
|
||||||
struct wl_event_source *idle_source;
|
|
||||||
struct wl_event_loop *event_loop;
|
|
||||||
struct wl_listener display_destroy;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager;
|
|
||||||
uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities
|
|
||||||
struct {
|
|
||||||
struct wl_signal destroy;
|
|
||||||
} events;
|
|
||||||
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1.groups
|
|
||||||
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
|
|
||||||
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 {
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager;
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group; // May be NULL
|
|
||||||
char *id;
|
|
||||||
char *name;
|
|
||||||
struct wl_array coordinates;
|
|
||||||
uint32_t caps; // ext_workspace_handle_v1_workspace_capabilities
|
|
||||||
uint32_t state; // ext_workspace_handle_v1_state
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_signal destroy;
|
|
||||||
} events;
|
|
||||||
|
|
||||||
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces
|
|
||||||
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct wl_list resources; // wlr_ext_workspace_v1_resource.link
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_manager_v1 *
|
|
||||||
wlr_ext_workspace_manager_v1_create(struct wl_display *display,
|
|
||||||
uint32_t version);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *
|
|
||||||
wlr_ext_workspace_group_handle_v1_create(
|
|
||||||
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps);
|
|
||||||
void wlr_ext_workspace_group_handle_v1_destroy(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group);
|
|
||||||
|
|
||||||
void wlr_ext_workspace_group_handle_v1_output_enter(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
|
|
||||||
void wlr_ext_workspace_group_handle_v1_output_leave(
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
|
|
||||||
|
|
||||||
struct wlr_ext_workspace_handle_v1 *
|
|
||||||
wlr_ext_workspace_handle_v1_create(struct wlr_ext_workspace_manager_v1 *manager,
|
|
||||||
const char *id, uint32_t caps);
|
|
||||||
void wlr_ext_workspace_handle_v1_destroy(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace);
|
|
||||||
|
|
||||||
void wlr_ext_workspace_handle_v1_set_group(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace,
|
|
||||||
struct wlr_ext_workspace_group_handle_v1 *group);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_name(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, const char *name);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_coordinates(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, const uint32_t *coords,
|
|
||||||
size_t coords_len);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_active(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_urgent(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
|
||||||
void wlr_ext_workspace_handle_v1_set_hidden(
|
|
||||||
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -31,7 +31,7 @@ Client *termforwin(Client *w) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wl_list_for_each(c, &fstack, flink) {
|
wl_list_for_each(c, &fstack, flink) {
|
||||||
if (c->isterm && !c->swallowing && c->pid &&
|
if (c->isterm && !c->swallowdby && c->pid &&
|
||||||
isdescprocess(c->pid, w->pid)) {
|
isdescprocess(c->pid, w->pid)) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
@ -48,9 +48,9 @@ Client *get_client_by_id_or_title(const char *arg_id, const char *arg_title) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->swallowedby) {
|
if (c->swallowing) {
|
||||||
appid = client_get_appid(c->swallowedby);
|
appid = client_get_appid(c->swallowing);
|
||||||
title = client_get_title(c->swallowedby);
|
title = client_get_title(c->swallowing);
|
||||||
} else {
|
} else {
|
||||||
appid = client_get_appid(c);
|
appid = client_get_appid(c);
|
||||||
title = client_get_title(c);
|
title = client_get_title(c);
|
||||||
|
|
@ -184,11 +184,11 @@ Client *find_client_by_direction(Client *tc, const Arg *arg,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (!c || c == tc)
|
if (!c || !c->mon || c == tc)
|
||||||
continue;
|
continue;
|
||||||
if (!findfloating && c->isfloating)
|
if (!findfloating && c->isfloating)
|
||||||
continue;
|
continue;
|
||||||
if (c->is_monocle_hide)
|
if (!VISIBLEON(c, c->mon))
|
||||||
continue;
|
continue;
|
||||||
if (c->isunglobal)
|
if (c->isunglobal)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -197,11 +197,6 @@ Client *find_client_by_direction(Client *tc, const Arg *arg,
|
||||||
if (!(c->tags & c->mon->tagset[c->mon->seltags]))
|
if (!(c->tags & c->mon->tagset[c->mon->seltags]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (step == 0 && ((!tc->mon->isoverview &&
|
|
||||||
!client_is_in_same_stack(tc, c, NULL)) ||
|
|
||||||
c->mon != tc->mon))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int32_t c_l = c->geom.x;
|
int32_t c_l = c->geom.x;
|
||||||
int32_t c_r = c->geom.x + c->geom.width;
|
int32_t c_r = c->geom.x + c->geom.width;
|
||||||
int32_t c_t = c->geom.y;
|
int32_t c_t = c->geom.y;
|
||||||
|
|
@ -257,17 +252,24 @@ Client *find_client_by_direction(Client *tc, const Arg *arg,
|
||||||
if (!match_dir)
|
if (!match_dir)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (step == 0) {
|
||||||
|
if (c->mon != tc->mon)
|
||||||
|
continue;
|
||||||
|
if (!tc->mon->isoverview &&
|
||||||
|
!client_is_in_same_stack(tc, c, NULL))
|
||||||
|
continue;
|
||||||
|
if (orth_dist != 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t penalty = 0;
|
int64_t penalty = 0;
|
||||||
if (main_dist < 0) {
|
if (main_dist < 0) {
|
||||||
penalty = 10000000000LL; // 主方向重叠(反方向)的极大惩罚
|
penalty = 10000000000LL;
|
||||||
main_dist = -main_dist;
|
main_dist = -main_dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 正交方向无重叠惩罚,优先选择在同一行/列的窗口
|
|
||||||
int64_t no_overlap_penalty = 0;
|
int64_t no_overlap_penalty = 0;
|
||||||
if (orth_dist > 0) {
|
if (orth_dist > 0) {
|
||||||
// LEFT/RIGHT 时 orth_dist 是垂直间距,>0 表示垂直无重叠
|
|
||||||
// UP/DOWN 时 orth_dist 是水平间距,>0 表示水平无重叠
|
|
||||||
no_overlap_penalty = 10000000LL;
|
no_overlap_penalty = 10000000LL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -442,7 +444,7 @@ Client *get_focused_stack_client(Client *sc, Client *custom_focus_client) {
|
||||||
return sc;
|
return sc;
|
||||||
|
|
||||||
wl_list_for_each(tc, &fstack, flink) {
|
wl_list_for_each(tc, &fstack, flink) {
|
||||||
if (tc->iskilling || tc->isunglobal || tc->is_monocle_hide)
|
if (tc->iskilling || tc->isunglobal)
|
||||||
continue;
|
continue;
|
||||||
if (!VISIBLEON(tc, sc->mon))
|
if (!VISIBLEON(tc, sc->mon))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -100,23 +100,30 @@ static bool layer_ignores_focus(LayerSurface *l) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||||
LayerSurface **pl, double *nx, double *ny) {
|
LayerSurface **pl, MangoGroupBar **gb, double *nx, double *ny) {
|
||||||
struct wlr_scene_node *node, *pnode;
|
struct wlr_scene_node *node = NULL, *pnode = NULL;
|
||||||
struct wlr_surface *surface = NULL;
|
struct wlr_surface *surface = NULL;
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
LayerSurface *l = NULL;
|
LayerSurface *l = NULL;
|
||||||
|
MangoGroupBar *mangogroupbar = NULL;
|
||||||
int32_t layer;
|
int32_t layer;
|
||||||
Client *ovc = NULL;
|
Client *ovc = NULL;
|
||||||
|
|
||||||
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
|
if (psurface)
|
||||||
|
*psurface = NULL;
|
||||||
|
if (pc)
|
||||||
|
*pc = NULL;
|
||||||
|
if (pl)
|
||||||
|
*pl = NULL;
|
||||||
|
if (gb)
|
||||||
|
*gb = NULL;
|
||||||
|
|
||||||
|
for (layer = NUM_LAYERS - 1; layer >= 0; layer--) {
|
||||||
if (layer == LyrFadeOut)
|
if (layer == LyrFadeOut)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny)))
|
node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny);
|
||||||
continue;
|
if (!node)
|
||||||
|
|
||||||
if (!node->enabled)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
||||||
|
|
@ -125,32 +132,44 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||||
wlr_scene_buffer_from_node(node));
|
wlr_scene_buffer_from_node(node));
|
||||||
if (scene_surface) {
|
if (scene_surface) {
|
||||||
surface = scene_surface->surface;
|
surface = scene_surface->surface;
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start from the topmost layer,
|
|
||||||
find a sureface that can be focused by pointer,
|
|
||||||
impopup neither a client nor a layer surface.*/
|
|
||||||
if (layer == LyrIMPopup) {
|
if (layer == LyrIMPopup) {
|
||||||
c = NULL;
|
c = NULL;
|
||||||
l = NULL;
|
l = NULL;
|
||||||
} else {
|
} else {
|
||||||
for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
|
void *data = NULL;
|
||||||
c = pnode->data;
|
for (pnode = node; pnode; pnode = &pnode->parent->node) {
|
||||||
if (c && c->type == LayerShell) {
|
if (pnode->data) {
|
||||||
l = (LayerSurface *)c;
|
data = pnode->data;
|
||||||
c = NULL;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
Client *temp_c = (Client *)data;
|
||||||
|
if (temp_c->type == LayerShell) {
|
||||||
|
l = (LayerSurface *)temp_c;
|
||||||
|
} else if (temp_c->type == GroupBar) {
|
||||||
|
mangogroupbar = (MangoGroupBar *)temp_c;
|
||||||
|
} else if (temp_c->type == XDGShell || temp_c->type == X11) {
|
||||||
|
c = temp_c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_RECT) {
|
if (node->type == WLR_SCENE_NODE_RECT) {
|
||||||
if (c) {
|
if (c && (c->type == XDGShell || c->type == X11)) {
|
||||||
surface = client_surface(c);
|
surface = client_surface(c);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
if (l && l->type == LayerShell) {
|
||||||
|
surface = l->layer_surface->surface;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psurface)
|
if (psurface)
|
||||||
|
|
@ -159,6 +178,8 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||||
*pc = c;
|
*pc = c;
|
||||||
if (pl)
|
if (pl)
|
||||||
*pl = l;
|
*pl = l;
|
||||||
|
if (gb)
|
||||||
|
*gb = mangogroupbar;
|
||||||
|
|
||||||
if (selmon && selmon->isoverview && config.ov_no_resize) {
|
if (selmon && selmon->isoverview && config.ov_no_resize) {
|
||||||
ovc = xytoclient(x, y);
|
ovc = xytoclient(x, y);
|
||||||
|
|
@ -174,12 +195,12 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||||
if (ovc && (!l || layer_ignores_focus(l) || is_below)) {
|
if (ovc && (!l || layer_ignores_focus(l) || is_below)) {
|
||||||
if (pc)
|
if (pc)
|
||||||
*pc = ovc;
|
*pc = ovc;
|
||||||
|
|
||||||
if (psurface)
|
if (psurface)
|
||||||
*psurface = ovc ? client_surface(ovc) : NULL;
|
*psurface = ovc ? client_surface(ovc) : NULL;
|
||||||
|
if (pl)
|
||||||
if (pl && ovc)
|
|
||||||
*pl = NULL;
|
*pl = NULL;
|
||||||
|
if (gb)
|
||||||
|
*gb = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -181,4 +181,4 @@ bool match_monitor_spec(char *spec, Monitor *m) {
|
||||||
free(serial_rule);
|
free(serial_rule);
|
||||||
|
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,11 +143,17 @@ static cJSON *build_client_json(Client *c) {
|
||||||
|
|
||||||
cJSON_AddNumberToObject(obj, "id", c->id);
|
cJSON_AddNumberToObject(obj, "id", c->id);
|
||||||
cJSON_AddNumberToObject(obj, "pid", c->pid);
|
cJSON_AddNumberToObject(obj, "pid", c->pid);
|
||||||
|
cJSON_AddStringToObject(obj, "foreign_toplevel_id",
|
||||||
|
c->ext_foreign_toplevel->identifier);
|
||||||
cJSON_AddStringToObject(obj, "title", client_get_title(c));
|
cJSON_AddStringToObject(obj, "title", client_get_title(c));
|
||||||
cJSON_AddStringToObject(obj, "appid", client_get_appid(c));
|
cJSON_AddStringToObject(obj, "appid", client_get_appid(c));
|
||||||
cJSON_AddStringToObject(obj, "monitor",
|
cJSON_AddStringToObject(obj, "monitor",
|
||||||
c->mon ? c->mon->wlr_output->name : "");
|
c->mon ? c->mon->wlr_output->name : "");
|
||||||
cJSON_AddItemToObject(obj, "tags", tags_mask_to_array(c->tags));
|
cJSON_AddItemToObject(obj, "tags", tags_mask_to_array(c->tags));
|
||||||
|
cJSON_AddBoolToObject(obj, "is_swallowing", c->swallowing ? true : false);
|
||||||
|
cJSON_AddBoolToObject(obj, "is_swallowedby", c->swallowdby ? true : false);
|
||||||
|
cJSON_AddBoolToObject(obj, "is_group", c->group_prev || c->group_next);
|
||||||
|
cJSON_AddBoolToObject(obj, "is_visible", c->mon && VISIBLEON(c, c->mon));
|
||||||
cJSON_AddBoolToObject(obj, "is_focused", c->isfocusing);
|
cJSON_AddBoolToObject(obj, "is_focused", c->isfocusing);
|
||||||
cJSON_AddBoolToObject(obj, "is_fullscreen", c->isfullscreen);
|
cJSON_AddBoolToObject(obj, "is_fullscreen", c->isfullscreen);
|
||||||
cJSON_AddBoolToObject(obj, "is_floating", c->isfloating);
|
cJSON_AddBoolToObject(obj, "is_floating", c->isfloating);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ void set_size_per(Monitor *m, Client *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found || c->isfloating) {
|
||||||
c->master_mfact_per = m->pertag->mfacts[m->pertag->curtag];
|
c->master_mfact_per = m->pertag->mfacts[m->pertag->curtag];
|
||||||
c->master_inner_per = 1.0f;
|
c->master_inner_per = 1.0f;
|
||||||
c->stack_inner_per = 1.0f;
|
c->stack_inner_per = 1.0f;
|
||||||
|
|
@ -37,21 +37,6 @@ void set_size_per(Monitor *m, Client *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void monocle_set_focus(Client *c, bool focused) {
|
|
||||||
|
|
||||||
if (!c || !c->mon)
|
|
||||||
return;
|
|
||||||
|
|
||||||
c->is_monocle_hide = !focused;
|
|
||||||
mango_tab_bar_node_set_focus(c->tab_bar_node, focused);
|
|
||||||
wlr_scene_node_set_enabled(&c->scene->node, focused);
|
|
||||||
|
|
||||||
if (!focused) {
|
|
||||||
c->animation.current = c->animainit_geom = c->animation.initial =
|
|
||||||
c->pending = c->current = c->geom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx,
|
||||||
int32_t offsety, uint32_t time,
|
int32_t offsety, uint32_t time,
|
||||||
int32_t type) {
|
int32_t type) {
|
||||||
|
|
@ -1147,14 +1132,8 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
|
||||||
client_add_jump_label_node(c);
|
client_add_jump_label_node(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->pertag->ltidxs[m->pertag->curtag]->id == MONOCLE &&
|
if (c->group_bar->scene_buffer->node.enabled) {
|
||||||
!c->tab_bar_node) {
|
client_check_tab_node_visible(c);
|
||||||
client_add_tab_bar_node(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->tab_bar_node && c->mon == m) {
|
|
||||||
wlr_scene_node_set_enabled(&c->tab_bar_node->scene_buffer->node,
|
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
if (c->mon == m && (c->isglobal || c->isunglobal)) {
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ static void dwindle_assign(DwindleNode *node, int32_t ax, int32_t ay,
|
||||||
!node->client->ismaximizescreen) {
|
!node->client->ismaximizescreen) {
|
||||||
struct wlr_box box = {ax, ay, MANGO_MAX(1, aw),
|
struct wlr_box box = {ax, ay, MANGO_MAX(1, aw),
|
||||||
MANGO_MAX(1, ah)};
|
MANGO_MAX(1, ah)};
|
||||||
resize(node->client, box, 0);
|
client_tile_resize(node->client, box, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -290,18 +290,37 @@ void center_tile(Monitor *m) {
|
||||||
int32_t should_overspread =
|
int32_t should_overspread =
|
||||||
config.center_master_overspread && (n <= nmasters);
|
config.center_master_overspread && (n <= nmasters);
|
||||||
|
|
||||||
|
int32_t left_num = 0;
|
||||||
|
int32_t right_num = 0;
|
||||||
|
for (int j = 0; j < stack_num; j++) {
|
||||||
|
if ((j % 2) ^ (n % 2 == 0)) {
|
||||||
|
right_num++;
|
||||||
|
} else {
|
||||||
|
left_num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32_t master_surplus_height =
|
int32_t master_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
(m->w.height - 2 * cur_gappov -
|
||||||
|
cur_gappiv * ie * (master_num > 0 ? master_num - 1 : 0));
|
||||||
float master_surplus_ratio = 1.0;
|
float master_surplus_ratio = 1.0;
|
||||||
|
int32_t init_master_surplus = master_surplus_height;
|
||||||
|
|
||||||
int32_t slave_left_surplus_height =
|
int32_t slave_left_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num / 2 - 1));
|
(m->w.height - 2 * cur_gappov -
|
||||||
|
cur_gappiv * ie * (left_num > 0 ? left_num - 1 : 0));
|
||||||
float slave_left_surplus_ratio = 1.0;
|
float slave_left_surplus_ratio = 1.0;
|
||||||
|
int32_t init_slave_left_surplus = slave_left_surplus_height;
|
||||||
|
|
||||||
int32_t slave_right_surplus_height =
|
int32_t slave_right_surplus_height =
|
||||||
(m->w.height - 2 * cur_gappov -
|
(m->w.height - 2 * cur_gappov -
|
||||||
cur_gappiv * ie * ((stack_num + 1) / 2 - 1));
|
cur_gappiv * ie * (right_num > 0 ? right_num - 1 : 0));
|
||||||
float slave_right_surplus_ratio = 1.0;
|
float slave_right_surplus_ratio = 1.0;
|
||||||
|
int32_t init_slave_right_surplus = slave_right_surplus_height;
|
||||||
|
|
||||||
|
int32_t init_single_stack_surplus =
|
||||||
|
(m->w.height - 2 * cur_gappov -
|
||||||
|
cur_gappiv * ie * (stack_num > 0 ? stack_num - 1 : 0));
|
||||||
|
|
||||||
if (n > nmasters || !should_overspread) {
|
if (n > nmasters || !should_overspread) {
|
||||||
// 计算主区域宽度(居中模式)
|
// 计算主区域宽度(居中模式)
|
||||||
|
|
@ -349,6 +368,8 @@ void center_tile(Monitor *m) {
|
||||||
if (c->master_inner_per > 0.0f) {
|
if (c->master_inner_per > 0.0f) {
|
||||||
h = master_surplus_height * c->master_inner_per /
|
h = master_surplus_height * c->master_inner_per /
|
||||||
master_surplus_ratio;
|
master_surplus_ratio;
|
||||||
|
if (r == 1)
|
||||||
|
h = m->w.height - my - cur_gappov;
|
||||||
master_surplus_height = master_surplus_height - h;
|
master_surplus_height = master_surplus_height - h;
|
||||||
master_surplus_ratio =
|
master_surplus_ratio =
|
||||||
master_surplus_ratio - c->master_inner_per;
|
master_surplus_ratio - c->master_inner_per;
|
||||||
|
|
@ -357,8 +378,12 @@ void center_tile(Monitor *m) {
|
||||||
h = (m->w.height - my - cur_gappov -
|
h = (m->w.height - my - cur_gappov -
|
||||||
cur_gappiv * ie * (r - 1)) /
|
cur_gappiv * ie * (r - 1)) /
|
||||||
r;
|
r;
|
||||||
c->master_inner_per = h / (m->w.height - my - cur_gappov -
|
if (r == 1)
|
||||||
cur_gappiv * ie * (r - 1));
|
h = m->w.height - my - cur_gappov;
|
||||||
|
c->master_inner_per =
|
||||||
|
init_master_surplus > 0
|
||||||
|
? ((float)h / (float)init_master_surplus)
|
||||||
|
: 0;
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,16 +402,20 @@ void center_tile(Monitor *m) {
|
||||||
// 单个堆叠窗口
|
// 单个堆叠窗口
|
||||||
r = n - i;
|
r = n - i;
|
||||||
if (c->stack_inner_per > 0.0f) {
|
if (c->stack_inner_per > 0.0f) {
|
||||||
h = (m->w.height - 2 * cur_gappov -
|
h = init_single_stack_surplus * c->stack_inner_per;
|
||||||
cur_gappiv * ie * (stack_num - 1)) *
|
if (r == 1)
|
||||||
c->stack_inner_per;
|
h = m->w.height - ety - cur_gappov;
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
} else {
|
} else {
|
||||||
h = (m->w.height - ety - cur_gappov -
|
h = (m->w.height - ety - cur_gappov -
|
||||||
cur_gappiv * ie * (r - 1)) /
|
cur_gappiv * ie * (r - 1)) /
|
||||||
r;
|
r;
|
||||||
c->stack_inner_per = h / (m->w.height - ety - cur_gappov -
|
if (r == 1)
|
||||||
cur_gappiv * ie * (r - 1));
|
h = m->w.height - ety - cur_gappov;
|
||||||
|
c->stack_inner_per =
|
||||||
|
init_single_stack_surplus > 0
|
||||||
|
? ((float)h / (float)init_single_stack_surplus)
|
||||||
|
: 0;
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -403,7 +432,7 @@ void center_tile(Monitor *m) {
|
||||||
.width = tw,
|
.width = tw,
|
||||||
.height = h},
|
.height = h},
|
||||||
0);
|
0);
|
||||||
ety += h + cur_gappiv * ie; // 使用理论高度累加
|
ety += h + cur_gappiv * ie;
|
||||||
} else {
|
} else {
|
||||||
// 多个堆叠窗口:交替放在左右两侧
|
// 多个堆叠窗口:交替放在左右两侧
|
||||||
r = (n - i + 1) / 2;
|
r = (n - i + 1) / 2;
|
||||||
|
|
@ -413,6 +442,8 @@ void center_tile(Monitor *m) {
|
||||||
if (c->stack_inner_per > 0.0f) {
|
if (c->stack_inner_per > 0.0f) {
|
||||||
h = slave_right_surplus_height * c->stack_inner_per /
|
h = slave_right_surplus_height * c->stack_inner_per /
|
||||||
slave_right_surplus_ratio;
|
slave_right_surplus_ratio;
|
||||||
|
if (r == 1)
|
||||||
|
h = m->w.height - ety - cur_gappov;
|
||||||
slave_right_surplus_height =
|
slave_right_surplus_height =
|
||||||
slave_right_surplus_height - h;
|
slave_right_surplus_height - h;
|
||||||
slave_right_surplus_ratio =
|
slave_right_surplus_ratio =
|
||||||
|
|
@ -422,9 +453,12 @@ void center_tile(Monitor *m) {
|
||||||
h = (m->w.height - ety - cur_gappov -
|
h = (m->w.height - ety - cur_gappov -
|
||||||
cur_gappiv * ie * (r - 1)) /
|
cur_gappiv * ie * (r - 1)) /
|
||||||
r;
|
r;
|
||||||
|
if (r == 1)
|
||||||
|
h = m->w.height - ety - cur_gappov;
|
||||||
c->stack_inner_per =
|
c->stack_inner_per =
|
||||||
h / (m->w.height - ety - cur_gappov -
|
init_slave_right_surplus > 0
|
||||||
cur_gappiv * ie * (r - 1));
|
? ((float)h / (float)init_slave_right_surplus)
|
||||||
|
: 0;
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -436,12 +470,14 @@ void center_tile(Monitor *m) {
|
||||||
.width = tw,
|
.width = tw,
|
||||||
.height = h},
|
.height = h},
|
||||||
0);
|
0);
|
||||||
ety += h + cur_gappiv * ie; // 使用理论高度累加
|
ety += h + cur_gappiv * ie;
|
||||||
} else {
|
} else {
|
||||||
// 左侧堆叠窗口
|
// 左侧堆叠窗口
|
||||||
if (c->stack_inner_per > 0.0f) {
|
if (c->stack_inner_per > 0.0f) {
|
||||||
h = slave_left_surplus_height * c->stack_inner_per /
|
h = slave_left_surplus_height * c->stack_inner_per /
|
||||||
slave_left_surplus_ratio;
|
slave_left_surplus_ratio;
|
||||||
|
if (r == 1)
|
||||||
|
h = m->w.height - oty - cur_gappov;
|
||||||
slave_left_surplus_height =
|
slave_left_surplus_height =
|
||||||
slave_left_surplus_height - h;
|
slave_left_surplus_height - h;
|
||||||
slave_left_surplus_ratio =
|
slave_left_surplus_ratio =
|
||||||
|
|
@ -451,9 +487,12 @@ void center_tile(Monitor *m) {
|
||||||
h = (m->w.height - oty - cur_gappov -
|
h = (m->w.height - oty - cur_gappov -
|
||||||
cur_gappiv * ie * (r - 1)) /
|
cur_gappiv * ie * (r - 1)) /
|
||||||
r;
|
r;
|
||||||
|
if (r == 1)
|
||||||
|
h = m->w.height - oty - cur_gappov;
|
||||||
c->stack_inner_per =
|
c->stack_inner_per =
|
||||||
h / (m->w.height - oty - cur_gappov -
|
init_slave_left_surplus > 0
|
||||||
cur_gappiv * ie * (r - 1));
|
? ((float)h / (float)init_slave_left_surplus)
|
||||||
|
: 0;
|
||||||
c->master_mfact_per = mfact;
|
c->master_mfact_per = mfact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -464,7 +503,7 @@ void center_tile(Monitor *m) {
|
||||||
.width = tw,
|
.width = tw,
|
||||||
.height = h},
|
.height = h},
|
||||||
0);
|
0);
|
||||||
oty += h + cur_gappiv * ie; // 使用理论高度累加
|
oty += h + cur_gappiv * ie;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -545,83 +584,32 @@ void deck(Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void monocle(Monitor *m) {
|
void // 17
|
||||||
Client *c = NULL, *fc = NULL;
|
monocle(Monitor *m) {
|
||||||
|
Client *c = NULL;
|
||||||
struct wlr_box geom;
|
struct wlr_box geom;
|
||||||
|
|
||||||
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
||||||
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
||||||
int32_t cur_gapiv = enablegaps ? m->gappiv : 0;
|
|
||||||
int32_t cur_gapih = enablegaps ? m->gappih : 0;
|
|
||||||
|
|
||||||
if (config.smartgaps && m->visible_fake_tiling_clients == 1) {
|
cur_gappoh = config.smartgaps && m->visible_fake_tiling_clients == 1
|
||||||
cur_gappov = cur_gappoh = cur_gapiv = cur_gapih = 0;
|
? 0
|
||||||
}
|
: cur_gappoh;
|
||||||
|
cur_gappov = config.smartgaps && m->visible_fake_tiling_clients == 1
|
||||||
int n = m->visible_fake_tiling_clients;
|
? 0
|
||||||
if (n == 0)
|
: cur_gappov;
|
||||||
return;
|
|
||||||
|
|
||||||
wl_list_for_each(c, &fstack, flink) {
|
|
||||||
if (c->iskilling || c->isunglobal || !ISFAKETILED(c))
|
|
||||||
continue;
|
|
||||||
if (VISIBLEON(c, m)) {
|
|
||||||
fc = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == 1) {
|
|
||||||
geom.x = m->w.x + cur_gappoh;
|
|
||||||
geom.y = m->w.y + cur_gappov;
|
|
||||||
geom.width = m->w.width - 2 * cur_gappoh;
|
|
||||||
geom.height = m->w.height - 2 * cur_gappov;
|
|
||||||
client_tile_resize(fc, geom, 0);
|
|
||||||
monocle_set_focus(fc, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tab_bar_height = config.tab_bar_height;
|
|
||||||
|
|
||||||
int tab_bar_inner_gap_height =
|
|
||||||
config.tab_bar_height > 0 ? 2 * cur_gapiv : 0;
|
|
||||||
int tab_bar_y_offset = config.tab_bar_height > 0 ? cur_gapiv : 0;
|
|
||||||
|
|
||||||
int tab_y = m->w.y + cur_gappov;
|
|
||||||
int main_y = tab_y + tab_bar_height + tab_bar_y_offset;
|
|
||||||
int main_height = m->w.height - 2 * cur_gappov - tab_bar_inner_gap_height -
|
|
||||||
tab_bar_height;
|
|
||||||
|
|
||||||
int tab_area_width = m->w.width - 2 * cur_gappoh;
|
|
||||||
|
|
||||||
int total_gaps = (n - 1) * cur_gapih;
|
|
||||||
int base_width = (tab_area_width - total_gaps) / n;
|
|
||||||
int remainder = (tab_area_width - total_gaps) % n;
|
|
||||||
|
|
||||||
int tab_x = m->w.x + cur_gappoh;
|
|
||||||
int idx = 0;
|
|
||||||
|
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (!VISIBLEON(c, m) || !ISFAKETILED(c))
|
if (!VISIBLEON(c, m) || !ISFAKETILED(c))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c == fc) {
|
|
||||||
monocle_set_focus(c, true);
|
|
||||||
} else {
|
|
||||||
monocle_set_focus(c, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
geom.x = m->w.x + cur_gappoh;
|
geom.x = m->w.x + cur_gappoh;
|
||||||
geom.y = main_y;
|
geom.y = m->w.y + cur_gappov;
|
||||||
geom.width = m->w.width - 2 * cur_gappoh;
|
geom.width = m->w.width - 2 * cur_gappoh;
|
||||||
geom.height = main_height;
|
geom.height = m->w.height - 2 * cur_gappov;
|
||||||
client_tile_resize(c, geom, 0);
|
client_tile_resize(c, geom, 0);
|
||||||
|
|
||||||
int tw = base_width + (idx < remainder ? 1 : 0);
|
|
||||||
global_draw_tab_bar(c, tab_x, tab_y, tw, tab_bar_height);
|
|
||||||
|
|
||||||
tab_x += tw + cur_gapih;
|
|
||||||
idx++;
|
|
||||||
}
|
}
|
||||||
|
if ((c = focustop(m)))
|
||||||
|
wlr_scene_node_raise_to_top(&c->scene->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网格布局窗口大小和位置计算
|
// 网格布局窗口大小和位置计算
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x, y, w, h;
|
float x, y, w, h;
|
||||||
} OvPlacedRect;
|
} OvPlacedRect;
|
||||||
|
|
@ -232,16 +231,20 @@ void overview_scale(Monitor *m) {
|
||||||
float base_x = m->w.x + target_gappo + dx;
|
float base_x = m->w.x + target_gappo + dx;
|
||||||
float base_y = m->w.y + target_gappo + dy;
|
float base_y = m->w.y + target_gappo + dy;
|
||||||
|
|
||||||
|
// 收集所有客户端的目标几何,最后统一调用 client_tile_resize
|
||||||
|
struct wlr_box overview_boxes[n]; // C99 VLA,n > 0 时有效
|
||||||
for (int k = 0; k < n; k++) {
|
for (int k = 0; k < n; k++) {
|
||||||
Client *cl = items[k].c;
|
|
||||||
struct wlr_box geom;
|
|
||||||
geom.x = (int)(base_x + placed[k].x + 0.5f);
|
|
||||||
geom.y = (int)(base_y + placed[k].y + 0.5f);
|
|
||||||
float w = items[k].orig_w * best_s;
|
float w = items[k].orig_w * best_s;
|
||||||
float h = items[k].orig_h * best_s;
|
float h = items[k].orig_h * best_s;
|
||||||
geom.width = (int)(geom.x + w + 0.5f) - geom.x;
|
int ix = (int)(base_x + placed[k].x + 0.5f);
|
||||||
geom.height = (int)(geom.y + h + 0.5f) - geom.y;
|
int iy = (int)(base_y + placed[k].y + 0.5f);
|
||||||
resize(cl, geom, 0);
|
int iw = (int)(ix + w + 0.5f) - ix;
|
||||||
|
int ih = (int)(iy + h + 0.5f) - iy;
|
||||||
|
overview_boxes[k] = (struct wlr_box){ix, iy, iw, ih};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < n; k++) {
|
||||||
|
client_tile_resize(items[k].c, overview_boxes[k], 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,74 +283,69 @@ void overview_resize(Monitor *m) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 临时存储每个客户端的目标几何
|
||||||
|
struct wlr_box boxes[n]; // C99 VLA
|
||||||
|
|
||||||
if (n == 1) {
|
if (n == 1) {
|
||||||
int32_t cw = (m->w.width - 2 * target_gappo) * single_width_ratio;
|
int32_t cw = (m->w.width - 2 * target_gappo) * single_width_ratio;
|
||||||
int32_t ch = (m->w.height - 2 * target_gappo) * single_height_ratio;
|
int32_t ch = (m->w.height - 2 * target_gappo) * single_height_ratio;
|
||||||
c_arr[0]->geom.x = m->w.x + (m->w.width - cw) / 2;
|
boxes[0].x = m->w.x + (m->w.width - cw) / 2;
|
||||||
c_arr[0]->geom.y = m->w.y + (m->w.height - ch) / 2;
|
boxes[0].y = m->w.y + (m->w.height - ch) / 2;
|
||||||
c_arr[0]->geom.width = cw;
|
boxes[0].width = cw;
|
||||||
c_arr[0]->geom.height = ch;
|
boxes[0].height = ch;
|
||||||
resize(c_arr[0], c_arr[0]->geom, 0);
|
} else if (n == 2) {
|
||||||
free(c_arr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == 2) {
|
|
||||||
int32_t cw = (m->w.width - 2 * target_gappo - target_gappi) / 2;
|
int32_t cw = (m->w.width - 2 * target_gappo - target_gappi) / 2;
|
||||||
int32_t ch = (m->w.height - 2 * target_gappo) * 0.65f;
|
int32_t ch = (m->w.height - 2 * target_gappo) * 0.65f;
|
||||||
|
|
||||||
c_arr[0]->geom.x = m->w.x + target_gappo;
|
boxes[0].x = m->w.x + target_gappo;
|
||||||
c_arr[0]->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
boxes[0].y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
||||||
c_arr[0]->geom.width = cw;
|
boxes[0].width = cw;
|
||||||
c_arr[0]->geom.height = ch;
|
boxes[0].height = ch;
|
||||||
resize(c_arr[0], c_arr[0]->geom, 0);
|
|
||||||
|
|
||||||
c_arr[1]->geom.x = m->w.x + cw + target_gappo + target_gappi;
|
boxes[1].x = m->w.x + cw + target_gappo + target_gappi;
|
||||||
c_arr[1]->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
boxes[1].y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
||||||
c_arr[1]->geom.width = cw;
|
boxes[1].width = cw;
|
||||||
c_arr[1]->geom.height = ch;
|
boxes[1].height = ch;
|
||||||
resize(c_arr[1], c_arr[1]->geom, 0);
|
} else {
|
||||||
|
int32_t cols = 1;
|
||||||
|
while (cols * cols < n)
|
||||||
|
cols++;
|
||||||
|
int32_t rows = (n + cols - 1) / cols;
|
||||||
|
|
||||||
free(c_arr);
|
int32_t ch =
|
||||||
return;
|
(m->w.height - 2 * target_gappo - (rows - 1) * target_gappi) / rows;
|
||||||
}
|
int32_t cw =
|
||||||
|
(m->w.width - 2 * target_gappo - (cols - 1) * target_gappi) / cols;
|
||||||
|
|
||||||
int32_t cols = 1;
|
if (ch < 1)
|
||||||
while (cols * cols < n) {
|
ch = 1;
|
||||||
cols++;
|
if (cw < 1)
|
||||||
}
|
cw = 1;
|
||||||
int32_t rows = (n + cols - 1) / cols;
|
|
||||||
|
|
||||||
int32_t ch =
|
int32_t overcols = n % cols;
|
||||||
(m->w.height - 2 * target_gappo - (rows - 1) * target_gappi) / rows;
|
int32_t dx = 0;
|
||||||
int32_t cw =
|
if (overcols) {
|
||||||
(m->w.width - 2 * target_gappo - (cols - 1) * target_gappi) / cols;
|
dx = (m->w.width - overcols * cw - (overcols - 1) * target_gappi) /
|
||||||
|
2 -
|
||||||
if (ch < 1)
|
target_gappo;
|
||||||
ch = 1;
|
|
||||||
if (cw < 1)
|
|
||||||
cw = 1;
|
|
||||||
|
|
||||||
int32_t overcols = n % cols;
|
|
||||||
int32_t dx = 0;
|
|
||||||
if (overcols) {
|
|
||||||
dx = (m->w.width - overcols * cw - (overcols - 1) * target_gappi) / 2 -
|
|
||||||
target_gappo;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
int32_t cx = m->w.x + (i % cols) * (cw + target_gappi);
|
|
||||||
int32_t cy = m->w.y + (i / cols) * (ch + target_gappi);
|
|
||||||
|
|
||||||
if (overcols && i >= n - overcols) {
|
|
||||||
cx += dx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c_arr[i]->geom.x = cx + target_gappo;
|
for (int i = 0; i < n; i++) {
|
||||||
c_arr[i]->geom.y = cy + target_gappo;
|
int32_t cx = m->w.x + (i % cols) * (cw + target_gappi);
|
||||||
c_arr[i]->geom.width = cw;
|
int32_t cy = m->w.y + (i / cols) * (ch + target_gappi);
|
||||||
c_arr[i]->geom.height = ch;
|
if (overcols && i >= n - overcols)
|
||||||
resize(c_arr[i], c_arr[i]->geom, 0);
|
cx += dx;
|
||||||
|
|
||||||
|
boxes[i].x = cx + target_gappo;
|
||||||
|
boxes[i].y = cy + target_gappo;
|
||||||
|
boxes[i].width = cw;
|
||||||
|
boxes[i].height = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一应用所有几何变更,使用 client_tile_resize
|
||||||
|
for (int k = 0; k < n; k++) {
|
||||||
|
client_tile_resize(c_arr[k], boxes[k], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(c_arr);
|
free(c_arr);
|
||||||
|
|
@ -365,10 +363,9 @@ void create_jump_hints(Monitor *m) {
|
||||||
char c_char = jump_labels[label_idx];
|
char c_char = jump_labels[label_idx];
|
||||||
c->jump_char = c_char;
|
c->jump_char = c_char;
|
||||||
|
|
||||||
// 把字符变成字符串
|
|
||||||
char label_text[2] = {c_char, '\0'};
|
char label_text[2] = {c_char, '\0'};
|
||||||
|
mango_jump_label_node_update(c->jump_label_node, label_text,
|
||||||
mango_jump_label_node_update(c->jump_label_node, label_text, 1.0f);
|
m->wlr_output->scale);
|
||||||
wlr_scene_node_set_enabled(&c->jump_label_node->scene_buffer->node,
|
wlr_scene_node_set_enabled(&c->jump_label_node->scene_buffer->node,
|
||||||
true);
|
true);
|
||||||
wlr_scene_node_raise_to_top(
|
wlr_scene_node_raise_to_top(
|
||||||
|
|
@ -385,12 +382,10 @@ void create_jump_hints(Monitor *m) {
|
||||||
void begin_jump_mode(Monitor *m) { m->is_jump_mode = 1; }
|
void begin_jump_mode(Monitor *m) { m->is_jump_mode = 1; }
|
||||||
|
|
||||||
void finish_jump_mode(Monitor *m) {
|
void finish_jump_mode(Monitor *m) {
|
||||||
Client *c = NULL;
|
if (!m->is_jump_mode)
|
||||||
|
|
||||||
if (!m->is_jump_mode) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
|
Client *c;
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (VISIBLEON(c, m)) {
|
if (VISIBLEON(c, m)) {
|
||||||
if (c->jump_label_node->scene_buffer->node.enabled) {
|
if (c->jump_label_node->scene_buffer->node.enabled) {
|
||||||
|
|
@ -400,12 +395,10 @@ void finish_jump_mode(Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m->is_jump_mode = 0;
|
m->is_jump_mode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void overview(Monitor *m) {
|
void overview(Monitor *m) {
|
||||||
|
|
||||||
if (config.ov_no_resize) {
|
if (config.ov_no_resize) {
|
||||||
overview_scale(m);
|
overview_scale(m);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -415,4 +408,4 @@ void overview(Monitor *m) {
|
||||||
if (m->is_jump_mode) {
|
if (m->is_jump_mode) {
|
||||||
create_jump_hints(m);
|
create_jump_hints(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ scroller_node_create(struct TagScrollerState *st, Client *c) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 从 tag 状态中移除一个节点并释放 */
|
|
||||||
static void scroller_node_remove(struct TagScrollerState *st,
|
static void scroller_node_remove(struct TagScrollerState *st,
|
||||||
struct ScrollerStackNode *target) {
|
struct ScrollerStackNode *target) {
|
||||||
if (!st || !target)
|
if (!st || !target)
|
||||||
|
|
@ -223,7 +222,7 @@ void arrange_stack_node(struct ScrollerStackNode *head, struct wlr_box geometry,
|
||||||
.y = current_y,
|
.y = current_y,
|
||||||
.width = geometry.width,
|
.width = geometry.width,
|
||||||
.height = client_height};
|
.height = client_height};
|
||||||
resize(iter->client, client_geom, 0);
|
client_tile_resize(iter->client, client_geom, 0);
|
||||||
remain_proportion -= iter->stack_proportion;
|
remain_proportion -= iter->stack_proportion;
|
||||||
remain_client_height -= client_height;
|
remain_client_height -= client_height;
|
||||||
current_y += client_height + gappiv;
|
current_y += client_height + gappiv;
|
||||||
|
|
@ -272,7 +271,7 @@ void arrange_stack_vertical_node(struct ScrollerStackNode *head,
|
||||||
.x = current_x,
|
.x = current_x,
|
||||||
.height = geometry.height,
|
.height = geometry.height,
|
||||||
.width = client_width};
|
.width = client_width};
|
||||||
resize(iter->client, client_geom, 0);
|
client_tile_resize(iter->client, client_geom, 0);
|
||||||
remain_proportion -= iter->stack_proportion;
|
remain_proportion -= iter->stack_proportion;
|
||||||
remain_client_width -= client_width;
|
remain_client_width -= client_width;
|
||||||
current_x += client_width + gappih;
|
current_x += client_width + gappih;
|
||||||
|
|
@ -508,6 +507,7 @@ void scroller(Monitor *m) {
|
||||||
|
|
||||||
void vertical_scroller(Monitor *m) {
|
void vertical_scroller(Monitor *m) {
|
||||||
uint32_t tag = m->pertag->curtag;
|
uint32_t tag = m->pertag->curtag;
|
||||||
|
int32_t bar_height = 0;
|
||||||
struct TagScrollerState *st = ensure_scroller_state(m, tag);
|
struct TagScrollerState *st = ensure_scroller_state(m, tag);
|
||||||
Client *c = NULL;
|
Client *c = NULL;
|
||||||
float scroller_default_proportion_single =
|
float scroller_default_proportion_single =
|
||||||
|
|
@ -696,7 +696,12 @@ void vertical_scroller(Monitor *m) {
|
||||||
arrange_stack_vertical_node(heads[focus_index], target_geom,
|
arrange_stack_vertical_node(heads[focus_index], target_geom,
|
||||||
cur_gappih);
|
cur_gappih);
|
||||||
} else {
|
} else {
|
||||||
target_geom.y = root_client->geom.y;
|
bar_height = !root_client->isfullscreen && (root_client->group_prev ||
|
||||||
|
root_client->group_next)
|
||||||
|
? config.group_bar_height
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
target_geom.y = root_client->geom.y - bar_height;
|
||||||
vertical_check_scroller_root_inside_mon(heads[focus_index]->client,
|
vertical_check_scroller_root_inside_mon(heads[focus_index]->client,
|
||||||
&target_geom);
|
&target_geom);
|
||||||
arrange_stack_vertical_node(heads[focus_index], target_geom,
|
arrange_stack_vertical_node(heads[focus_index], target_geom,
|
||||||
|
|
@ -709,8 +714,15 @@ void vertical_scroller(Monitor *m) {
|
||||||
up_geom.width = m->w.width - 2 * cur_gappoh;
|
up_geom.width = m->w.width - 2 * cur_gappoh;
|
||||||
up_geom.height = max_client_height * cur->scroller_proportion;
|
up_geom.height = max_client_height * cur->scroller_proportion;
|
||||||
vertical_scroll_adjust_fullandmax(cur->client, &up_geom);
|
vertical_scroll_adjust_fullandmax(cur->client, &up_geom);
|
||||||
|
|
||||||
|
bar_height = !heads[focus_index - i + 1]->client->isfullscreen &&
|
||||||
|
(heads[focus_index - i + 1]->client->group_prev ||
|
||||||
|
heads[focus_index - i + 1]->client->group_next)
|
||||||
|
? config.group_bar_height
|
||||||
|
: 0;
|
||||||
|
|
||||||
up_geom.y = heads[focus_index - i + 1]->client->geom.y - cur_gappiv -
|
up_geom.y = heads[focus_index - i + 1]->client->geom.y - cur_gappiv -
|
||||||
up_geom.height;
|
up_geom.height - bar_height;
|
||||||
arrange_stack_vertical_node(cur, up_geom, cur_gappih);
|
arrange_stack_vertical_node(cur, up_geom, cur_gappih);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -773,16 +785,14 @@ void scroller_insert_stack(Client *c, Client *target_client,
|
||||||
if (tnode->prev_in_stack)
|
if (tnode->prev_in_stack)
|
||||||
tnode->prev_in_stack->next_in_stack = newnode;
|
tnode->prev_in_stack->next_in_stack = newnode;
|
||||||
tnode->prev_in_stack = newnode;
|
tnode->prev_in_stack = newnode;
|
||||||
wl_list_remove(&c->link);
|
wl_list_safe_reinsert_prev(&tnode->client->link, &c->link);
|
||||||
wl_list_insert(tnode->client->link.prev, &c->link);
|
|
||||||
} else {
|
} else {
|
||||||
newnode->prev_in_stack = tnode;
|
newnode->prev_in_stack = tnode;
|
||||||
newnode->next_in_stack = tnode->next_in_stack;
|
newnode->next_in_stack = tnode->next_in_stack;
|
||||||
if (tnode->next_in_stack)
|
if (tnode->next_in_stack)
|
||||||
tnode->next_in_stack->prev_in_stack = newnode;
|
tnode->next_in_stack->prev_in_stack = newnode;
|
||||||
tnode->next_in_stack = newnode;
|
tnode->next_in_stack = newnode;
|
||||||
wl_list_remove(&c->link);
|
wl_list_safe_reinsert_next(&tnode->client->link, &c->link);
|
||||||
wl_list_insert(&tnode->client->link, &c->link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 处理堆叠头部的全屏/最大化状态*/
|
/* 处理堆叠头部的全屏/最大化状态*/
|
||||||
|
|
@ -821,13 +831,11 @@ void scroller_drop_tile(Client *c, Client *closest, int vertical) {
|
||||||
return;
|
return;
|
||||||
} else if (closest->drop_direction == UP) {
|
} else if (closest->drop_direction == UP) {
|
||||||
if (c != stack_head) {
|
if (c != stack_head) {
|
||||||
wl_list_remove(&c->link);
|
wl_list_safe_reinsert_prev(&stack_head->link, &c->link);
|
||||||
wl_list_insert(stack_head->link.prev, &c->link);
|
|
||||||
}
|
}
|
||||||
} else if (closest->drop_direction == DOWN) {
|
} else if (closest->drop_direction == DOWN) {
|
||||||
if (c != stack_tail) {
|
if (c != stack_tail) {
|
||||||
wl_list_remove(&c->link);
|
wl_list_safe_reinsert_next(&stack_head->link, &c->link);
|
||||||
wl_list_insert(&stack_tail->link, &c->link);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -841,13 +849,11 @@ void scroller_drop_tile(Client *c, Client *closest, int vertical) {
|
||||||
return;
|
return;
|
||||||
} else if (closest->drop_direction == LEFT) {
|
} else if (closest->drop_direction == LEFT) {
|
||||||
if (c != stack_head) {
|
if (c != stack_head) {
|
||||||
wl_list_remove(&c->link);
|
wl_list_safe_reinsert_prev(&stack_head->link, &c->link);
|
||||||
wl_list_insert(stack_head->link.prev, &c->link);
|
|
||||||
}
|
}
|
||||||
} else if (closest->drop_direction == RIGHT) {
|
} else if (closest->drop_direction == RIGHT) {
|
||||||
if (c != stack_tail) {
|
if (c != stack_tail) {
|
||||||
wl_list_remove(&c->link);
|
wl_list_safe_reinsert_next(&stack_head->link, &c->link);
|
||||||
wl_list_insert(&stack_tail->link, &c->link);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -902,7 +908,6 @@ static void update_scroller_state(Monitor *m) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 移除不再可见的节点 */
|
|
||||||
struct ScrollerStackNode *n = st->all_first;
|
struct ScrollerStackNode *n = st->all_first;
|
||||||
while (n) {
|
while (n) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
|
||||||
835
src/mango.c
835
src/mango.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue