Full Code of FelixKratz/SketchyBar for AI

master 856ee4afef9c cached
75 files
462.3 KB
111.5k tokens
936 symbols
1 requests
Download .txt
Showing preview only (484K chars total). Download the full file or copy to clipboard to get everything.
Repository: FelixKratz/SketchyBar
Branch: master
Commit: 856ee4afef9c
Files: 75
Total size: 462.3 KB

Directory structure:
gitextract_dn_wj_wt/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── makefile
├── plugins/
│   ├── battery.sh
│   ├── clock.sh
│   ├── front_app.sh
│   ├── space.sh
│   └── volume.sh
├── sketchybarrc
└── src/
    ├── alias.c
    ├── alias.h
    ├── animation.c
    ├── animation.h
    ├── app_windows.c
    ├── app_windows.h
    ├── background.c
    ├── background.h
    ├── bar.c
    ├── bar.h
    ├── bar_item.c
    ├── bar_item.h
    ├── bar_manager.c
    ├── bar_manager.h
    ├── color.c
    ├── color.h
    ├── custom_events.c
    ├── custom_events.h
    ├── display.c
    ├── display.h
    ├── event.c
    ├── event.h
    ├── font.c
    ├── font.h
    ├── graph.c
    ├── graph.h
    ├── group.c
    ├── group.h
    ├── hotload.c
    ├── hotload.h
    ├── image.c
    ├── image.h
    ├── mach.c
    ├── mach.h
    ├── media.h
    ├── media.m
    ├── message.c
    ├── message.h
    ├── misc/
    │   ├── defines.h
    │   ├── env_vars.h
    │   ├── extern.h
    │   ├── help.h
    │   └── helpers.h
    ├── mouse.c
    ├── mouse.h
    ├── popup.c
    ├── popup.h
    ├── power.c
    ├── power.h
    ├── shadow.c
    ├── shadow.h
    ├── sketchybar.c
    ├── slider.c
    ├── slider.h
    ├── text.c
    ├── text.h
    ├── volume.c
    ├── volume.h
    ├── wifi.h
    ├── wifi.m
    ├── window.c
    ├── window.h
    ├── workspace.h
    └── workspace.m

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
ko_fi: felixkratz


================================================
FILE: .gitignore
================================================
test
bin
todo.md
notifications.md
.ccls-cache
.DS_Store
.ccls
.cache
.cmake
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
compile_commands.json


================================================
FILE: LICENSE.md
================================================
                    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>.


================================================
FILE: README.md
================================================
<p align="center">
  <img src="images/Sbar.svg" />
</p>

<p align="center">
<a href="https://felixkratz.github.io/SketchyBar/setup">Install</a>
<span> • </span>
<a href="https://felixkratz.github.io/SketchyBar/config/bar">Documentation</a> 
<span> • </span> 
<a href="https://github.com/FelixKratz/SketchyBar/discussions/47?sort=top">Setups</a>
<span> • </span> 
<a href="https://github.com/FelixKratz/SketchyBar/discussions/12?sort=top">Plugins</a>
</p>

<p align="center">
<a href="https://opensource.org/licenses/"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
<a href="https://github.com/FelixKratz/SketchyBar/releases"><img src="https://img.shields.io/github/v/release/FelixKratz/SketchyBar.svg?style=flat&color=orange" /></a>
<a href="https://github.com/FelixKratz/SketchyBar/releases"><img src="https://img.shields.io/github/commits-since/FelixKratz/SketchyBar/latest.svg?color=orange"></a>
<a href="https://en.wikipedia.org/wiki/Free_and_open-source_software"><img src="https://img.shields.io/badge/FOSS-100%25-green.svg?style=flat"></a>
</p>

<p align="center">
This bar project aims to create a highly flexible, customizable, fast and powerful status bar replacement for people that like playing with
shell scripts.
</p>

![](images/example.png)
<p align="center">
<a href="https://github.com/FelixKratz/SketchyBar/discussions/47?sort=top">More Setups</a>
</p>



## Features
* Full *configurability* at any time
* Dynamic *animation* system
* Powerful *scripting* and *event* system
* Optimized to be *fast* and *efficient*
* Interactive *mouse* support
* Support for displaying macOS menu bar apps (*aliases*)
* Can draw arbitrary *graphs*
* On-demand *popup* menus

The main design principle of this project is that *all* elements of the bar can
be added, removed and freely changed at any point in time. Thus, the
configuration of the bar is not *static*, rather it is possible to adapt the
appearance of the bar completely dynamically with the help of a powerful
event-driven scripting system at any point in time using the highly
configurable basic building blocks SketchyBar offers.

## Getting Started
Refer to the installation guide in the [documentation](https://felixkratz.github.io/SketchyBar/setup) to get the program set up.
Once this is sorted you can start to become familiar with the syntax of sketchybar by going through the default [*sketchybarrc*](https://github.com/FelixKratz/SketchyBar/blob/master/sketchybarrc) file and the default [*plugin scripts*](https://github.com/FelixKratz/SketchyBar/blob/master/plugins),
which are located in `~/.config/sketchybar/` and look like this:

![](images/default.png)

All commands and options are explained in detail in the relevant sections
of the configuration [documentation](https://felixkratz.github.io/SketchyBar/config/bar). You can try the commands directly from
the commandline to see which affect they have and how they alter the bar. Once you have become familiar with the syntax you can
look for a config to start from [here](https://github.com/FelixKratz/SketchyBar/discussions/47?sort=top) or start from scratch and customize
everything to your liking.

You might also enjoy looking at the [Tips & Tricks](https://felixkratz.github.io/SketchyBar/config/tricks) section
for some further tips on your journey. If you are searching for functional items you might want to check the
[plugins](https://github.com/FelixKratz/SketchyBar/discussions/12?sort=top) section if someone has already created what you are looking for.

Should you encounter things not working as you expect them to, please *do not* hesitate to open an [issue](https://github.com/FelixKratz/SketchyBar/issues), as
this is either a bug or a documentation problem and relevant in any case.

## Documentation
For the full documentation of all commands and properties please refer to the [website](https://felixkratz.github.io/SketchyBar/config/bar).

If questions remain, feel free to consult the [Q&A](https://github.com/FelixKratz/SketchyBar/discussions/categories/q-a) section.

## Supporting
*You* can support this project is many ways:
- By *creating* issues and pull-requests if you encounter problems
- By *sharing* your [plugins](https://github.com/FelixKratz/SketchyBar/discussions/12) and [setups](https://github.com/FelixKratz/SketchyBar/discussions/47)
- By *starring* the project on GitHub
- If this project has value to you, consider quantifying it and *donating* to a charity of your choice. If you want to let me know about your donation, you
can contact me via [email](mailto:felix.kratz@tu-dortmund.de?Subject=Donation).
- If you want to support me directly, you can do so via [ko-fi](https://ko-fi.com/felixkratz)

## Credits
This project was forked from *[spacebar](https://github.com/cmacrae/spacebar)* and completely reimagined and rewritten. <br>
The original idea is based on the status bar that was included in *[yabai](https://github.com/koekeishiya/yabai)* before getting removed.


## Related Projects
- [SbarLua](https://github.com/FelixKratz/SbarLua): A Lua API for SketchyBar
- [sketchybar-app-font](https://github.com/kvndrsslr/sketchybar-app-font): A symbol font for SketchyBar
- [SketchyBarHelper](https://github.com/FelixKratz/SketchyBarHelper): A header for C/C++ to directly communicate with SketchyBar

## Some animation examples

https://user-images.githubusercontent.com/22680421/211198711-45318f04-e96f-4aa1-a0ba-c7f30f050902.mp4




================================================
FILE: makefile
================================================
CFLAGS   = -std=c99 -Wall -O3 -ffast-math -fvisibility=hidden -fno-common

LIBS     = -framework Carbon \
					 -framework AppKit \
					 -framework CoreAudio \
					 -framework CoreWLAN \
					 -framework CoreVideo \
					 -framework IOKit \
					 -F/System/Library/PrivateFrameworks \
					 -framework SkyLight \
					 -framework DisplayServices \
					 -framework MediaRemote

ODIR     = bin
SRC      = src

_OBJ = alias.o background.o bar_item.o custom_events.o event.o graph.o \
			 image.o mouse.o shadow.o font.o text.o message.o mouse.o bar.o color.o \
			 window.o bar_manager.o display.o group.o mach.o popup.o \
			 animation.o workspace.om volume.o slider.o power.o wifi.om media.om \
			 hotload.o app_windows.o

OBJ  = $(patsubst %, $(ODIR)/%, $(_OBJ))

.PHONY: all clean arm x86 profile leak universal

all: clean universal

leak: CFLAGS=-std=c99 -Wall -g
leak: clean arm64
leak:
	/usr/libexec/PlistBuddy -c "Add :com.apple.security.get-task-allow bool true" bin/tmp.entitlements
	codesign -s - --entitlements bin/tmp.entitlements -f ./bin/sketchybar
	leaks -atExit -- ./bin/sketchybar

x86: CFLAGS+=-target x86_64-apple-macos10.13
x86: $(ODIR)/sketchybar

arm64: CFLAGS+=-target arm64-apple-macos11
arm64: $(ODIR)/sketchybar

universal:
	$(MAKE) x86
	mv $(ODIR)/sketchybar $(ODIR)/sketchybar_x86
	rm -rf $(ODIR)/*.o*
	$(MAKE) arm64
	mv $(ODIR)/sketchybar $(ODIR)/sketchybar_arm64
	lipo -create -output $(ODIR)/sketchybar $(ODIR)/sketchybar_x86 $(ODIR)/sketchybar_arm64

debug: CFLAGS=-std=c99 -Wall -g
debug: arm64

asan: CFLAGS=-std=c99 -Wall -g -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
asan: clean arm64
	./bin/sketchybar

$(ODIR)/sketchybar: $(SRC)/sketchybar.c $(OBJ) | $(ODIR)
	$(CC) $(CFLAGS) $^ -o $@ $(LIBS)

$(ODIR)/%.o: $(SRC)/%.c $(SRC)/%.h | $(ODIR)
	$(CC) -c -o $@ $< $(CFLAGS)

$(ODIR)/%.om: $(SRC)/%.m $(SRC)/%.h | $(ODIR)
	$(CC) -c -o $@ $< $(CFLAGS)

$(ODIR):
	mkdir $(ODIR)

clean:
	rm -rf $(ODIR)


================================================
FILE: plugins/battery.sh
================================================
#!/bin/sh

PERCENTAGE="$(pmset -g batt | grep -Eo "\d+%" | cut -d% -f1)"
CHARGING="$(pmset -g batt | grep 'AC Power')"

if [ "$PERCENTAGE" = "" ]; then
  exit 0
fi

case "${PERCENTAGE}" in
  9[0-9]|100) ICON=""
  ;;
  [6-8][0-9]) ICON=""
  ;;
  [3-5][0-9]) ICON=""
  ;;
  [1-2][0-9]) ICON=""
  ;;
  *) ICON=""
esac

if [[ "$CHARGING" != "" ]]; then
  ICON=""
fi

# The item invoking this script (name $NAME) will get its icon and label
# updated with the current battery status
sketchybar --set "$NAME" icon="$ICON" label="${PERCENTAGE}%"


================================================
FILE: plugins/clock.sh
================================================
#!/bin/sh

# The $NAME variable is passed from sketchybar and holds the name of
# the item invoking this script:
# https://felixkratz.github.io/SketchyBar/config/events#events-and-scripting

sketchybar --set "$NAME" label="$(date '+%d/%m %H:%M')"



================================================
FILE: plugins/front_app.sh
================================================
#!/bin/sh

# Some events send additional information specific to the event in the $INFO
# variable. E.g. the front_app_switched event sends the name of the newly
# focused application in the $INFO variable:
# https://felixkratz.github.io/SketchyBar/config/events#events-and-scripting

if [ "$SENDER" = "front_app_switched" ]; then
  sketchybar --set "$NAME" label="$INFO"
fi


================================================
FILE: plugins/space.sh
================================================
#!/bin/sh

# The $SELECTED variable is available for space components and indicates if
# the space invoking this script (with name: $NAME) is currently selected:
# https://felixkratz.github.io/SketchyBar/config/components#space----associate-mission-control-spaces-with-an-item

sketchybar --set "$NAME" background.drawing="$SELECTED"


================================================
FILE: plugins/volume.sh
================================================
#!/bin/sh

# The volume_change event supplies a $INFO variable in which the current volume
# percentage is passed to the script.

if [ "$SENDER" = "volume_change" ]; then
  VOLUME="$INFO"

  case "$VOLUME" in
    [6-9][0-9]|100) ICON="󰕾"
    ;;
    [3-5][0-9]) ICON="󰖀"
    ;;
    [1-9]|[1-2][0-9]) ICON="󰕿"
    ;;
    *) ICON="󰖁"
  esac

  sketchybar --set "$NAME" icon="$ICON" label="$VOLUME%"
fi


================================================
FILE: sketchybarrc
================================================
# This is a demo config to showcase some of the most important commands.
# It is meant to be changed and configured, as it is intentionally kept sparse.
# For a (much) more advanced configuration example see my dotfiles:
# https://github.com/FelixKratz/dotfiles

PLUGIN_DIR="$CONFIG_DIR/plugins"

##### Bar Appearance #####
# Configuring the general appearance of the bar.
# These are only some of the options available. For all options see:
# https://felixkratz.github.io/SketchyBar/config/bar
# If you are looking for other colors, see the color picker:
# https://felixkratz.github.io/SketchyBar/config/tricks#color-picker

sketchybar --bar position=top height=40 blur_radius=30 color=0x40000000

##### Changing Defaults #####
# We now change some default values, which are applied to all further items.
# For a full list of all available item properties see:
# https://felixkratz.github.io/SketchyBar/config/items

default=(
  padding_left=5
  padding_right=5
  icon.font="Hack Nerd Font:Bold:17.0"
  label.font="Hack Nerd Font:Bold:14.0"
  icon.color=0xffffffff
  label.color=0xffffffff
  icon.padding_left=4
  icon.padding_right=4
  label.padding_left=4
  label.padding_right=4
)
sketchybar --default "${default[@]}"

##### Adding Mission Control Space Indicators #####
# Let's add some mission control spaces:
# https://felixkratz.github.io/SketchyBar/config/components#space----associate-mission-control-spaces-with-an-item
# to indicate active and available mission control spaces.

SPACE_ICONS=("1" "2" "3" "4" "5" "6" "7" "8" "9" "10")
for i in "${!SPACE_ICONS[@]}"
do
  sid="$(($i+1))"
  space=(
    space="$sid"
    icon="${SPACE_ICONS[i]}"
    icon.padding_left=7
    icon.padding_right=7
    background.color=0x40ffffff
    background.corner_radius=5
    background.height=25
    label.drawing=off
    script="$PLUGIN_DIR/space.sh"
    click_script="yabai -m space --focus $sid"
  )
  sketchybar --add space space."$sid" left --set space."$sid" "${space[@]}"
done

##### Adding Left Items #####
# We add some regular items to the left side of the bar, where
# only the properties deviating from the current defaults need to be set

sketchybar --add item chevron left \
           --set chevron icon= label.drawing=off \
           --add item front_app left \
           --set front_app icon.drawing=off script="$PLUGIN_DIR/front_app.sh" \
           --subscribe front_app front_app_switched

##### Adding Right Items #####
# In the same way as the left items we can add items to the right side.
# Additional position (e.g. center) are available, see:
# https://felixkratz.github.io/SketchyBar/config/items#adding-items-to-sketchybar

# Some items refresh on a fixed cycle, e.g. the clock runs its script once
# every 10s. Other items respond to events they subscribe to, e.g. the
# volume.sh script is only executed once an actual change in system audio
# volume is registered. More info about the event system can be found here:
# https://felixkratz.github.io/SketchyBar/config/events

sketchybar --add item clock right \
           --set clock update_freq=10 icon=  script="$PLUGIN_DIR/clock.sh" \
           --add item volume right \
           --set volume script="$PLUGIN_DIR/volume.sh" \
           --subscribe volume volume_change \
           --add item battery right \
           --set battery update_freq=120 script="$PLUGIN_DIR/battery.sh" \
           --subscribe battery system_woke power_source_change

##### Force all scripts to run the first time (never do this in a script) #####
sketchybar --update


================================================
FILE: src/alias.c
================================================
#include "alias.h"
#include "misc/helpers.h"
#include <CoreFoundation/CFBase.h>
#include <CoreFoundation/CoreFoundation.h>

void print_all_menu_items(FILE* rsp) {
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 110000
  if (__builtin_available(macOS 11.0, *)) {
    if (!CGRequestScreenCaptureAccess()) {
      respond(rsp, "[!] Query (default_menu_items): Screen Recording "
                   "Permissions not given. Restart SketchyBar after granting "
                   "permissions.\n");
      return;
    }
  }

#endif
  CFArrayRef window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionAll,
                                                      kCGNullWindowID        );
  int window_count = CFArrayGetCount(window_list);

  float x_pos[window_count];
  char* owner[window_count];
  char* name[window_count];
  memset(owner, 0, sizeof(owner));
  memset(name, 0, sizeof(name));

  int item_count = 0;
  for (int i = 0; i < window_count; ++i) {
    x_pos[i] = -9999.f;
    CFDictionaryRef dictionary = CFArrayGetValueAtIndex(window_list, i);
    if (!dictionary) continue;

    CFStringRef owner_ref = CFDictionaryGetValue(dictionary,
                                                 kCGWindowOwnerName);

    CFNumberRef owner_pid_ref = CFDictionaryGetValue(dictionary,
                                                     kCGWindowOwnerPID);

    CFStringRef name_ref = CFDictionaryGetValue(dictionary, kCGWindowName);
    CFNumberRef layer_ref = CFDictionaryGetValue(dictionary, kCGWindowLayer);
    CFDictionaryRef bounds_ref = CFDictionaryGetValue(dictionary,
                                                      kCGWindowBounds);

    if (!name_ref || !owner_ref || !owner_pid_ref || !layer_ref || !bounds_ref)
      continue;

    long long int layer = 0;
    CFNumberGetValue(layer_ref, CFNumberGetType(layer_ref), &layer);
    uint64_t owner_pid = 0;
    CFNumberGetValue(owner_pid_ref,
                     CFNumberGetType(owner_pid_ref),
                     &owner_pid                     );

    if (layer != MENUBAR_LAYER) continue;
    CGRect bounds = CGRectNull;
    if (!CGRectMakeWithDictionaryRepresentation(bounds_ref, &bounds)) continue;
    char* owner_copy = cfstring_copy(owner_ref);
    if (string_equals(owner_copy, "Window Server")) {
      free(owner_copy);
      continue;
    }
    owner[item_count] = owner_copy;
    name[item_count] = cfstring_copy(name_ref);
    x_pos[item_count++] = bounds.origin.x;
  }

  if (item_count > 0) {
    fprintf(rsp, "[\n");
    int counter = 0;
    for (int i = 0; i < item_count; i++) {
      float current_pos = x_pos[0];
      uint32_t current_pos_id = 0;
      for (int j = 0; j < window_count; j++) {
        if (!name[j] || !owner[j]) continue;
        if (x_pos[j] > current_pos) {
          current_pos = x_pos[j];
          current_pos_id = j;
        }
      }

      if (!name[current_pos_id] || !owner[current_pos_id]) continue;
      if (strcmp(name[current_pos_id], "") != 0) {
        if (counter++ > 0) {
          fprintf(rsp, ", \n");
        }
        fprintf(rsp, "\t\"%s,%s\"", owner[current_pos_id],
                                    name[current_pos_id]  );
      }
      x_pos[current_pos_id] = -9999.f;
    }
    fprintf(rsp, "\n]\n");
    for (int i = 0; i < window_count; i++) {
      if (owner[i]) free(owner[i]);
      if (name[i]) free(name[i]);
    }
  }
  CFRelease(window_list);
}

void alias_get_permission(struct alias* alias) { 
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 110000 
  if (__builtin_available(macOS 11.0, *)) {
    alias->permission = CGRequestScreenCaptureAccess();
  }
#else
  if(__builtin_available(macos 10.15, *)) {
    CGImageRef img = CGWindowListCreateImage(CGRectMake(0, 0, 1, 1),
                                             kCGWindowListOptionOnScreenOnly,
                                             kCGNullWindowID,
                                             kCGWindowImageDefault           );

    CFRelease(img);
  }
#endif
}

void alias_init(struct alias* alias) {
  alias->name = NULL;
  alias->owner = NULL;
  alias->color_override = false;
  color_init(&alias->color, 0xffff0000);
  alias->update_frequency = 1;
  alias->counter = 0;

  window_init(&alias->window);
  image_init(&alias->image);
}

static void alias_find_window(struct alias* alias) {
  CFArrayRef window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionAll,
                                                      kCGNullWindowID        );
  int window_count = CFArrayGetCount(window_list);

  for (int i = 0; i < window_count; ++i) {
    CFDictionaryRef dictionary = CFArrayGetValueAtIndex(window_list, i);
    if (!dictionary) continue;

    CFStringRef owner_ref = CFDictionaryGetValue(dictionary,
                                                 kCGWindowOwnerName);

    CFNumberRef owner_pid_ref = CFDictionaryGetValue(dictionary,
                                                     kCGWindowOwnerPID);

    CFStringRef name_ref = CFDictionaryGetValue(dictionary, kCGWindowName);
    if (!name_ref) continue;
    if (!owner_ref) continue;
    char* owner = cfstring_copy(owner_ref);
    char* name = cfstring_copy(name_ref);

    if (!(alias->owner && strcmp(alias->owner, owner) == 0
          && ((alias->name && strcmp(alias->name, name) == 0)
              || (!alias->name && strcmp(name, "") != 0)     ))) {
      free(owner);
      free(name);
      continue;
    }
    free(owner);
    free(name);

    CFNumberRef layer_ref = CFDictionaryGetValue(dictionary, kCGWindowLayer);
    if (!layer_ref) continue;

    uint64_t layer = 0;
    CFNumberGetValue(layer_ref, CFNumberGetType(layer_ref), &layer);
    if (layer != MENUBAR_LAYER) continue;

    CFNumberGetValue(owner_pid_ref,
                     CFNumberGetType(owner_pid_ref),
                     &alias->pid                    );

    CFNumberRef window_id_ref = CFDictionaryGetValue(dictionary,
                                                     kCGWindowNumber);

    if (!window_id_ref) continue;
    CFDictionaryRef bounds_ref = CFDictionaryGetValue(dictionary, kCGWindowBounds);
    if (!bounds_ref) continue;

    CGRect bounds;
    CGRectMakeWithDictionaryRepresentation(bounds_ref, &bounds);

    uint64_t wid;
    CFNumberGetValue(window_id_ref,
                     CFNumberGetType(window_id_ref),
                     &wid                           );

    alias->window.id = (uint32_t)wid;
    alias->window.frame.size = bounds.size;
    alias->window.origin = bounds.origin;

    CFRelease(window_list);
    return;
  }
  alias->window.id = 0;
  CFRelease(window_list);
}

static bool alias_update_image(struct alias* alias, bool forced) {
  if (alias->window.id == 0) alias_find_window(alias);
  if (alias->window.id == 0) return false;

  bool disabled = false;
  CGImageRef image_ref = window_capture(&alias->window, &disabled);

  if (!image_ref) {
    if (!disabled) {
      alias->window.id = 0;
      image_destroy(&alias->image);
    }
    return false;
  }

  return image_set_image(&alias->image,
                         image_ref,
                         alias->window.frame,
                         forced              );
}

void alias_setup(struct alias* alias, char* owner, char* name) {
  alias->name = name;
  alias->owner = owner;
  alias_get_permission(alias);
  alias_update_image(alias, true);
}

uint32_t alias_get_length(struct alias* alias) {
  if (alias->image.image_ref) return alias->image.bounds.size.width;
  return 0;
}

uint32_t alias_get_height(struct alias* alias) {
  if (alias->image.image_ref) return alias->image.bounds.size.height;
  return 0;
}

bool alias_update(struct alias* alias, bool forced) {
  if (alias->update_frequency == 0) return false;

  alias->counter++;
  if (forced || alias->counter >= alias->update_frequency) {
    alias->counter = 0;
    if (alias_update_image(alias, forced)) {
      return true;
    }
  }
  return false;
}

void alias_draw(struct alias* alias, CGContextRef context) {
  if (alias->color_override) {
    CGContextSaveGState(context);
    image_draw(&alias->image, context);
    CGContextClipToMask(context, alias->image.bounds, alias->image.image_ref);
    CGContextSetRGBFillColor(context,
                             alias->color.r,
                             alias->color.g,
                             alias->color.b,
                             alias->color.a );

    CGContextFillRect(context, alias->image.bounds);
    CGContextRestoreGState(context);
  }
  else {
    image_draw(&alias->image, context);
  }
}

void alias_destroy(struct alias* alias) {
  image_destroy(&alias->image);
  if (alias->name) free(alias->name);
  if (alias->owner) free(alias->owner);
  alias->name = NULL;
  alias->owner = NULL;
}

void alias_calculate_bounds(struct alias* alias, uint32_t x, uint32_t y) {
  image_calculate_bounds(&alias->image, x, y);
}

bool alias_parse_sub_domain(struct alias* alias, FILE* rsp, struct token property, char* message) {
  struct key_value_pair key_value_pair = get_key_value_pair(property.text,'.');
  if (key_value_pair.key && key_value_pair.value) {
    struct token subdom = { key_value_pair.key, strlen(key_value_pair.key) };
    struct token entry = { key_value_pair.value, strlen(key_value_pair.value)};
    if (token_equals(subdom, SUB_DOMAIN_SHADOW))
      return shadow_parse_sub_domain(&alias->image.shadow,
                                     rsp,
                                     entry,
                                     message              );
    else if (token_equals(subdom, SUB_DOMAIN_COLOR)) {
      bool changed = !alias->color_override;
      alias->color_override = true;
      return color_parse_sub_domain(&alias->color, rsp, entry, message)
            || changed;
    }
    else {
      respond(rsp, "[!] Alias: Invalid subdomain '%s'\n", subdom.text);
    }
  }
  else if (token_equals(property, PROPERTY_COLOR)) {
    color_set_hex(&alias->color, token_to_uint32t(get_token(&message)));
    alias->color_override = true;
    return true;
  } else if (token_equals(property, PROPERTY_SCALE)) {
    return image_set_scale(&alias->image, token_to_float(get_token(&message)));
  } else if (token_equals(property, PROPERTY_UPDATE_FREQ)) {
    alias->update_frequency = token_to_uint32t(get_token(&message));
    return false;
  } else {
    respond(rsp, "[!] Alias: Invalid property '%s' \n", property.text);
  }
  return false;
}


================================================
FILE: src/alias.h
================================================
#pragma once
#include <stdbool.h>
#include "misc/helpers.h"
#include "window.h"
#include "image.h"

#define MENUBAR_LAYER 0x19

struct alias {
  bool permission;
  uint32_t update_frequency;
  uint32_t counter;

  char* name;
  char* owner;

  pid_t pid;

  struct window window;

  bool color_override;
  struct color color;
  struct image image;
};

void alias_init(struct alias* alias);
void alias_setup(struct alias* alias, char* owner, char* name);
uint32_t alias_get_length(struct alias* alias);
uint32_t alias_get_height(struct alias* alias);

void alias_calculate_bounds(struct alias* alias, uint32_t x, uint32_t y);
void alias_draw(struct alias* alias, CGContextRef context);
bool alias_update(struct alias* alias, bool forced);
void alias_destroy(struct alias* alias);

void print_all_menu_items(FILE* rsp);

bool alias_parse_sub_domain(struct alias* alias, FILE* rsp, struct token property, char* message);


================================================
FILE: src/animation.c
================================================
#include "animation.h"
#include "event.h"

static CVReturn animation_frame_callback(CVDisplayLinkRef display_link, const CVTimeStamp* now, const CVTimeStamp* output_time, CVOptionFlags flags, CVOptionFlags* flags_out, void* context) {
  uint64_t hostTime = output_time->hostTime;
  dispatch_async(dispatch_get_main_queue(), ^{
    struct event event = { (void*)hostTime, ANIMATOR_REFRESH };
    event_post(&event);
  });
  return kCVReturnSuccess;
}

struct animation* animation_create() {
  struct animation* animation = malloc(sizeof(struct animation));
  memset(animation, 0, sizeof(struct animation));

  return animation;
}

static void animation_destroy(struct animation* animation) {
  if (animation) free(animation);
}

static void animation_lock(struct animation* animation) {
  animation->locked = true;
}

void animation_setup(struct animation* animation, void* target, animator_function* update_function, int initial_value, int final_value, uint32_t duration, char interp_function) {
  // The animation duration is represented as a frame count equivalent on a
  // 60Hz display. E.g. 120frames = 2 seconds
  animation->duration = (double)duration / 60.0;
  animation->initial_value = initial_value;
  animation->final_value = final_value;
  animation->update_function = update_function;
  animation->target = target;
  animation->separate_bytes = false;
  animation->as_float = false;

  if (interp_function == INTERP_FUNCTION_TANH) {
    animation->interp_function = &function_tanh;
  } else if (interp_function == INTERP_FUNCTION_SIN) {
    animation->interp_function = &function_sin;
  } else if (interp_function == INTERP_FUNCTION_QUADRATIC) {
    animation->interp_function = &function_square;
  } else if (interp_function == INTERP_FUNCTION_EXP) {
    animation->interp_function = &function_exp;
  } else if (interp_function == INTERP_FUNCTION_CIRC) {
    animation->interp_function = &function_circ;
  } else {
    animation->interp_function = &function_linear;
  }
}

static bool animation_update(struct animation* animation, uint64_t time, uint64_t clock) {
  if (!animation->target
      || !animation->update_function
      || animation->waiting         ) {
    return false;
  }

  if (!animation->initial_time) animation->initial_time = time;
  double t = animation->duration > 0
             ? ((double)(time - animation->initial_time)
               / (double)(animation->duration * clock))
             : 1.0;

  bool final_frame = t >= 1.0;
  if (t < 0.0) t = 0.0;
  if (t > 1.0) t = 1.0;

  double slider = final_frame ? 1.0 : animation->interp_function(t);

  int value;
  if (animation->separate_bytes) {
    for (int i = 0; i < 4; i++) {
      unsigned char byte_i = *((unsigned char*)&animation->initial_value + i);
      unsigned char byte_f = *((unsigned char*)&animation->final_value + i);

      unsigned char byte_val = (1. - slider) * byte_i + slider * byte_f;
      *((unsigned char*)&value + i) = byte_val;
    }
  } else if (animation->as_float) {
    *((float*)&value) = (1. - slider) * *(float*)&animation->initial_value
             + slider * *(float*)&animation->final_value;

  } else {
    value = (1. - slider) * animation->initial_value
            + slider * animation->final_value
            + 0.5;
    if (final_frame) value = animation->final_value;
  }

  bool needs_update;
  if (animation->as_float) {
    needs_update =
      ((bool (*)(void*, float))animation->update_function)(animation->target,
                                                           *((float*)&value) );
  } else {
    needs_update = animation->update_function(animation->target, value);
  }

  bool found_item = false;
  for (int i = 0; i < g_bar_manager.bar_item_count; i++) {
    if (needs_update
        && (animation->target >= (void*)g_bar_manager.bar_items[i])
        && (animation->target < ((void*)g_bar_manager.bar_items[i]
                                 + sizeof(struct bar_item)         ))) {

      bar_item_needs_update(g_bar_manager.bar_items[i]);
      found_item = true;
    }
  }

  if (!found_item && needs_update) g_bar_manager.bar_needs_update = true;

  animation->finished = final_frame;
  if (animation->finished && animation->next) {
    animation->next->previous = NULL;
    animation->next->waiting = false;
    animation->next = NULL;
  }
  return needs_update;
}

void animator_init(struct animator* animator) {
  animator->animations = NULL;
  animator->animation_count = 0;
  animator->interp_function = 0;
  animator->duration = 0;
  animator->display_link = NULL;

  animator_renew_display_link(animator);
}

void animator_renew_display_link(struct animator* animator) {
  animator_destroy_display_link(animator);
  CVDisplayLinkCreateWithActiveCGDisplays(&animator->display_link);

  CVDisplayLinkSetOutputCallback(animator->display_link,
                                 animation_frame_callback,
                                 animator                 );

  animator->clock = CVGetHostClockFrequency();
  CVDisplayLinkStart(animator->display_link);
}

void animator_destroy_display_link(struct animator* animator) {
  if (animator->display_link) {
    CVDisplayLinkStop(animator->display_link);
    CVDisplayLinkRelease(animator->display_link);
    animator->display_link = NULL;
  }
}

void animator_lock(struct animator* animator) {
  for (int i = 0; i < animator->animation_count; i++) {
     animation_lock(animator->animations[i]);
  }
}

static void animator_calculate_offset_for_animation(struct animator* animator, struct animation* animation) {
  if (animator->animation_count < 1) return;

  struct animation* previous = NULL;
  for (int i = animator->animation_count - 1; i >= 0; i--) {
    struct animation* current = animator->animations[i];
    if (current->target == animation->target
        && current->update_function == animation->update_function) {
      previous = current;
      break;
    }
  }

  if (previous) {
    animation->initial_value = previous->final_value;
    previous->next = animation;
    animation->previous = previous;
    animation->waiting = true;
  }
}

void animator_add(struct animator* animator, struct animation* animation) {
  animator_calculate_offset_for_animation(animator, animation);
  animator->animations = realloc(animator->animations,
                                 sizeof(struct animation*)
                                        * ++animator->animation_count);
  animator->animations[animator->animation_count - 1] = animation;

  if (!animator->display_link) animator_renew_display_link(animator);
}

static void animator_remove(struct animator* animator, struct animation* animation) {
  if (animator->animation_count == 1) {
    free(animator->animations);
    animator->animations = NULL;
    animator->animation_count = 0;
  } else {
    struct animation* tmp[animator->animation_count - 1];
    int count = 0;
    for (int i = 0; i < animator->animation_count; i++) {
      if (animator->animations[i] == animation) continue;
      tmp[count++] = animator->animations[i];
    }
    animator->animation_count--;
    animator->animations = realloc(animator->animations,
                                   sizeof(struct animation*)
                                          *animator->animation_count);

    memcpy(animator->animations,
           tmp,
           sizeof(struct animation*)*animator->animation_count);
  }

  if (animation->previous) animation->previous->next = NULL;
  if (animation->next) animation->next->previous = NULL;

  animation_destroy(animation);
}

void animator_cancel_locked(struct animator* animator, void* target, animator_function* function) {
  struct animation* remove[animator->animation_count];
  memset(remove, 0, animator->animation_count);
  uint32_t remove_count = 0;

  for (int i = 0; i < animator->animation_count; i++) {
    struct animation* animation = animator->animations[i];
    if (animation->locked
        && animation->target == target
        && animation->update_function == function) {
      remove[remove_count++] = animation;
    }
  }

  for (uint32_t i = 0; i < remove_count; i++) {
    animator_remove(animator, remove[i]);
  }
}

bool animator_cancel(struct animator* animator, void* target, animator_function* function) {
  bool needs_update = false;

  struct animation* remove[animator->animation_count];
  memset(remove, 0, animator->animation_count);
  uint32_t remove_count = 0;

  for (int i = 0; i < animator->animation_count; i++) {
    struct animation* animation = animator->animations[i];
    if (animation->target == target
        && animation->update_function == function) {
      needs_update |= function(animation->target, animation->final_value);
      remove[remove_count++] = animation;
    }
  }

  for (uint32_t i = 0; i < remove_count; i++) {
    animator_remove(animator, remove[i]);
  }

  return needs_update;
}

bool animator_update(struct animator* animator, uint64_t time) {
  bool needs_refresh = false;
  struct animation* remove[animator->animation_count];
  memset(remove, 0, animator->animation_count);
  uint32_t remove_count = 0;

  for (uint32_t i = 0; i < animator->animation_count; i++) {
    needs_refresh |= animation_update(animator->animations[i],
                                      time,
                                      animator->clock         );

    if (animator->animations[i]->finished) {
      remove[remove_count++] = animator->animations[i];
    }
  }

  for (uint32_t i = 0; i < remove_count; i++) {
    animator_remove(animator, remove[i]);
  }

  if (animator->animation_count == 0) animator_destroy_display_link(animator);
  return needs_refresh;
}

void animator_destroy(struct animator* animator) {
  if (animator->animation_count > 0) {
    if (animator->display_link)
      CVDisplayLinkStop(animator->display_link);
    CVDisplayLinkRelease(animator->display_link);
    animator->display_link = NULL;

    for (int i = 0; i < animator->animation_count; i++) {
      animation_destroy(animator->animations[i]);
    }
  }

  if (animator->animations) free(animator->animations);
}


================================================
FILE: src/animation.h
================================================
#pragma once
#include <CoreVideo/CoreVideo.h>
#include "misc/helpers.h"

extern struct bar_manager g_bar_manager;

#define ANIMATE(f, o, p, t) \
{\
  if (g_bar_manager.animator.duration > 0) { \
    animator_cancel_locked(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
    struct animation* animation = animation_create(); \
    animation_setup(animation, \
                    (void*)o, \
                    (bool (*)(void*, int))&f, \
                    p, \
                    t, \
                    g_bar_manager.animator.duration, \
                    g_bar_manager.animator.interp_function ); \
    animator_add(&g_bar_manager.animator, animation); \
  } else { \
    needs_refresh = animator_cancel(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
    needs_refresh |= f(o, t); \
  } \
}

#define ANIMATE_FLOAT(f, o, p, t) \
{\
  if (g_bar_manager.animator.duration > 0) { \
    animator_cancel_locked(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
    struct animation* animation = animation_create(); \
    float initial_value = p; \
    float final_value = t; \
    animation_setup(animation, \
                    (void*)o, \
                    (bool (*)(void*, int))&f, \
                    *(int*)&initial_value, \
                    *(int*)&final_value, \
                    g_bar_manager.animator.duration, \
                    g_bar_manager.animator.interp_function ); \
    animation->as_float = true; \
    animator_add(&g_bar_manager.animator, animation); \
  } else { \
    needs_refresh = animator_cancel(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
    needs_refresh |= f(o, t); \
  } \
}

#define ANIMATE_BYTES(f, o, p, t) \
{\
  if (g_bar_manager.animator.duration > 0) { \
    animator_cancel_locked(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
    struct animation* animation = animation_create(); \
    animation_setup(animation, \
                    (void*)o, \
                    (bool (*)(void*, int))&f, \
                    p, \
                    t, \
                    g_bar_manager.animator.duration, \
                    g_bar_manager.animator.interp_function ); \
    animation->separate_bytes = true; \
    animator_add(&g_bar_manager.animator, animation); \
  } else { \
    needs_refresh = animator_cancel(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
    needs_refresh |= f(o, t); \
  } \
}

#define ANIMATOR_FUNCTION(name) bool name(void* target, int value);
typedef ANIMATOR_FUNCTION(animator_function);

#define ANIMATION_FUNCTION(name) double name(double x);
typedef ANIMATION_FUNCTION(animation_function);

#define INTERP_FUNCTION_LINEAR    'l'
#define INTERP_FUNCTION_QUADRATIC 'q'
#define INTERP_FUNCTION_SIN       's'
#define INTERP_FUNCTION_TANH      't'
#define INTERP_FUNCTION_CIRC      'c'
#define INTERP_FUNCTION_BOUNCE    'b'
#define INTERP_FUNCTION_EXP       'e'
#define INTERP_FUNCTION_OVERSHOOT 'o'


struct animation {
  bool separate_bytes;
  bool as_float;
  bool locked;
  bool finished;
  bool waiting;

  uint64_t initial_time;
  double duration;

  int initial_value;
  int final_value;
  animation_function* interp_function;

  void* target;
  animator_function* update_function;

  struct animation* next;
  struct animation* previous;
};

struct animation* animation_create();
void animation_setup(struct animation* animation, void* target, animator_function* update_function, int initial_value, int final_value, uint32_t duration, char interp_function);

struct animator {
  CVDisplayLinkRef display_link;

  double clock;
  uint32_t interp_function;
  uint32_t duration;
  struct animation** animations;
  uint32_t animation_count;
};

void animator_init(struct animator* animator);
void animator_add(struct animator* animator, struct animation* animation);

bool animator_cancel(struct animator* animator, void* target, animator_function* function);
void animator_cancel_locked(struct animator* animator, void* target, animator_function* function);

bool animator_update(struct animator* animator, uint64_t time);
void animator_lock(struct animator* animator);
void animator_destroy(struct animator* animator);

void animator_renew_display_link(struct animator* animator);
void animator_destroy_display_link(struct animator* animator);


================================================
FILE: src/app_windows.c
================================================
#include "app_windows.h"
#include "workspace.h"
#include "misc/helpers.h"
#include "event.h"

extern pid_t g_pid;
struct app_windows g_windows = { 0 };
struct app_windows g_hidden_windows = { 0 };
bool g_space_window_events = false;

static bool iterator_window_suitable(CFTypeRef iterator) {
  uint64_t tags = SLSWindowIteratorGetTags(iterator);
  uint64_t attributes = SLSWindowIteratorGetAttributes(iterator);
  uint32_t parent_wid = SLSWindowIteratorGetParentID(iterator);
  if (((parent_wid == 0)
        && ((attributes & 0x2)
          || (tags & 0x400000000000000))
        && (((tags & 0x1))
          || ((tags & 0x2)
            && (tags & 0x80000000))))) {
    return true;
  }
  return false;
}

void app_window_clear(struct app_window* window) {
  memset(window, 0, sizeof(struct app_window));
}

void app_windows_add(struct app_windows* windows, struct app_window* window) {
  for (int i = 0; i < windows->num_windows; i++) {
    if (!windows->windows[i].wid) {
      windows->windows[i] = *window;
      return;
    }
  }

  windows->windows = realloc(windows->windows,
                             sizeof(struct app_window)
                             * ++windows->num_windows);

  windows->windows[windows->num_windows - 1] = *window;
}

void app_windows_clear_space(struct app_windows* windows, uint64_t sid) {
  for (int i = 0; i < windows->num_windows; i++) {
    if (windows->windows[i].sid == sid) app_window_clear(windows->windows + i);
  }
}

void app_windows_register_notifications() {
  uint32_t window_count = 0;
  uint32_t wid_list[g_windows.num_windows + g_hidden_windows.num_windows];
  for (int i = 0; i < g_windows.num_windows; i++) {
    if (g_windows.windows[i].wid)
      wid_list[window_count++] = g_windows.windows[i].wid;
  }

  for (int i = 0; i < g_hidden_windows.num_windows; i++) {
    if (g_hidden_windows.windows[i].wid)
      wid_list[window_count++] = g_hidden_windows.windows[i].wid;
  }
  SLSRequestNotificationsForWindows(g_connection, wid_list, window_count);
}

bool app_windows_find(struct app_windows* windows, struct app_window* window) {
  for (int i = 0; i < windows->num_windows; i++) {
    if (windows->windows[i].wid == window->wid
        && windows->windows[i].sid == window->sid) {
      return true;
    }
  }
  return false;
}

struct app_window* app_windows_find_by_wid(struct app_windows* windows, uint32_t wid) {
  for (int i = 0; i < windows->num_windows; i++) {
    if (windows->windows[i].wid == wid) return &windows->windows[i];
  }
  return NULL;
}

static bool app_window_suitable(struct app_window* window) {
  CFArrayRef target_ref = cfarray_of_cfnumbers(&window->wid,
                                               sizeof(uint32_t),
                                               1,
                                               kCFNumberSInt32Type);

  if (!target_ref) return false;

  bool suitable = false;
  CFTypeRef query = SLSWindowQueryWindows(g_connection, target_ref, 0x0);
  if (query) {
    CFTypeRef iterator = SLSWindowQueryResultCopyWindows(query);
    if (iterator && SLSWindowIteratorGetCount(iterator) > 0) {
      if (SLSWindowIteratorAdvance(iterator)) {
        if (iterator_window_suitable(iterator)) suitable = true;
      }
    }
    if (iterator) CFRelease(iterator);
    CFRelease(query);
  }
  CFRelease(target_ref);
  return suitable;
}

static void app_windows_post_event_for_space(struct app_windows* windows, uint64_t sid) {
  int index = mission_control_index(sid);
  pid_t pid_list[windows->num_windows];
  uint32_t pid_count[windows->num_windows];
  char* pid_name[windows->num_windows];

  memset(&pid_list, 0, sizeof(pid_t)*windows->num_windows);
  memset(&pid_count, 0, sizeof(uint32_t)*windows->num_windows);
  memset(&pid_name, 0, sizeof(char*)*windows->num_windows);

  uint32_t length = 64;
  for (int i = 0; i < windows->num_windows; i++) {
    for (int j = 0; j < windows->num_windows; j++) {
      if ((!pid_list[j] || pid_list[j] == windows->windows[i].pid)
          && windows->windows[i].sid == sid) {
        pid_list[j] = windows->windows[i].pid;
        pid_count[j]++;
        if (!pid_name[j]) {
          pid_name[j] = workspace_copy_app_name_for_pid(pid_list[j]);
          length += pid_name[j] ? (strlen(pid_name[j]) + 16) : 0;
        }
        break;
      }
    }
  }

  for (int i = 0; i < windows->num_windows; i++) {
    for (int j = i + 1; j < windows->num_windows; j++) {
      if (pid_name[i]
          && pid_name[j]
          && strcmp(pid_name[i], pid_name[j]) == 0) {
        free(pid_name[j]);
        pid_name[j] = NULL;

        pid_count[i] += pid_count[j];
      }
    }
  }

  char payload[length];
  memset(payload, 0, length);
  snprintf(payload, length, "{\n"
                            "\t\"space\": %d,\n"
                            "\t\"apps\": {\n",
                            index               );

  char* cursor = payload + strlen(payload);
  bool first = true;
  for (int i = 0; i < windows->num_windows; i++) {
    if (!pid_list[i]) break; 
    if (!pid_name[i]) continue;
    if (!first) {
      snprintf(cursor, length - (cursor - payload), ",\n");
      cursor = payload + strlen(payload);
    } else first = false;
    snprintf(cursor,
             length - (cursor - payload),
             "\t\t\"%s\": %d",
             pid_name[i],
             pid_count[i]                );

    free(pid_name[i]);
    cursor = payload + strlen(payload);
  }

  snprintf(cursor, length - (cursor - payload), "\n\t}\n}\n");
  struct event event = { payload, SPACE_WINDOWS_CHANGED };
  event_post(&event);
}

static void app_windows_update_space(struct app_windows* windows, uint64_t sid, bool silent) {
  app_windows_clear_space(windows, sid);
  CFArrayRef space_list_ref = cfarray_of_cfnumbers(&sid,
                                                   sizeof(uint64_t),
                                                   1,
                                                   kCFNumberSInt64Type);

  uint64_t set_tags = 1;
  uint64_t clear_tags = 0;
  CFArrayRef window_list = SLSCopyWindowsWithOptionsAndTags(g_connection,
                                                            0,
                                                            space_list_ref,
                                                            0x2,
                                                            &set_tags,
                                                            &clear_tags    );

  if (window_list) {
    uint32_t window_count = CFArrayGetCount(window_list);
    if (window_count > 0) {
      CFTypeRef query = SLSWindowQueryWindows(g_connection, window_list, 0x0);
      if (query) {
        CFTypeRef iterator = SLSWindowQueryResultCopyWindows(query);
        if (iterator) {
          while(SLSWindowIteratorAdvance(iterator)) {
            if (iterator_window_suitable(iterator)) {
              uint32_t wid = SLSWindowIteratorGetWindowID(iterator);
              int wid_cid = 0;
              SLSGetWindowOwner(g_connection, wid, &wid_cid);

              pid_t pid = 0;
              SLSConnectionGetPID(wid_cid, &pid);
              struct app_window window = {.wid = wid, .sid = sid, .pid = pid};
              app_windows_add(windows, &window);
            }
          }
          CFRelease(iterator);
        }
        CFRelease(query);
      }
    }
    CFRelease(window_list);
  }

  CFRelease(space_list_ref);
  if (!silent) app_windows_post_event_for_space(windows, sid);
  app_windows_register_notifications();
}

struct window_spawn_data {
  uint64_t sid;
  uint32_t wid;
};

static void window_spawn_handler(uint32_t event, struct window_spawn_data* data, size_t _, int cid) {
  uint32_t wid = data->wid;
  uint64_t sid = data->sid;

  if (!wid || !sid) return;

  struct app_window window = { .wid = wid, .sid = sid, .pid = 0 };

  if (event == 1325 && app_window_suitable(&window)) {
    app_windows_update_space(&g_windows, sid, false);
  } else if (event == 1326 && app_windows_find(&g_windows, &window)) {
    app_windows_update_space(&g_windows, sid, false);
    struct app_window* window = app_windows_find_by_wid(&g_hidden_windows,
                                                        wid               );
    if (window) app_window_clear(window);
  }
}

static void window_hide_handler(uint32_t event, uint32_t* window_id, size_t _, int cid) {
  uint32_t wid = *window_id;

  if (event == 816) {
    struct app_window* window = app_windows_find_by_wid(&g_windows, wid);
    if (window) {
      if (!app_windows_find(&g_hidden_windows, window)) {
        app_windows_add(&g_hidden_windows, window);
      }
      app_windows_update_space(&g_windows, window->sid, false);
    }
  } else if (event == 815) {
    struct app_window* window = app_windows_find_by_wid(&g_hidden_windows, wid);
    if (window) {
      app_windows_update_space(&g_windows, window->sid, false);
      app_window_clear(window);
      app_windows_register_notifications();
    }
  }
}

static void update_all_spaces(struct app_windows* windows, bool silent) {
  uint32_t display_count = 0;
  uint32_t* displays = display_active_display_list(&display_count);
  for (int i = 0; i < display_count; i++) {
    int space_count = 0;
    uint64_t* spaces = display_space_list(displays[i], &space_count);
    for (int j = 0; j < space_count; j++) {
      app_windows_update_space(windows, spaces[j], silent);
    }
    if (spaces) free(spaces);
  }
  if (displays) free(displays);
}

static void space_handler(uint32_t event, void* data, size_t data_length, void* context) {
  update_all_spaces(&g_windows, event == 1401);
}

void forced_space_windows_event() {
  if (g_space_window_events) update_all_spaces(&g_windows, false);
}

void begin_receiving_space_window_events() {
  if (!g_space_window_events) {
    SLSRegisterNotifyProc(window_spawn_handler,
                          1325,
                          (void*)(intptr_t)g_connection);

    SLSRegisterNotifyProc(window_spawn_handler,
                          1326,
                          (void*)(intptr_t)g_connection);

    SLSRegisterNotifyProc(window_hide_handler,
                          815,
                          (void*)(intptr_t)g_connection);

    SLSRegisterNotifyProc(window_hide_handler,
                          816,
                          (void*)(intptr_t)g_connection);

    SLSRegisterNotifyProc((void*)space_handler, 1401, NULL);
    if (__builtin_available(macOS 13.0, *)) {
      SLSRegisterNotifyProc((void*)space_handler, 1327, NULL);
      SLSRegisterNotifyProc((void*)space_handler, 1328, NULL);
    }

    g_space_window_events = true;
    update_all_spaces(&g_windows, true);
  }
}


================================================
FILE: src/app_windows.h
================================================
#pragma once
#include "event.h"

struct app_window {
  uint32_t wid;
  uint64_t sid;
  pid_t pid;
};

struct app_windows {
  struct app_window* windows;
  uint32_t num_windows;
};

void begin_receiving_space_window_events();
void forced_space_windows_event();


================================================
FILE: src/background.c
================================================
#include "background.h"
#include "image.h"
#include "misc/helpers.h"
#include "shadow.h"
#include "animation.h"
#include "bar_manager.h"

void background_init(struct background* background) {
  background->enabled = false;
  background->clip = 0.f;
  background->clips = NULL;
  background->num_clips = 0;
  background->overrides_height = false;

  background->bounds.size.height = 0;
  background->bounds.size.width = 0;
  background->border_width = 0;
  background->padding_left = 0;
  background->padding_right = 0;
  background->corner_radius = 0;
  background->x_offset = 0;
  background->y_offset = 0;

  color_init(&background->color, 0x00000000);
  color_init(&background->border_color, 0x00000000);
  shadow_init(&background->shadow);
  image_init(&background->image);
}

bool background_set_height(struct background* background, uint32_t height) {
  if (background->bounds.size.height == height) return false;
  background->bounds.size.height = height;
  background->overrides_height = height != 0;
  return true;
}

static void background_reset_clip(struct background* background) {
  for (uint32_t i = 0; i < background->num_clips; i++)
    free(background->clips[i]);

  if (background->clips) free(background->clips);
  background->clips = NULL;
  background->num_clips = 0;
}

bool background_set_enabled(struct background* background, bool enabled) {
  if (background->enabled == enabled) return false;

  if (background_clips_bar(background)) {
    background_reset_clip(background);
    g_bar_manager.bar_needs_update = true;
  }

  background->enabled = enabled;

  return true;
}

bool background_set_color(struct background* background, uint32_t color) {
  bool changed = background_set_enabled(background, true);
  return color_set_hex(&background->color, color) || changed;
}

static bool background_set_clip(struct background* background, float clip) {
  if (background->clip == clip) return false;
  background->clip = clip;
  g_bar_manager.bar_needs_update = true;
  g_bar_manager.might_need_clipping = true;
  if (clip > 0.f) background_set_enabled(background, true);
  return true;
}

static bool background_set_border_color(struct background* background, uint32_t color) {
  return color_set_hex(&background->border_color, color);
}

static bool background_set_border_width(struct background* background, uint32_t border_width) {
  if (background->border_width == border_width) return false;
  background->border_width = border_width;
  return true;
}

static bool background_set_corner_radius(struct background* background, uint32_t corner_radius) {
  if (background->corner_radius == corner_radius) return false;
  background->corner_radius = corner_radius;
  return true;
}

static bool background_set_xoffset(struct background* background, int offset) {
  if (background->x_offset == offset) return false;
  background->x_offset = offset;
  return true;
}

static bool background_set_yoffset(struct background* background, int offset) {
  if (background->y_offset == offset) return false;
  background->y_offset = offset;
  return true;
}

bool background_set_padding_left(struct background* background, uint32_t pad) {
  if (background->padding_left == pad) return false;
  background->padding_left = pad;
  return true;
}

bool background_set_padding_right(struct background* background, uint32_t pad) {
  if (background->padding_right == pad) return false;
  background->padding_right = pad;
  return true;
}

bool background_clip_needs_update(struct background* background, struct bar* bar) {
  if (background->clip == 0.f || !background->enabled) return false;
  struct background* clip = background_get_clip(background, bar->adid);
  if (!CGRectEqualToRect(background->bounds, clip->bounds)) return true;
  if (background->corner_radius != clip->corner_radius) return true;
  if (background->x_offset != clip->x_offset) return true;
  if (background->y_offset != clip->y_offset) return true;
  return false;
}

static void background_update_clip(struct background* background, struct background* clip) {
  memcpy(clip, background, sizeof(struct background));
  background_clear_pointers(clip);
}

struct background* background_get_clip(struct background* background, uint32_t adid) {
  if (adid < 1) return NULL;
  if (background->num_clips < adid) {
    background->clips = (struct background**) realloc(background->clips,
                                                sizeof(struct background*)*adid);
    memset(background->clips + background->num_clips,
           0,
           sizeof(struct background*) * (adid - background->num_clips));

    background->num_clips = adid;
  }

  if (!background->clips[adid - 1]) {
    struct background* clip = malloc(sizeof(struct background));
    background->clips[adid - 1] = clip;
    background_init(clip);
    background_update_clip(background, clip);
    clip->bounds.origin = g_nirvana;
  }

  return background->clips[adid - 1];
}

bool background_clips_bar(struct background* background) {
  return background->enabled && (background->clip > 0.f);
}

void background_clip_bar(struct background* background, int offset, struct bar* bar) {
  if (!background_clips_bar(background)) return;

  struct background* clip = background_get_clip(background, bar->adid);
  background_update_clip(background, clip);

  CGRect background_bounds = background->bounds;
  background_bounds.origin.x += offset + background->x_offset;
  background_bounds.origin.y += background->y_offset;

  clip_rect(bar->window.context,
            background_bounds,
            background->clip,
            background->corner_radius);
}

void background_calculate_bounds(struct background* background, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
  background->bounds.origin.x = x;
  background->bounds.origin.y = y - height / 2;
  background->bounds.size.width = width;
  background->bounds.size.height = height;

  if (background->image.enabled)
    image_calculate_bounds(&background->image, x, y);
}

static void draw_rect(CGContextRef context, CGRect region, struct color* fill_color, uint32_t corner_radius, uint32_t line_width, struct color* stroke_color) {
  CGContextSetLineWidth(context, line_width);
  if (stroke_color) CGContextSetRGBStrokeColor(context, stroke_color->r, stroke_color->g, stroke_color->b, stroke_color->a);
  CGContextSetRGBFillColor(context, fill_color->r, fill_color->g, fill_color->b, fill_color->a);

  CGMutablePathRef path = CGPathCreateMutable();
  CGRect inset_region = CGRectInset(region, (float)(line_width) / 2.f, (float)(line_width) / 2.f);
  if (corner_radius > inset_region.size.height / 2.f || corner_radius > inset_region.size.width / 2.f)
    corner_radius = inset_region.size.height > inset_region.size.width ? inset_region.size.width / 2.f : inset_region.size.height / 2.f; 
  CGPathAddRoundedRect(path, NULL, inset_region, corner_radius, corner_radius);
  CGContextAddPath(context, path);
  CGContextDrawPath(context, kCGPathFillStroke);
  CFRelease(path);
}

void background_draw(struct background* background, CGContextRef context) {
  if (!background->enabled) return;

  if ((background->border_color.a == 0 || background->border_width == 0)
      && (background->color.a == 0)
      && !background->shadow.enabled
      && !background->image.enabled                                      ) {
    // The background is enabled but has no content.
    return;
  }

  CGRect background_bounds = background->bounds;
  background_bounds.origin.x += background->x_offset;
  background_bounds.origin.y += background->y_offset;
  if (background->shadow.enabled) {
    CGRect bounds = shadow_get_bounds(&background->shadow, background_bounds);
    draw_rect(context,
              bounds,
              &background->shadow.color,
              background->corner_radius,
              background->border_width,
              &background->shadow.color);
  }

  draw_rect(context,
            background_bounds,
            &background->color,
            background->corner_radius,
            background->border_width,
            &background->border_color);

  if (background->image.enabled)
    image_draw(&background->image, context);

}

void background_clear_pointers(struct background* background) {
  background->clips = NULL;
  background->num_clips = 0;
  image_clear_pointers(&background->image);
}

void background_destroy(struct background* background) {
  for (uint32_t i = 0; i < background->num_clips; i++)
    free(background->clips[i]);

  if (background->clips) free(background->clips);

  image_destroy(&background->image);
  background_clear_pointers(background);
}

void background_serialize(struct background* background, char* indent, FILE* rsp, bool detailed) {
  fprintf(rsp, "%s\"drawing\": \"%s\",\n"
               "%s\"color\": \"0x%x\",\n"
               "%s\"border_color\": \"0x%x\",\n"
               "%s\"border_width\": %u,\n"
               "%s\"height\": %u,\n"
               "%s\"corner_radius\": %u,\n"
               "%s\"padding_left\": %d,\n"
               "%s\"padding_right\": %d,\n"
               "%s\"x_offset\": %d,\n"
               "%s\"y_offset\": %d,\n"
               "%s\"clip\": %f,\n",
               indent, format_bool(background->enabled),
               indent, background->color.hex,
               indent, background->border_color.hex,
               indent, background->border_width,
               indent, background->overrides_height ? (int)background->bounds.size.height : 0,
               indent, background->corner_radius,
               indent, background->padding_left,
               indent, background->padding_right,
               indent, background->x_offset,
               indent, background->y_offset,
               indent, background->clip                                                       );

  char deeper_indent[strlen(indent) + 2];
  snprintf(deeper_indent, strlen(indent) + 2, "%s\t", indent);

  fprintf(rsp, "%s\"image\": {\n", indent);
  image_serialize(&background->image, deeper_indent, rsp);
  fprintf(rsp, "\n%s}", indent);

  if (!detailed) return;

  fprintf(rsp, ",\n%s\"shadow\": {\n", indent);
  shadow_serialize(&background->shadow, deeper_indent, rsp);
  fprintf(rsp, "\n%s}", indent);
}

bool background_parse_sub_domain(struct background* background, FILE* rsp, struct token property, char* message) {
  bool needs_refresh = false;
  if (token_equals(property, PROPERTY_DRAWING))
    return background_set_enabled(background,
                                  evaluate_boolean_state(get_token(&message),
                                                         background->enabled));
  else if (token_equals(property, PROPERTY_CLIP)) {
    struct token token = get_token(&message);
    ANIMATE_FLOAT(background_set_clip,
                  background,
                  background->clip,
                  token_to_float(token));
  } else if (token_equals(property, PROPERTY_HEIGHT)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_height,
            background,
            background->bounds.size.height,
            token_to_int(token)            );
  }
  else if (token_equals(property, PROPERTY_CORNER_RADIUS)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_corner_radius,
            background,
            background->corner_radius,
            token_to_int(token)          );
  }
  else if (token_equals(property, PROPERTY_BORDER_WIDTH)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_border_width,
            background,
            background->border_width,
            token_to_int(token)         );
  }
  else if (token_equals(property, PROPERTY_COLOR)) {
    struct token token = get_token(&message);
    ANIMATE_BYTES(background_set_color,
                  background,
                  background->color.hex,
                  token_to_int(token)   );
  }
  else if (token_equals(property, PROPERTY_BORDER_COLOR)) {
    struct token token = get_token(&message);
    ANIMATE_BYTES(background_set_border_color,
                  background,
                  background->border_color.hex,
                  token_to_int(token)          );
  }
  else if (token_equals(property, PROPERTY_PADDING_LEFT)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_padding_left,
            background,
            background->padding_left,
            token_to_int(token)         );
  }
  else if (token_equals(property, PROPERTY_PADDING_RIGHT)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_padding_right,
            background,
            background->padding_right,
            token_to_int(token)         );
  }
  else if (token_equals(property, PROPERTY_XOFFSET)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_xoffset,
            background,
            background->x_offset,
            token_to_int(token)    );
  }
  else if (token_equals(property, PROPERTY_YOFFSET)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_yoffset,
            background,
            background->y_offset,
            token_to_int(token)    );
  }
  else if (token_equals(property, SUB_DOMAIN_IMAGE)) {
    return image_load(&background->image,
                      token_to_string(get_token(&message)),
                      rsp                                  );
  }
  else {
    struct key_value_pair key_value_pair = get_key_value_pair(property.text,
                                                              '.'           );
    if (key_value_pair.key && key_value_pair.value) {
      struct token subdom = {key_value_pair.key,strlen(key_value_pair.key)};
      struct token entry = {key_value_pair.value,strlen(key_value_pair.value)};
      if (token_equals(subdom, SUB_DOMAIN_SHADOW))
        return shadow_parse_sub_domain(&background->shadow,
                                       rsp,
                                       entry,
                                       message             );
      else if (token_equals(subdom, SUB_DOMAIN_IMAGE)) {
        return image_parse_sub_domain(&background->image, rsp, entry, message);
      }
      else if (token_equals(subdom, SUB_DOMAIN_COLOR)) {
        return color_parse_sub_domain(&background->color, rsp, entry, message);
      }
      else if (token_equals(subdom, SUB_DOMAIN_BORDER_COLOR)) {
        return color_parse_sub_domain(&background->border_color,
                                      rsp,
                                      entry,
                                      message                   );
      }
      else {
        respond(rsp, "[!] Background: Invalid subdomain '%s'\n", subdom.text);
      }
    }
    else {
      respond(rsp, "[!] Background: Invalid property '%s'\n", property.text);
    }
  }
  return needs_refresh;
}


================================================
FILE: src/background.h
================================================
#pragma once
#include "image.h"

struct background {
  bool enabled;
  float clip;
  bool overrides_height;

  int padding_left;
  int padding_right;
  int x_offset;
  int y_offset;
  uint32_t border_width;
  uint32_t corner_radius;

  CGRect bounds;
  struct image image;
  struct shadow shadow;
  struct color color;
  struct color border_color;

  struct background** clips;
  uint32_t num_clips;
};

struct bar;

void background_init(struct background* background);
void background_calculate_bounds(struct background* background, uint32_t x, uint32_t y, uint32_t width, uint32_t height);

bool background_set_enabled(struct background* background, bool enabled);
bool background_set_color(struct background* background, uint32_t color);
bool background_set_height(struct background* background, uint32_t height);
bool background_set_padding_left(struct background* background, uint32_t pad);
bool background_set_padding_right(struct background* background, uint32_t pad);

void background_draw(struct background* background, CGContextRef context);

struct background* background_get_clip(struct background* background, uint32_t adid);
void background_clip_bar(struct background* background, int offset, struct bar* bar);
bool background_clip_needs_update(struct background* background, struct bar* bar);
bool background_clips_bar(struct background* background);

void background_clear_pointers(struct background* background);
void background_destroy(struct background* background);

void background_serialize(struct background* background, char* indent, FILE* rsp, bool detailed);
bool background_parse_sub_domain(struct background* background, FILE* rsp, struct token property, char* message);


================================================
FILE: src/bar.c
================================================
#include "bar.h"
#include "bar_manager.h"
#include "event.h"
#include "display.h"
#include "misc/helpers.h"
#include "window.h"

#define MAX_RENDER_THREADS 10
static pthread_t g_render_threads[MAX_RENDER_THREADS];
static uint32_t g_used_threads = 0;

void join_render_threads() {
  for (int i = 0; i < g_used_threads; i++)
    pthread_join(g_render_threads[i], NULL);
  g_used_threads = 0;
}

bool bar_draws_item(struct bar* bar, struct bar_item* bar_item) {
    if (!bar_item->drawing || !bar->shown || bar->hidden) return false;

    if (((bar_item->associated_display > 0
          && (!(bar_item->associated_display & (1 << bar->adid))))
        || (bar_item->associated_to_active_display
            && (bar->adid != g_bar_manager.active_adid)))
        && !bar_item->ignore_association)
      return false;

    if (bar_item->associated_space > 0
        && (!(bar_item->associated_space & (1 << bar->sid))
            && !bar_item->ignore_association)
        && (bar_item->type != BAR_COMPONENT_SPACE)        )
      return false;

    if (bar_item->position == POSITION_POPUP
        && (!bar_item->parent
            || !bar_item->parent->popup.drawing
            || (bar->adid != g_bar_manager.active_adid)))
      return false;

    return true;
}

static void bar_calculate_popup_anchor_for_bar_item(struct bar* bar, struct bar_item* bar_item) {
  if (bar->adid != g_bar_manager.active_adid) return;
  struct window* window = bar_item_get_window(bar_item, bar->adid);

  if (!bar_item->popup.overrides_cell_size) {
    if (g_bar_manager.position == POSITION_LEFT
        || g_bar_manager.position == POSITION_RIGHT) {
      bar_item->popup.cell_size = window->frame.size.width;
    } else {
      bar_item->popup.cell_size = window->frame.size.height;
    }
  }

  popup_calculate_bounds(&bar_item->popup, bar);

  CGPoint anchor = window->origin;

  if (g_bar_manager.position == POSITION_LEFT
      || g_bar_manager.position == POSITION_RIGHT) {
    if (bar_item->popup.align == POSITION_CENTER) {
      anchor.y += (window->frame.size.height
                   - bar_item->popup.background.bounds.size.height) / 2;
    } else if (bar_item->popup.align == POSITION_LEFT) {
      anchor.y -= bar_item->background.padding_left;
    } else {
      anchor.y += window->frame.size.height
                  - bar_item->popup.background.bounds.size.height;
    }
    anchor.x += (g_bar_manager.position == POSITION_RIGHT
                ? (- bar_item->popup.background.bounds.size.width)
                : window->frame.size.width);
  } else {
    if (bar_item->popup.align == POSITION_CENTER) {
      anchor.x += (window->frame.size.width
                   - bar_item->popup.background.bounds.size.width) / 2;
    } else if (bar_item->popup.align == POSITION_LEFT) {
      anchor.x -= bar_item->background.padding_left;
    } else {
      anchor.x += window->frame.size.width
                  - bar_item->popup.background.bounds.size.width;
    }
    anchor.y += (g_bar_manager.position == POSITION_BOTTOM
                ? (- bar_item->popup.background.bounds.size.height)
                : window->frame.size.height);
  }
  popup_set_anchor(&bar_item->popup, anchor, bar->adid);
  popup_calculate_bounds(&bar_item->popup, bar);
}

void bar_order_item_windows(struct bar* bar) {
  if (bar->sid < 1 || bar->adid < 1 || !bar->shown) return;
  window_set_level(&bar->window, g_bar_manager.window_level);
  window_order(&bar->window, NULL, W_ABOVE);

  struct window* previous_window = NULL;
  struct window* first_window = NULL;
  for (int i = 0; i < g_bar_manager.bar_item_count; i++) {
    struct bar_item* bar_item = g_bar_manager.bar_items[i];
    if (bar_item->position == POSITION_POPUP) continue;

    struct window* window = bar_item_get_window(bar_item, bar->adid);
    window_set_level(window, g_bar_manager.window_level);

    if (!first_window) first_window = window;

    if (bar_item->type == BAR_COMPONENT_GROUP) {
      if (first_window)
        window_order(window, first_window, W_BELOW);
      else
        window_order(window, &bar->window, W_ABOVE);
      continue;
    }

    if (previous_window) window_order(window, previous_window, W_ABOVE);
    else window_order(window, &bar->window, W_ABOVE);

    previous_window = window;
  }
}

static void bar_check_for_clip_updates(struct bar* bar) {
  if (!g_bar_manager.bar_needs_update) {
    for (int i = 0; i < g_bar_manager.bar_item_count; i++) {
      struct bar_item* bar_item = g_bar_manager.bar_items[i];
      struct window* window = bar_item_get_window(bar_item, bar->adid);

      bool clips_bar = bar_item_clips_bar(bar_item);
      if (!clips_bar || (!bar_draws_item(bar, bar_item))) {

        if (clips_bar && !CGPointEqualToPoint(window->origin, g_nirvana)) {
          g_bar_manager.bar_needs_update = true;
          break;
        }

        continue;
      }

      g_bar_manager.bar_needs_update
                       |= window->needs_move
                          || window->needs_resize
                          || bar_item_clip_needs_update_for_bar(bar_item, bar);

      if (g_bar_manager.bar_needs_update) break;
    }
  }
}

void bar_draw(struct bar* bar, bool forced, bool threaded) {
  if (bar->sid < 1 || bar->adid < 1) return;

  if (g_bar_manager.might_need_clipping)
    bar_check_for_clip_updates(bar);

  if (g_bar_manager.bar_needs_update) {
    struct background background = g_bar_manager.background;
    background.bounds = bar->window.frame;
    background.bounds.origin.y -= background.y_offset;
    background.shadow.enabled = false;
    background.enabled = true;
    windows_freeze();
    CGContextClearRect(bar->window.context, bar->window.frame);
    background_draw(&background, bar->window.context);
  }

  for (int i = 0; i < g_bar_manager.bar_item_count; i++) {
    struct bar_item* bar_item = g_bar_manager.bar_items[i];
    struct window* window = bar_item_get_window(bar_item, bar->adid);

    if (!bar_draws_item(bar, bar_item)){
      if (!CGPointEqualToPoint(window->origin, g_nirvana)) {
        window_move(window, g_nirvana);
      }

      bar_item_remove_associated_bar(bar_item, bar->adid);
      continue;
    }

    bar_item_append_associated_bar(bar_item, bar->adid);

    if (bar_item->popup.drawing && bar->adid == g_bar_manager.active_adid)
      popup_draw(&bar_item->popup);

    if (g_bar_manager.bar_needs_update) {
      bar_item_clip_bar(bar_item,
                        window->origin.x - bar->window.origin.x,
                        bar                                     );
    }

    if (!window_apply_frame(window, forced) && !bar_item->needs_update)
      continue;

    if (bar_item->update_mask & UPDATE_MOUSE_ENTERED
        || bar_item->update_mask & UPDATE_MOUSE_EXITED) {
      window_assign_mouse_tracking_area(window, window->frame);
    }

    windows_freeze();
    if (threaded && g_used_threads < MAX_RENDER_THREADS) {
      uint32_t thread_id = g_used_threads++;
      struct draw_item_payload {
        struct window* window;
        struct bar_item bar_item;
      }* context = malloc(sizeof(struct draw_item_payload));
      // We need to perform a shallow copy of the item here because
      // the cached bounds will be invalidated when drawing the next bar.
      context->bar_item = *bar_item;
      context->window = window;
      pthread_create(&g_render_threads[thread_id],
                     NULL,
                     draw_item_proc,
                     context        );
    } else {
      CGContextClearRect(window->context, window->frame);
      bar_item_draw(bar_item, window->context);
      CGContextFlush(window->context);
      window_flush(window);
    }
  }

  if (g_bar_manager.bar_needs_update) {
    CGContextFlush(bar->window.context);
    window_flush(&bar->window);
  }
}

static void bar_calculate_bounds_top_bottom(struct bar* bar) {
  bool is_builtin = CGDisplayIsBuiltin(bar->did);
  uint32_t notch_width = is_builtin ? g_bar_manager.notch_width : 0;

  uint32_t center_length = bar_manager_length_for_bar_side(&g_bar_manager,
                                                           bar,
                                                           POSITION_CENTER);

  uint32_t bar_left_first_item_x = max(g_bar_manager.background.padding_left,
                                       0                                     );

  uint32_t bar_right_first_item_x = bar->window.frame.size.width
                                   -max(g_bar_manager.background.padding_right,
                                          0                                  );

  uint32_t bar_center_first_item_x = (bar->window.frame.size.width
                                      - center_length) / 2;

  uint32_t bar_center_right_first_item_x = (bar->window.frame.size.width
                                            + notch_width) / 2;

  uint32_t bar_center_left_first_item_x = (bar->window.frame.size.width
                                           - notch_width) / 2;

  uint32_t* next_position = NULL;
  uint32_t y = bar->window.frame.size.height / 2;

  for (int i = 0; i < g_bar_manager.bar_item_count; i++) {
    struct bar_item* bar_item = g_bar_manager.bar_items[i];

    if (!bar_draws_item(bar, bar_item)
        || bar_item->type == BAR_COMPONENT_GROUP
        || bar_item->position == POSITION_POPUP ) {
      continue;
    } 

    uint32_t bar_item_display_length = bar_item_get_length(bar_item, true);
    bool rtl = false;

    if (bar_item->position == POSITION_LEFT)
      next_position = &bar_left_first_item_x;
    else if (bar_item->position == POSITION_CENTER)
      next_position = &bar_center_first_item_x;
    else if (bar_item->position == POSITION_RIGHT)
      next_position = &bar_right_first_item_x, rtl = true;
    else if (bar_item->position == POSITION_CENTER_RIGHT)
      next_position = &bar_center_right_first_item_x;
    else if (bar_item->position == POSITION_CENTER_LEFT)
      next_position = &bar_center_left_first_item_x, rtl = true;
    else continue;

    if (bar_item->position == POSITION_RIGHT
        || bar_item->position == POSITION_CENTER_LEFT) {
      *next_position = min(*next_position - bar_item_display_length
                           - bar_item->background.padding_right,
                           bar->window.frame.size.width
                           - bar_item_display_length               );
    }
    else {
      *next_position += max((int)-*next_position,
                            bar_item->background.padding_left);
    }

    bar_item->graph.rtl = rtl;

    CGPoint shadow_offsets = bar_item_calculate_shadow_offsets(bar_item);
    uint32_t bar_item_length = bar_item_calculate_bounds(bar_item,
                                 bar->window.frame.size.height
                                 - (g_bar_manager.background.border_width + 1),
                                 max(shadow_offsets.x, 0),
                                 y                                           );

    CGRect frame = {{bar->window.origin.x + *next_position
                    - max(shadow_offsets.x, 0),
                     bar->window.origin.y                 },
                    {bar_item_display_length
                      + shadow_offsets.x
                      + shadow_offsets.y,
                     bar->window.frame.size.height}         };

    window_set_frame(bar_item_get_window(bar_item, bar->adid), frame);

    if (bar_item->popup.drawing)
      bar_calculate_popup_anchor_for_bar_item(bar, bar_item);

    if (bar_item->position == POSITION_RIGHT
        || bar_item->position == POSITION_CENTER_LEFT) {
      *next_position += bar_item->has_const_width
                        ? bar_item_display_length
                          + bar_item->background.padding_right
                          - bar_item->custom_width
                        : (- bar_item->background.padding_left);
    } else {
      *next_position += bar_item->has_const_width
                        ? bar_item->custom_width
                          - bar_item->background.padding_left
                        : (bar_item_length
                           + bar_item->background.padding_right);
    }
  }

  for (int i = 0; i < g_bar_manager.bar_item_count; i++) {
    struct bar_item* bar_item = g_bar_manager.bar_items[i];

    if (bar_item->type != BAR_COMPONENT_GROUP
        || bar_item->position == POSITION_POPUP
        || !bar_draws_item(bar, bar_item)) {
      continue;
    }

    group_calculate_bounds(bar_item->group, bar, y);
    window_set_frame(bar_item_get_window(bar_item->group->members[0],
                                         bar->adid                   ),
                     bar_item->group->bounds                           );

    if (bar_item->popup.drawing)
      bar_calculate_popup_anchor_for_bar_item(bar, bar_item);
  }
}

static void bar_calculate_bounds_left_right(struct bar* bar) {
  uint32_t notch_width = 0;

  uint32_t center_length = bar_manager_length_for_bar_side(&g_bar_manager,
                                                           bar,
                                                           POSITION_CENTER);

  uint32_t bar_left_first_item_y = max(g_bar_manager.background.padding_left,
                                       0                                     );

  uint32_t bar_right_first_item_y = bar->window.frame.size.height
                                   -max(g_bar_manager.background.padding_right,
                                          0                                  );

  uint32_t bar_center_first_item_y = (bar->window.frame.size.height
                                      - 2*g_bar_manager.margin
                                      - center_length) / 2 - 1;

  uint32_t bar_center_right_first_item_y = (bar->window.frame.size.height
                                            + notch_width) / 2;

  uint32_t bar_center_left_first_item_y = (bar->window.frame.size.height
                                           - notch_width) / 2 ;

  uint32_t* next_position = NULL;

  for (int i = 0; i < g_bar_manager.bar_item_count; i++) {
    struct bar_item* bar_item = g_bar_manager.bar_items[i];

    if (!bar_draws_item(bar, bar_item)
        || bar_item->type == BAR_COMPONENT_GROUP
        || bar_item->position == POSITION_POPUP ) {
      continue;
    } 

    uint32_t bar_item_display_height = bar_item_get_height(bar_item);
    uint32_t bar_item_display_length = bar_item_get_length(bar_item, true);
    uint32_t x =  0;
    bool rtl = false;

    if (bar_item->position == POSITION_LEFT)
      next_position = &bar_left_first_item_y;
    else if (bar_item->position == POSITION_CENTER)
      next_position = &bar_center_first_item_y;
    else if (bar_item->position == POSITION_RIGHT)
      next_position = &bar_right_first_item_y, rtl = true;
    else if (bar_item->position == POSITION_CENTER_RIGHT)
      next_position = &bar_center_right_first_item_y;
    else if (bar_item->position == POSITION_CENTER_LEFT)
      next_position = &bar_center_left_first_item_y, rtl = true;
    else continue;

    if (bar_item->position == POSITION_RIGHT
        || bar_item->position == POSITION_CENTER_LEFT) {

      *next_position = min(*next_position - bar_item_display_height
                           - bar_item->background.padding_right,
                           bar->window.frame.size.height
                           - bar_item_display_height               );
    }
    else {
      *next_position += max((int)-*next_position,
                            bar_item->background.padding_left);
    }

    bar_item->graph.rtl = rtl;

    CGPoint shadow_offsets = bar_item_calculate_shadow_offsets(bar_item);
    bar_item_calculate_bounds(bar_item,
                              bar_item_display_height,
                              (g_bar_manager.background.bounds.size.height
                               - bar_item_display_length) / 2.
                              + max(shadow_offsets.x, 0),
                              bar_item_display_height / 2.);


    CGRect frame = {{bar->window.origin.x + x
                     - max(shadow_offsets.x, 0),
                     bar->window.origin.y
                     + *next_position
                     + -max(-bar_item->y_offset, 0)},
                    {g_bar_manager.background.bounds.size.height,
                     bar_item_display_height + abs(bar_item->y_offset)}};

    window_set_frame(bar_item_get_window(bar_item, bar->adid), frame);

    if (bar_item->popup.drawing)
      bar_calculate_popup_anchor_for_bar_item(bar, bar_item);

    if (bar_item->position == POSITION_RIGHT
        || bar_item->position == POSITION_CENTER_LEFT) {
      *next_position += bar_item->has_const_width
                        ? bar_item_display_height
                          + bar_item->background.padding_right
                          - bar_item->custom_width
                        : - bar_item->background.padding_left;
    } else {
      *next_position += bar_item->has_const_width
                        ? bar_item->custom_width
                          - bar_item->background.padding_left
                        : (bar_item_display_height
                           + bar_item->background.padding_right);
    }
  }
}

void bar_calculate_bounds(struct bar* bar) {
  if (bar->sid < 1 || bar->adid < 1) return;

  if (g_bar_manager.position == POSITION_LEFT
      || g_bar_manager.position == POSITION_RIGHT) {
    bar_calculate_bounds_left_right(bar);
  } else {
    bar_calculate_bounds_top_bottom(bar);
  }
}

static CGRect bar_get_frame(struct bar *bar) {
  bool is_builtin = CGDisplayIsBuiltin(bar->did);
  int notch_offset = is_builtin ? g_bar_manager.notch_offset : 0;
  int notch_display_height = is_builtin ? g_bar_manager.notch_display_height : 0;


  CGRect bounds = display_bounds(bar->did);
  CGPoint origin = bounds.origin;

  if (g_bar_manager.position == POSITION_LEFT
      || g_bar_manager.position == POSITION_RIGHT) {
    bounds.size.height -= 2*g_bar_manager.background.y_offset;

    origin.x += (g_bar_manager.position == POSITION_RIGHT
                 ? (bounds.size.width
                    - g_bar_manager.background.bounds.size.height
                    - g_bar_manager.margin)
                 : g_bar_manager.margin);

    origin.y += g_bar_manager.background.y_offset;

    if (display_menu_bar_visible() && !g_bar_manager.topmost) {
      CGRect menu = display_menu_bar_rect(bar->did);
      origin.y += menu.size.height;
      bounds.size.height -= menu.size.height;
    }

    return (CGRect) {{origin.x, origin.y},
                     {g_bar_manager.background.bounds.size.height,
                      bounds.size.height                          }};
  } else {
    bounds.size.width -= 2*g_bar_manager.margin;
    CGPoint origin = bounds.origin;
    origin.x += g_bar_manager.margin;
    origin.y += g_bar_manager.background.y_offset + notch_offset;


    if (g_bar_manager.position == POSITION_BOTTOM) {
      origin.y = CGRectGetMaxY(bounds)
                 - g_bar_manager.background.bounds.size.height
                 - 2*(g_bar_manager.background.y_offset) - notch_offset;
    } else if (display_menu_bar_visible() && !g_bar_manager.topmost) {
      CGRect menu = display_menu_bar_rect(bar->did);
      origin.y += menu.size.height;
    }


    if (notch_display_height > 0) {
      return (CGRect) {{origin.x, origin.y},
                        {bounds.size.width,
                        g_bar_manager.notch_display_height}};
    }
    
    return (CGRect) {{origin.x, origin.y},
                      {bounds.size.width,
                      g_bar_manager.background.bounds.size.height}};
  }
}

void bar_resize(struct bar* bar) {
  if (bar->hidden || !bar->shown) {
    window_move(&bar->window, g_nirvana);
    return;
  };
  window_set_frame(&bar->window, bar_get_frame(bar));
  if (window_apply_frame(&bar->window, false)) {
    window_assign_mouse_tracking_area(&bar->window, bar->window.frame);
    g_bar_manager.bar_needs_update = true;
  }
}

void bar_set_hidden(struct bar* bar, bool hidden) {
  if (bar->hidden == hidden) return;
  bar->hidden = hidden;
  
  if (hidden) window_move(&bar->window, g_nirvana);
  else bar_resize(bar);
}

static void bar_create_window(struct bar* bar) {
  window_init(&bar->window);
  window_create(&bar->window, bar_get_frame(bar));
  window_assign_mouse_tracking_area(&bar->window, bar->window.frame);
  window_set_blur_radius(&bar->window, g_bar_manager.blur_radius);
  if (!g_bar_manager.shadow) window_disable_shadow(&bar->window);

  context_set_font_smoothing(bar->window.context, g_bar_manager.font_smoothing);
}

void bar_change_space(struct bar* bar, uint64_t dsid) {
  if (bar->adid < 1) return;

  for (uint32_t i = 0; i < g_bar_manager.bar_item_count; i++) {
    struct bar_item* bar_item = g_bar_manager.bar_items[i];
    bar_item_change_space(bar_item, dsid, bar->adid);
  }

  window_send_to_space(&bar->window, dsid);
}

struct bar *bar_create(uint32_t did) {
  struct bar *bar = malloc(sizeof(struct bar));
  memset(bar, 0, sizeof(struct bar));
  bar->hidden = false;
  bar->mouse_over = false;
  bar->did = did;
  bar->dsid = display_space_id(did);
  bar->sid = mission_control_index(bar->dsid);
  bar->shown = SLSSpaceGetType(g_connection, bar->dsid) != 4;
  g_bar_manager.bar_needs_update = true;
  bar_create_window(bar);
  return bar;
}

void bar_destroy(struct bar *bar) {
  window_close(&bar->window);
  free(bar);
}


================================================
FILE: src/bar.h
================================================
#pragma once
#include "bar_item.h"
#include "misc/helpers.h"
#include "window.h"

struct bar {
  bool shown;
  bool hidden;
  bool mouse_over;

  uint32_t sid;
  uint32_t dsid;
  uint32_t did;
  uint32_t adid;

  struct window window;
};

struct bar *bar_create(uint32_t did);
void bar_close_window(struct bar* bar);
void bar_destroy(struct bar* bar);
void bar_set_hidden(struct bar* bar, bool hidden);
void bar_calculate_bounds(struct bar* bar);
void bar_resize(struct bar* bar);
void bar_draw(struct bar* bar, bool forced, bool threaded);
void bar_order_item_windows(struct bar* bar);

bool bar_draws_item(struct bar* bar, struct bar_item* bar_item);

void bar_change_space(struct bar* bar, uint64_t dsid);

void context_set_font_smoothing(CGContextRef context, bool smoothing);
void join_render_threads();


================================================
FILE: src/bar_item.c
================================================
#include "bar_item.h"
#include "bar_manager.h"
#include "event.h"
#include "volume.h"
#include "power.h"
#include "media.h"
#include "app_windows.h"

struct bar_item* bar_item_create() {
  struct bar_item* bar_item = malloc(sizeof(struct bar_item));
  memset(bar_item, 0, sizeof(struct bar_item));
  return bar_item;
}

void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item) {
  bar_item->needs_update = true;
  bar_item->lazy = true;
  bar_item->drawing = true;
  bar_item->updates = true;
  bar_item->updates_only_when_shown = false;
  bar_item->selected = false;
  bar_item->ignore_association = false;
  bar_item->overrides_association = false;
  bar_item->counter = 0;
  bar_item->type = BAR_ITEM;
  bar_item->update_frequency = 0;
  bar_item->position = POSITION_LEFT;
  bar_item->align = POSITION_LEFT;
  bar_item->associated_to_active_display = false;
  bar_item->associated_display = 0;
  bar_item->associated_space = 0;
  bar_item->associated_bar = 0;
  bar_item->blur_radius = 0;
  bar_item->event_port = 0;
  bar_item->shadow = false;
  bar_item->scroll_texts = false;
  bar_item->mouse_over = false;

  bar_item->has_const_width = false;
  bar_item->custom_width = 0;

  bar_item->y_offset = 0;
  
  bar_item->has_alias = false;
  bar_item->has_graph = false;

  bar_item->name = NULL;
  bar_item->script = NULL;
  bar_item->click_script = NULL;

  bar_item->group = NULL;
  bar_item->parent = NULL;

  text_init(&bar_item->icon);
  text_init(&bar_item->label);
  background_init(&bar_item->background);
  env_vars_init(&bar_item->signal_args.env_vars);
  popup_init(&bar_item->popup, bar_item);
  graph_init(&bar_item->graph);
  alias_init(&bar_item->alias);
  slider_init(&bar_item->slider);
  
  if (default_item) bar_item_inherit_from_item(bar_item, default_item);
}

void bar_item_append_associated_space(struct bar_item* bar_item, uint32_t bit) {
  if (bar_item->associated_space & bit) return;
  bar_item->associated_space |= bit;
  if (bar_item->type == BAR_COMPONENT_SPACE) {
    bar_item->associated_space = bit;
    char sid_str[32];
    snprintf(sid_str, 32, "%u", get_set_bit_position(bit));
    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("SID"),
                 string_copy(sid_str)            );
  }
}

void bar_item_append_associated_display(struct bar_item* bar_item, uint32_t bit) {
  if (bar_item->associated_display & bit) return;
  bar_item->associated_display |= bit;
  if (bar_item->type == BAR_COMPONENT_SPACE) {
    bar_item->overrides_association = true;
    bar_item->associated_display = bit;
    char did_str[32];
    snprintf(did_str, 32, "%u", get_set_bit_position(bit));
    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("DID"),
                 string_copy(did_str)            );
  }
}

bool bar_item_is_shown(struct bar_item* bar_item) {
  if (bar_item->associated_bar & UINT32_MAX) return true;
  else return false;
}

void bar_item_append_associated_bar(struct bar_item* bar_item, uint32_t adid) {
  bar_item->associated_bar |= (1 << (adid - 1));
}

void bar_item_remove_associated_bar(struct bar_item* bar_item, uint32_t adid) {
  bar_item->associated_bar &= ~(1 << (adid - 1)); 
}

void bar_item_reset_associated_bar(struct bar_item* bar_item) {
  bar_item->associated_bar = 0;
}

bool bar_item_update(struct bar_item* bar_item, char* sender, bool forced, struct env_vars* env_vars) {
  bool is_shown = bar_item_is_shown(bar_item);
  if (is_shown && bar_item->scroll_texts && (bar_item->counter % 15 == 0)) {
    text_animate_scroll(&bar_item->icon);
    text_animate_scroll(&bar_item->label);
    if (bar_item->type == BAR_COMPONENT_SLIDER)
      text_animate_scroll(&bar_item->slider.knob);
  }

  bar_item->counter++;

  if ((!bar_item->updates || (bar_item->update_frequency == 0 && !sender))
      && !forced                                                          ) {
    return false;
  }

  bool scheduled_update_needed = bar_item->update_frequency
                                  <= bar_item->counter;

  bool should_update = bar_item->updates_only_when_shown
                       ? is_shown
                       : true;

  if (((scheduled_update_needed || sender) && should_update) || forced) {
    bar_item->counter = 0;

    if ((bar_item->script && strlen(bar_item->script) > 0)
         || bar_item->event_port                          ) {
      if (!env_vars)
        env_vars = &bar_item->signal_args.env_vars;
      else {
        for (int i = 0; i < bar_item->signal_args.env_vars.count; i++) {
          env_vars_set(env_vars,
                       string_copy(bar_item->signal_args.env_vars.vars[i]->key),
                       string_copy(bar_item->signal_args.env_vars.vars[i]->value));
        }
        env_vars_set(env_vars,
                     string_copy("NAME"),
                     string_copy(bar_item->name));
      }

      if (sender)
        env_vars_set(env_vars, string_copy("SENDER"), string_copy(sender));
      else
        env_vars_set(env_vars,
                     string_copy("SENDER"),
                     string_copy(forced ? "forced" : "routine"));
    }
    // Script Update
    if (bar_item->script && strlen(bar_item->script) > 0) {
      fork_exec(bar_item->script, env_vars);
    }

    // Mach events
    if (bar_item->event_port) {
      uint32_t len = 0;
      char* message = env_vars_copy_serialized_representation(env_vars, &len);

      mach_send_message(bar_item->event_port, message, len, false);
      free(message);
    }
  }

  return false;
}

void bar_item_needs_update(struct bar_item* bar_item) {
  bar_item->needs_update = true;
}

void bar_item_cancel_drag(struct bar_item* bar_item) {
  if (bar_item->has_slider) {
    char perc_str[8];
    snprintf(perc_str, 8, "%d", bar_item->slider.percentage);
    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("PERCENTAGE"),
                 string_copy(perc_str)           );

    slider_cancel_drag(&bar_item->slider);
  }
}

void bar_item_on_drag(struct bar_item* bar_item, CGPoint point) {
  if (bar_item->has_slider) {
    if (slider_handle_drag(&bar_item->slider, point)) {
      bar_item_needs_update(bar_item);
    }
  }
}

void bar_item_on_click(struct bar_item* bar_item, uint32_t type, uint32_t mouse_button_code, uint32_t modifier, CGPoint point) {
  if (!bar_item) return;

  struct env_vars env_vars;
  env_vars_init(&env_vars);
  char info_str[256];
  snprintf(info_str, 256, "{\n"
                         "\t\"button\": \"%s\",\n"
                         "\t\"button_code\": %u,\n"
                         "\t\"modifier\": \"%s\",\n"
                         "\t\"modfier_code\": %u\n"
                         "}\n",
                         get_type_description(type),
                         mouse_button_code,
                         get_modifier_description(modifier),
                         modifier                           );

  env_vars_set(&env_vars, string_copy("INFO"), string_copy(info_str));

  env_vars_set(&env_vars,
               string_copy("BUTTON"),
               string_copy(get_type_description(type)));

  env_vars_set(&env_vars,
               string_copy("MODIFIER"),
               string_copy(get_modifier_description(modifier)));

  if (bar_item->has_slider) {
    if (bar_item->slider.is_dragged
        || CGRectContainsPoint(bar_item->slider.background.bounds, point)) {
      if (slider_handle_drag(&bar_item->slider, point)) {
        bar_item_needs_update(bar_item);
      }

      bar_item_cancel_drag(bar_item);
    } else {
      env_vars_destroy(&env_vars);
      return;
    }
  }

  if (bar_item->click_script && strlen(bar_item->click_script) > 0) {
    for (int i = 0; i < bar_item->signal_args.env_vars.count; i++) {
      env_vars_set(&env_vars,
                   string_copy(bar_item->signal_args.env_vars.vars[i]->key),
                   string_copy(bar_item->signal_args.env_vars.vars[i]->value));
    }

    fork_exec(bar_item->click_script, &env_vars);
  }
  if (bar_item->update_mask & UPDATE_MOUSE_CLICKED)
    bar_item_update(bar_item,
                    COMMAND_SUBSCRIBE_MOUSE_CLICKED,
                    true,
                    &env_vars                       );

  env_vars_destroy(&env_vars);
}

void bar_item_on_scroll(struct bar_item* bar_item, int scroll_delta, uint32_t modifier) {
  if (!bar_item) return;

  struct env_vars env_vars;
  env_vars_init(&env_vars);
  char info_str[256];
  snprintf(info_str, 256, "{\n"
                          "\t\"delta\": %d,\n"
                          "\t\"modifier\": \"%s\",\n"
                          "\t\"modfier_code\": %u\n"
                          "}\n",
                          scroll_delta,
                          get_modifier_description(modifier),
                          modifier                           );

  env_vars_set(&env_vars, string_copy("INFO"), string_copy(info_str));

  char delta_ver_str[32];
  snprintf(delta_ver_str, 32, "%d", scroll_delta);
  env_vars_set(&env_vars,
               string_copy("SCROLL_DELTA"),
               string_copy(delta_ver_str));

  env_vars_set(&env_vars,
               string_copy("MODIFIER"),
               string_copy(get_modifier_description(modifier)));


  if (bar_item->update_mask & UPDATE_MOUSE_SCROLLED)
    bar_item_update(bar_item,
                    COMMAND_SUBSCRIBE_MOUSE_SCROLLED,
                    true,
                    &env_vars                        );


  env_vars_destroy(&env_vars);
}

void bar_item_mouse_entered(struct bar_item* bar_item) {
  if (bar_item->update_mask & UPDATE_MOUSE_ENTERED && !bar_item->mouse_over) {
    bar_item_update(bar_item, COMMAND_SUBSCRIBE_MOUSE_ENTERED, true, NULL);
  }
  bar_item->mouse_over = true;
}

void bar_item_mouse_exited(struct bar_item* bar_item) {
  if (bar_item->update_mask & UPDATE_MOUSE_EXITED) {
    bar_item_update(bar_item, COMMAND_SUBSCRIBE_MOUSE_EXITED, true, NULL); 
  }
  bar_item->mouse_over = false;
}

static bool bar_item_set_drawing(struct bar_item* bar_item, bool state) {
  if (bar_item->drawing == state) return false;
  bar_item->drawing = state;
  return true;
}

static void bar_item_set_script(struct bar_item* bar_item, char* script) {
  if (!script) return;

  if (bar_item->script && strcmp(bar_item->script, script) == 0) {
    free(script);
    return;
  }

  if (script != bar_item->script && bar_item->script)
    free(bar_item->script);

  char* path = resolve_path(script);
  if (path) bar_item->script = path;
}

static void bar_item_set_click_script(struct bar_item* bar_item, char* script) {
  if (!script) return;

  if (bar_item->click_script && strcmp(bar_item->click_script, script) == 0) {
    free(script);
    return;
  }

  if (script != bar_item->click_script && bar_item->click_script)
    free(bar_item->click_script);

  char* path = resolve_path(script);
  if (path) bar_item->click_script = path;
}

static bool bar_item_set_yoffset(struct bar_item* bar_item, int offset) {
  if (bar_item->y_offset == offset) return false;
  bar_item->y_offset = offset;
  return true;
}

static bool bar_item_set_blur_radius(struct bar_item* bar_item, uint32_t radius) {
  if (bar_item->blur_radius == radius) return false;
  bar_item->blur_radius = radius;
  for (int i = 0; i < bar_item->num_windows; i++) {
    if (!bar_item->windows[i]) continue;
    window_set_blur_radius(bar_item->windows[i], radius);
  }
  return true;
}

static bool bar_item_set_width(struct bar_item* bar_item, int width) {
  if (width < 0) {
    bool prev = bar_item->has_const_width;
    bar_item->has_const_width = false;
    return prev != bar_item->has_const_width;
  }
  if (bar_item->custom_width == width && bar_item->has_const_width)
    return false;

  bar_item->custom_width = width;
  bar_item->has_const_width = true;
  return true;
}

static void bar_item_set_event_port(struct bar_item* bar_item, char* bs_name) {
  mach_port_t port = mach_get_bs_port(bs_name);
  bar_item->event_port = port;
}

bool bar_item_set_name(struct bar_item* bar_item, char* name) {
  if (!name) return false;

  if (bar_item->name && strcmp(bar_item->name, name) == 0) {
    free(name);
    return true;
  }

  if (strlen(name) == 0) return false;

  if (name != bar_item->name && bar_item->name) free(bar_item->name);
  bar_item->name = name;
  env_vars_set(&bar_item->signal_args.env_vars,
               string_copy("NAME"),
               string_copy(name)               );
  return true;
}

bool bar_item_set_type(struct bar_item* bar_item, char* type) {
  bool success = true;

  if (string_equals(type, TYPE_SPACE)) {
    bar_item->type = BAR_COMPONENT_SPACE;
  } else if (string_equals(type, TYPE_ALIAS)) {
    bar_item->type = BAR_COMPONENT_ALIAS;
  } else if (string_equals(type, TYPE_GROUP)) {
    bar_item->type = BAR_COMPONENT_GROUP;
  } else if (string_equals(type, TYPE_GRAPH)) {
    bar_item->type = BAR_COMPONENT_GRAPH;
  } else if (string_equals(type, TYPE_SLIDER)) {
    bar_item->type = BAR_COMPONENT_SLIDER;
  } else {
    bar_item->type = BAR_ITEM;
    success = string_equals(type, TYPE_ITEM);
  }

  if (bar_item->type == BAR_COMPONENT_SPACE) {
    if (!bar_item->script) { 
        bar_item_set_script(bar_item,
            string_copy("sketchybar -m --set $NAME icon.highlight=$SELECTED"));
    }

    bar_item->update_mask |= UPDATE_SPACE_CHANGE;
    bar_item->updates = false;
    bar_item->updates_only_when_shown = false;
    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("SELECTED"),
                 string_copy("false")            );

    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("SID"),
                 string_copy("0")                );

    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("DID"),
                 string_copy("0")                );
  }
  else if (bar_item->type == BAR_COMPONENT_ALIAS) {
    bar_item->has_alias = true;
  }
  else if (bar_item->type == BAR_COMPONENT_GRAPH) {
    bar_item->has_graph = true;
  }
  else if (bar_item->type == BAR_COMPONENT_SLIDER) {
    bar_item->has_slider = true;
  }
  else if (bar_item->type == BAR_COMPONENT_GROUP) {
    bar_item->group = group_create();
    group_init(bar_item->group);
    group_add_member(bar_item->group, bar_item);
  }
  return success;
}

bool bar_item_set_position(struct bar_item* bar_item, char* position) {
  if (!position || strlen(position) == 0) return false;

  switch (position[0]) {
    case POSITION_LEFT:
      break;
    case POSITION_CENTER_LEFT:
      break;
    case POSITION_CENTER:
      break;
    case POSITION_CENTER_RIGHT:
      break;
    case POSITION_RIGHT:
      break;
    case POSITION_POPUP:
      break;
    default:
      return false;
  }

  if (bar_item->parent != NULL){
    popup_remove_item(&bar_item->parent->popup,bar_item);
  }

  bar_item->position = position[0];
  if (position[0] != POSITION_POPUP)
    bar_item->align = position[0];
  return true;
}

bool bar_item_set_media_cover(struct bar_item* bar_item, struct image* image) {
  bool linked = (bar_item->background.image.link == image
                 ||bar_item->icon.background.image.link == image
                 ||bar_item->label.background.image.link == image);
  if (linked) bar_item_needs_update(bar_item);
  return linked && bar_item_is_shown(bar_item);
}

static uint32_t bar_item_get_content_length(struct bar_item* bar_item) {
  int length = text_get_length(&bar_item->icon, false)
         + text_get_length(&bar_item->label, false)
         + (bar_item->has_graph  ? graph_get_length(&bar_item->graph) : 0)
         + (bar_item->has_slider ? slider_get_length(&bar_item->slider) : 0)
         + (bar_item->has_alias  ? alias_get_length(&bar_item->alias) : 0);
 
  return max(length, 0);
}

uint32_t bar_item_get_length(struct bar_item* bar_item, bool ignore_override) {
  uint32_t content_length = bar_item_get_content_length(bar_item);
  if (bar_item->background.enabled && bar_item->background.image.enabled) {
    CGSize image_size = image_get_size(&bar_item->background.image);

    if (image_size.width > content_length) content_length = image_size.width;
  }

  if (bar_item->has_const_width && (!ignore_override
                                    || bar_item->custom_width
                                       > content_length      )) {
    return bar_item->custom_width;
  }

  return content_length;
}

uint32_t bar_item_get_height(struct bar_item* bar_item) {
  uint32_t label_height = text_get_height(&bar_item->label);
  uint32_t icon_height = text_get_height(&bar_item->icon);
  uint32_t alias_height = alias_get_height(&bar_item->alias);
  
  uint32_t text_height = max(label_height, icon_height);
  uint32_t item_height = max(text_height, alias_height);

  uint32_t background_height = 0;
  if (bar_item->background.enabled) {
    uint32_t image_height = bar_item->background.image.enabled
                            ? image_get_size(&bar_item->background.image).height
                            : 0;

    background_height = max(image_height,
                            bar_item->background.bounds.size.height);
  }

  return max(item_height, background_height);
}

struct window* bar_item_get_window(struct bar_item* bar_item, uint32_t adid) {
  if (adid < 1 || !bar_item) return NULL;
  if (bar_item->num_windows < adid) {
    bar_item->windows = (struct window**) realloc(bar_item->windows,
                                                  sizeof(struct window*)*adid);
    memset(bar_item->windows + bar_item->num_windows,
           0,
           sizeof(struct window*) * (adid - bar_item->num_windows));

    bar_item->num_windows = adid;
  }

  if (!bar_item->windows[adid - 1]) {
    bar_item->windows[adid - 1] = malloc(sizeof(struct window));
    window_init(bar_item->windows[adid - 1]);
    window_create(bar_item->windows[adid - 1],
                  (CGRect){{g_nirvana.x,g_nirvana.y}, {1, 1}});
    if (!bar_item->shadow) window_disable_shadow(bar_item->windows[adid - 1]);
    window_set_blur_radius(bar_item->windows[adid - 1], bar_item->blur_radius);
    context_set_font_smoothing(bar_item->windows[adid - 1]->context,
                               g_bar_manager.font_smoothing         );
    
    if (bar_item->parent)
      bar_item->parent->popup.needs_ordering = true;
    else
      g_bar_manager.needs_ordering = true;
  }

  return bar_item->windows[adid - 1];
}

void bar_item_remove_window(struct bar_item* bar_item, uint32_t adid) {
  if (bar_item->num_windows >= adid && bar_item->windows[adid - 1]) {
    window_close(bar_item->windows[adid - 1]);
    free(bar_item->windows[adid - 1]);
    bar_item->windows[adid - 1] = NULL;
  }
}

CGPoint bar_item_calculate_shadow_offsets(struct bar_item* bar_item) {
  CGPoint offset;
  offset.x = (int)((bar_item->background.shadow.enabled
                ? max(-bar_item->background.shadow.offset.x, 0)
                : 0)
             + (bar_item->icon.shadow.enabled
                ? max(-bar_item->icon.shadow.offset.x, 0)
                : 0)
             + (bar_item->icon.background.shadow.enabled
                ? max(-bar_item->icon.background.shadow.offset.x, 0)
                : 0)
             + (bar_item->label.background.shadow.enabled
                ? max(-bar_item->label.background.shadow.offset.x, 0)
                : 0)
             + (bar_item->label.shadow.enabled
                ? max(-bar_item->label.shadow.offset.x, 0)
                : 0)
             + (bar_item->background.enabled
                ? max(-bar_item->background.x_offset, 0)
                : 0));

  offset.y = (int)((bar_item->background.shadow.enabled
                 ? max(bar_item->background.shadow.offset.x,0)
                 : 0)
              + (bar_item->icon.shadow.enabled
                 ? max(bar_item->icon.shadow.offset.x, 0)
                 : 0)
              + (bar_item->icon.background.shadow.enabled
                 ? max(bar_item->icon.background.shadow.offset.x, 0)
                 : 0)
              + (bar_item->label.background.shadow.enabled
                 ? max(bar_item->label.background.shadow.offset.x, 0)
                 : 0)
              + (bar_item->label.shadow.enabled
                 ? max(bar_item->label.shadow.offset.x, 0)
                 : 0)
              + (bar_item->background.enabled
                 ? max(bar_item->background.x_offset, 0)
                 : 0));
  return offset;
}

uint32_t bar_item_calculate_bounds(struct bar_item* bar_item, uint32_t bar_height, uint32_t x, uint32_t y) {
  uint32_t content_x = x;
  uint32_t content_y = y;

  uint32_t bar_item_length = bar_item_get_length(bar_item, false);
  uint32_t bar_item_content_length = bar_item_get_content_length(bar_item);
  if (bar_item_length > bar_item_content_length) {
    if (bar_item->align == POSITION_CENTER)
      content_x += (bar_item_length - bar_item_content_length) / 2;
    else if (bar_item->align == POSITION_RIGHT)
      content_x += bar_item_length - bar_item_content_length;
  }

  uint32_t icon_position = content_x;
  uint32_t label_position = icon_position + text_get_length(&bar_item->icon,
                                                            false           );

  uint32_t sandwich_position = label_position;
  if (bar_item->has_graph) {
    label_position += graph_get_length(&bar_item->graph);
  } else if (bar_item->has_alias) {
    label_position += alias_get_length(&bar_item->alias); 
  } else if (bar_item->has_slider) {
    label_position += slider_get_length(&bar_item->slider); 
  }


  text_calculate_bounds(&bar_item->icon,
                        icon_position,
                        content_y + bar_item->y_offset);

  text_calculate_bounds(&bar_item->label,
                        label_position,
                        content_y + bar_item->y_offset);

  if (bar_item->has_alias)
    alias_calculate_bounds(&bar_item->alias,
                           sandwich_position,
                           content_y + bar_item->y_offset);

  if (bar_item->has_slider)
    slider_calculate_bounds(&bar_item->slider,
                            sandwich_position,
                            content_y + bar_item->y_offset);

  if (bar_item->has_graph) {
    uint32_t height = bar_item->background.enabled
                      ? (bar_item->background.bounds.size.height
                         - bar_item->background.border_width - 1)
                      : (bar_height
                         - (g_bar_manager.background.border_width + 1));

    graph_calculate_bounds(&bar_item->graph,
                           sandwich_position,
                           content_y + bar_item->y_offset,
                           height                         );
  }

  if (bar_item->background.enabled) {
    uint32_t height = bar_item->background.overrides_height
                      ? bar_item->background.bounds.size.height
                      : (bar_height
                         - (g_bar_manager.background.border_width + 1));

    background_calculate_bounds(&bar_item->background,
                                x,
                                content_y + bar_item->y_offset,
                                bar_item_length,
                                height                         );
  }

  return bar_item_length;
}

bool bar_item_clip_needs_update_for_bar(struct bar_item* bar_item, struct bar* bar) {
  bool needs_update = false;

  needs_update |= background_clip_needs_update(&bar_item->background, bar)
               || background_clip_needs_update(&bar_item->icon.background, bar)
               || background_clip_needs_update(&bar_item->label.background, bar);

  return needs_update;
}

bool bar_item_clips_bar(struct bar_item* bar_item) {
  return background_clips_bar(&bar_item->background)
         || background_clips_bar(&bar_item->icon.background)
         || background_clips_bar(&bar_item->label.background);
}

void bar_item_clip_bar(struct bar_item* bar_item, int offset, struct bar* bar) {
  background_clip_bar(&bar_item->background, offset, bar);
  background_clip_bar(&bar_item->icon.background, offset, bar);
  background_clip_bar(&bar_item->label.background, offset, bar);
}

void* draw_item_proc(void* context) {
  struct { struct window* window; struct bar_item bar_item; }* info = context;
  CGContextClearRect(info->window->context, info->window->frame);
  bar_item_draw(&info->bar_item, info->window->context);
  CGContextFlush(info->window->context);
  window_flush(info->window);
  free(context);
  return NULL;
}

void bar_item_draw(struct bar_item* bar_item, CGContextRef context) {
  background_draw(&bar_item->background, context);
  if (bar_item->type == BAR_COMPONENT_GROUP) return;

  text_draw(&bar_item->icon, context);
  text_draw(&bar_item->label, context);

  if (bar_item->has_alias) alias_draw(&bar_item->alias, context);
  if (bar_item->has_graph) graph_draw(&bar_item->graph, context);
  if (bar_item->has_slider) slider_draw(&bar_item->slider, context);
}

void bar_item_change_space(struct bar_item* bar_item, uint64_t dsid, uint32_t adid) {
  if (bar_item->num_windows >= adid && bar_item->windows[adid - 1]) {
    window_send_to_space(bar_item->windows[adid - 1], dsid);
  }
  popup_change_space(&bar_item->popup, dsid, adid);
}

static void bar_item_clear_pointers(struct bar_item* bar_item) {
  bar_item->name = NULL;
  bar_item->script = NULL;
  bar_item->click_script = NULL;
  bar_item->group = NULL;
  bar_item->signal_args.env_vars.vars = NULL;
  bar_item->signal_args.env_vars.count = 0;
  bar_item->windows = NULL;
  bar_item->num_windows = 0;
  text_clear_pointers(&bar_item->icon);
  text_clear_pointers(&bar_item->label);
  background_clear_pointers(&bar_item->background);
  slider_clear_pointers(&bar_item->slider);
  popup_clear_pointers(&bar_item->popup);
  bar_item->popup.host = bar_item;
}

void bar_item_inherit_from_item(struct bar_item* bar_item, struct bar_item* ancestor) {
  text_destroy(&bar_item->icon);
  text_destroy(&bar_item->label);
  text_destroy(&bar_item->slider.knob);
  
  char* name = bar_item->name;
  char* script = bar_item->script;
  char* click_script = bar_item->click_script;

  memcpy(bar_item, ancestor, sizeof(struct bar_item));
  bar_item_clear_pointers(bar_item);

  bar_item->name = name;
  bar_item->script = script;
  bar_item->click_script = click_script;

  text_copy(&bar_item->icon, &ancestor->icon);
  text_copy(&bar_item->label, &ancestor->label);
  text_copy(&bar_item->slider.knob, &ancestor->slider.knob);

  if (ancestor->script)
    bar_item_set_script(bar_item, string_copy(ancestor->script));
  if (ancestor->click_script)
    bar_item_set_click_script(bar_item, string_copy(ancestor->click_script));

  image_copy(&bar_item->background.image,
             ancestor->background.image.image_ref);

  image_copy(&bar_item->icon.background.image,
             ancestor->icon.background.image.image_ref);

  image_copy(&bar_item->label.background.image,
             ancestor->label.background.image.image_ref);

  if (bar_item->type == BAR_COMPONENT_SPACE) {
    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("SELECTED"),
                 string_copy("false")            );

    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("SID"),
                 string_copy(env_vars_get_value_for_key(&ancestor->signal_args.env_vars,
                                                        "DID")                          ));
    env_vars_set(&bar_item->signal_args.env_vars,
                 string_copy("DID"),
                 string_copy(env_vars_get_value_for_key(&ancestor->signal_args.env_vars,
                                                        "DID")                          ));
  }
}

void bar_item_destroy(struct bar_item* bar_item, bool free_memory) {
  if (bar_item->name) free(bar_item->name);
  if (bar_item->script) free(bar_item->script);
  if (bar_item->click_script) free(bar_item->click_script);

  text_destroy(&bar_item->icon);
  text_destroy(&bar_item->label);

  graph_destroy(&bar_item->graph);
  alias_destroy(&bar_item->alias);
  slider_destroy(&bar_item->slider);

  if (bar_item->group && bar_item->type == BAR_COMPONENT_GROUP)
    group_destroy(bar_item->group);
  else if (bar_item->group)
    group_remove_member(bar_item->group, bar_item);

  env_vars_destroy(&bar_item->signal_args.env_vars);
  popup_destroy(&bar_item->popup);
  background_destroy(&bar_item->background);

  for (int j = 1; j <= bar_item->num_windows; j++) {
    bar_item_remove_window(bar_item, j);
  }
  if (bar_item->windows) free(bar_item->windows);

  if (free_memory) free(bar_item);
}

void bar_item_serialize(struct bar_item* bar_item, FILE* rsp) {
  char type[32] = { 0 };
  switch (bar_item->type) {
    case BAR_ITEM:
      snprintf(type, 32, "item");
      break;
    case BAR_COMPONENT_ALIAS:
      snprintf(type, 32, "alias");
      break;
    case BAR_COMPONENT_GROUP:
      snprintf(type, 32, "bracket");
      break;
    case BAR_COMPONENT_SLIDER:
      snprintf(type, 32, "slider");
      break;
    case BAR_COMPONENT_GRAPH:
      snprintf(type, 32, "graph");
      break;
    case BAR_COMPONENT_SPACE:
      snprintf(type, 32, "space");
      break;
    default:
      snprintf(type, 32, "invalid");
      break;
  }

  char position[32] = { 0 };
  switch (bar_item->position) {
    case POSITION_LEFT:
      snprintf(position, 32, "left");
      break;
    case POSITION_RIGHT:
      snprintf(position, 32, "right");
      break;
    case POSITION_CENTER:
      snprintf(position, 32, "center");
      break;
    case POSITION_CENTER_LEFT:
      snprintf(position, 32, "q");
      break;
    case POSITION_CENTER_RIGHT:
      snprintf(position, 32, "e");
      break;
    case POSITION_POPUP:
      snprintf(position, 32, "popup");
      break;
    default:
      snprintf(position, 32, "invalid");
      break;
  }

  fprintf(rsp, "{\n"
               "\t\"name\": \"%s\",\n"
               "\t\"type\": \"%s\",\n"
               "\t\"geometry\": {\n"
               "\t\t\"drawing\": \"%s\",\n"
               "\t\t\"position\": \"%s\",\n"
               "\t\t\"associated_space_mask\": %u,\n"
               "\t\t\"associated_display_mask\": %u,\n"
               "\t\t\"ignore_association\": \"%s\",\n"
               "\t\t\"y_offset\": %d,\n"
               "\t\t\"padding_left\": %d,\n"
               "\t\t\"padding_right\": %d,\n"
               "\t\t\"scroll_texts\": \"%s\",\n"
               "\t\t\"width\": %d,\n"
               "\t\t\"background\": {\n",
               bar_item->name,
               type,
               format_bool(bar_item->drawing),
               position,
               bar_item->associated_space,
               bar_item->associated_display,
               format_bool(bar_item->ignore_association),
               bar_item->y_offset,
               bar_item->background.padding_left,
               bar_item->background.padding_right,
               format_bool(bar_item->scroll_texts),
               bar_item->has_const_width ? bar_item->custom_width : -1);

  background_serialize(&bar_item->background, "\t\t\t", rsp, true);
  fprintf(rsp, "\n\t\t}\n\t},\n");

  fprintf(rsp, "\t\"icon\": {\n");
  text_serialize(&bar_item->icon, "\t\t", rsp);
  fprintf(rsp, "\n\t},\n");

  fprintf(rsp, "\t\"label\": {\n");
  text_serialize(&bar_item->label, "\t\t", rsp);
  fprintf(rsp, "\n\t},\n");


  char* escaped_script = escape_string(bar_item->script);
  char* escaped_click_script = escape_string(bar_item->click_script);
  fprintf(rsp, "\t\"scripting\": {\n"
               "\t\t\"script\": \"%s\",\n"
               "\t\t\"click_script\": \"%s\",\n"
               "\t\t\"update_freq\": %u,\n"
               "\t\t\"update_mask\": %llu,\n"
               "\t\t\"updates\": \"%s\"\n\t},\n",
               escaped_script,
               escaped_click_script,
               bar_item->update_frequency,
               bar_item->update_mask,
               bar_item->updates_only_when_shown
                ? "when_shown"
                : format_bool(bar_item->updates) );

  if (escaped_script) free(escaped_script);
  if (escaped_click_script) free(escaped_click_script);

  fprintf(rsp, "\t\"bounding_rects\": {\n");
  int counter = 0;
  for (int i = 0; i < bar_item->num_windows; i++) {
    if (!bar_item->windows[i]) continue;
    if (counter++ > 0) fprintf(rsp, ",\n");
    fprintf(rsp, "\t\t\"display-%d\": {\n"
            "\t\t\t\"origin\": [ %f, %f ],\n"
            "\t\t\t\"size\": [ %f, %f ]\n\t\t}",
            i + 1,
            bar_item->windows[i]->origin.x,
            bar_item->windows[i]->origin.y,
            bar_item->windows[i]->frame.size.width,
            bar_item->windows[i]->frame.size.height);
  } 
  fprintf(rsp, "\n\t}");

  if (bar_item->popup.num_items > 0) {
    fprintf(rsp, ",\n\t\"popup\": {\n");
    popup_serialize(&bar_item->popup, "\t\t", rsp);
    fprintf(rsp, "\n\t}");
  }

  if (bar_item->type == BAR_COMPONENT_GROUP && bar_item->group) {
    fprintf(rsp, ",\n\t\"bracket\": [\n");
    group_serialize(bar_item->group, "\t\t", rsp);
    fprintf(rsp, "\n\t]");
  } else if (bar_item->type == BAR_COMPONENT_GRAPH) {
    fprintf(rsp, ",\n\t\"graph\": {\n");
    graph_serialize(&bar_item->graph, "\t\t", rsp);
    fprintf(rsp, "\n\t}");
  } else if (bar_item->type == BAR_COMPONENT_SLIDER) {
    fprintf(rsp, ",\n\t\"slider\": {\n");
    slider_serialize(&bar_item->slider, "\t\t", rsp);
    fprintf(rsp, "\n\t}");
  }

  fprintf(rsp, "\n}\n");
}

void bar_item_parse_set_message(struct bar_item* bar_item, char* message, FILE* rsp) {
  bool needs_refresh = false;
  struct token property = get_token(&message);

  struct key_value_pair key_value_pair = get_key_value_pair(property.text,'.');
  if (key_value_pair.key && key_value_pair.value) {
    struct token subdom = { key_value_pair.key, strlen(key_value_pair.key) };
    struct token entry = { key_value_pair.value, strlen(key_value_pair.value)};
    if (token_equals(subdom, SUB_DOMAIN_ICON)) {
      needs_refresh = text_parse_sub_domain(&bar_item->icon,
                                            rsp,
                                            entry,
                                            message         );
    }
    else if (token_equals(subdom, SUB_DOMAIN_LABEL)) {
      needs_refresh = text_parse_sub_domain(&bar_item->label,
                                            rsp,
                                            entry,
                                            message          );
    }
    else if (token_equals(subdom, SUB_DOMAIN_BACKGROUND)) {
      needs_refresh = background_parse_sub_domain(&bar_item->background,
                                                  rsp,
                                                  entry,
                                                  message               );
    }
    else if (token_equals(subdom, SUB_DOMAIN_POPUP)) {
      needs_refresh = popup_parse_sub_domain(&bar_item->popup,
                                             rsp,
                                             entry,
                                             message          );
    }
    else if (token_equals(subdom, SUB_DOMAIN_GRAPH)) {
      if (bar_item->has_graph || bar_item == &g_bar_manager.default_item) {
        needs_refresh = graph_parse_sub_domain(&bar_item->graph,
                                               rsp,
                                               entry,
                                               message          );
      } else {
        respond(rsp, "[!] Item (%s): Trying to set a graph property on a non-graph item\n", bar_item->name);
      }
    }
    else if (token_equals(subdom, SUB_DOMAIN_ALIAS)) {
      if (bar_item->has_alias || bar_item == &g_bar_manager.default_item) {
        needs_refresh = alias_parse_sub_domain(&bar_item->alias,
                                               rsp,
                                               entry,
                                               message          );
      } else {
        respond(rsp, "[!] Item (%s): Trying to set an alias property on a non-alias item\n", bar_item->name);
      }
    }
    else if (token_equals(subdom, SUB_DOMAIN_SLIDER)) {
      if (bar_item->has_slider || bar_item == &g_bar_manager.default_item) {
        needs_refresh = slider_parse_sub_domain(&bar_item->slider,
                                                rsp,
                                                entry,
                                                message           );
      } else {
        respond(rsp, "[!] Item (%s): Trying to set a slider property on a non-slider item\n", bar_item->name);
      }
    }
    else {
      respond(rsp, "[!] Item (%s): Invalid subdomain '%s'\n", bar_item->name, subdom.text);
    }
  }
  else if (token_equals(property, PROPERTY_ICON)) {
    struct token dummy = { PROPERTY_STRING, strlen(PROPERTY_STRING)};
    needs_refresh = text_parse_sub_domain(&bar_item->icon,
                                          rsp,
                                          dummy,
                                          message         );

  } else if (token_equals(property, PROPERTY_LABEL)) {
    struct token dummy = { PROPERTY_STRING, strlen(PROPERTY_STRING)};
    needs_refresh = text_parse_sub_domain(&bar_item->label,
                                          rsp,
                                          dummy,
                                          message          );

  } else if (token_equals(property, PROPERTY_UPDATES)) {
    struct token token = get_token(&message);
    if (token_equals(token, ARGUMENT_UPDATES_WHEN_SHOWN)) {
      bar_item->updates = true;
      bar_item->updates_only_when_shown = true;
    }
    else {
      bar_item->updates = evaluate_boolean_state(token, bar_item->updates);
      bar_item->updates_only_when_shown = false;
    }
  } else if (token_equals(property, PROPERTY_DRAWING)) {
    needs_refresh = bar_item_set_drawing(bar_item,
                                         evaluate_boolean_state(get_token(&message),
                                                                bar_item->drawing   ));
  } else if (token_equals(property, PROPERTY_SCROLL_TEXTS)) {
    bar_item->scroll_texts = evaluate_boolean_state(get_token(&message),
                                                    bar_item->scroll_texts);
  } else if (token_equals(property, PROPERTY_WIDTH)) {
    struct token token = get_token(&message);
    if (token_equals(token, ARGUMENT_DYNAMIC)) {
      ANIMATE(bar_item_set_width,
              bar_item,
              bar_item->custom_width,
              bar_item_get_length(bar_item, true)
              + bar_item->background.padding_left
              + bar_item->background.padding_right);

      struct animation* animation = animation_create();
      animation_setup(animation,
                      bar_item,
                      (bool (*)(void*, int))&bar_item_set_width,
                      bar_item->custom_width,
                      -1,
                      0,
                      INTERP_FUNCTION_LINEAR               );
      animator_add(&g_bar_manager.animator, animation);
    }
    else {
      ANIMATE(bar_item_set_width,
              bar_item,
              bar_item_get_length(bar_item, false)
              + (bar_item->has_const_width
              ? 0
              : (bar_item->background.padding_left
                 + bar_item->background.padding_right)),
              token_to_int(token)                       );
    }
  } else if (token_equals(property, PROPERTY_SCRIPT)) {
    bar_item_set_script(bar_item, token_to_string(get_token(&message)));
  } else if (token_equals(property, PROPERTY_CLICK_SCRIPT)) {
    bar_item_set_click_script(bar_item, token_to_string(get_token(&message)));
  } else if (token_equals(property, PROPERTY_UPDATE_FREQ)) {
    bar_item->update_frequency = token_to_uint32t(get_token(&message));
  } else if (token_equals(property, PROPERTY_POSITION)) {
    struct token position = get_token(&message);
    bar_item_set_position(bar_item, position.text);
    struct key_value_pair key_value_pair = get_key_value_pair(position.text,
                                                              '.'           );

    if (key_value_pair.key && key_value_pair.value) {
      if (key_value_pair.key[0] == POSITION_POPUP) {
        int item_index_for_name = bar_manager_get_item_index_for_name(&g_bar_manager,
                                                                      key_value_pair.value);
        if (item_index_for_name < 0) {
          respond(rsp, "[!] Item Position (%s): Item '%s' is not a valid popup host\n", bar_item->name, key_value_pair.value);
          return;
        }
        struct bar_item* target_item = g_bar_manager.bar_items[item_index_for_name];
        popup_add_item(&target_item->popup, bar_item);
      } else {
        bar_item->parent = NULL;
      }
    }
    needs_refresh = true;
  } else if (token_equals(property, PROPERTY_ALIGN)) {
    struct token position = get_token(&message);
    if (bar_item->align != position.text[0]) {
      bar_item->align = position.text[0];
      needs_refresh = true;
    }
  } else if (token_equals(property, PROPERTY_ASSOCIATED_SPACE)
             || token_equals(property, PROPERTY_SPACE)        ) {
    struct token token = get_token(&message);
    uint32_t prev = bar_item->associated_space;
    bar_item->associated_space = 0;
    uint32_t count;
    char** list = token_split(token, ',', &count);
    if (list && count > 0) {
      for (int i = 0; i < count; i++) {
        bar_item_append_associated_space(bar_item,
                                         1 << strtoul(list[i],
                                                      NULL,
                                                      0       ));
      }
      free(list);
    }
    needs_refresh = (prev != bar_item->associated_space);
  } else if (token_equals(property, PROPERTY_ASSOCIATED_DISPLAY)
             || token_equals(property, PROPERTY_DISPLAY)        ) {
    struct token token = get_token(&message);
    uint32_t prev = bar_item->associated_display;
    bar_item->associated_display = 0;
    bar_item->associated_to_active_display = false;
    uint32_t count;
    char** list = token_split(token, ',', &count);
    if (list && count > 0) {
      for (int i = 0; i < count; i++) {
        if (strcmp(list[i], "active") == 0) {
          bar_item->associated_to_active_display = true;
        }
        else {
          bar_item_append_associated_display(bar_item,
                                             1 << strtoul(list[i],
                                                          NULL,
                                                          0       ));
        }
      }
      free(list);
    }
    needs_refresh = (prev != bar_item->associated_display);
  } else if (token_equals(property, PROPERTY_YOFFSET)) {
    struct token token = get_token(&message);
    ANIMATE(bar_item_set_yoffset,
            bar_item,
            bar_item->y_offset,
            token_to_int(token)  );

  } else if (token_equals(property, PROPERTY_PADDING_LEFT)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_padding_left,
            &bar_item->background,
            bar_item->background.padding_left,
            token_to_int(token)               );

  } else if (token_equals(property, PROPERTY_PADDING_RIGHT)) {
    struct token token = get_token(&message);
    ANIMATE(background_set_padding_right,
            &bar_item->background,
            bar_item->background.padding_right,
            token_to_int(token)                );

  } else if (token_equals(property, PROPERTY_BLUR_RADIUS)) {
    struct token token = get_token(&message);
    ANIMATE(bar_item_set_blur_radius,
            bar_item,
            bar_item->blur_radius,
            token_to_int(token)      );

  } else if (token_equals(property, PROPERTY_SHADOW)) {
    bool prev = bar_item->shadow;
    bar_item->shadow = evaluate_boolean_state(get_token(&message),
                                              bar_item->shadow    );
    if (prev != bar_item->shadow) {
      for (int i = 1; i <= bar_item->num_windows; i++) {
        bar_item_remove_window(bar_item, i);
      }
      needs_refresh = true;
    }
  } else if (token_equals(property, PROPERTY_IGNORE_ASSOCIATION)) {
    bar_item->ignore_association = evaluate_boolean_state(get_token(&message),
                                                          bar_item->ignore_association);
    needs_refresh = true;
  } else if (token_equals(property, COMMAND_DEFAULT_RESET)) {
    bar_item_init(&g_bar_manager.default_item, NULL);
  } else if (token_equals(property, PROPERTY_EVENT_PORT)) {
    struct token token = get_token(&message);
    if (token.text && token.length > 0)
      bar_item_set_event_port(bar_item, token.text);
  } else {
    respond(rsp, "[!] Item (%s): Invalid property '%s' \n", bar_item->name, property.text);
  }

  if (needs_refresh) bar_item_needs_update(bar_item);
}

void bar_item_parse_subscribe_message(struct bar_item* bar_item, char* message, FILE* rsp) {
  struct token event = get_token(&message);

  while (event.text && event.length > 0) {
    uint64_t event_flag = custom_events_get_flag_for_name(&g_bar_manager.custom_events,
                                                          event.text                   );

    if (event_flag & UPDATE_VOLUME_CHANGE) {
      begin_receiving_volume_events();
    }

    if (event_flag & UPDATE_BRIGHTNESS_CHANGE) {
      begin_receiving_brightness_events();
    }

    if (event_flag & UPDATE_MEDIA_CHANGE) {
      begin_receiving_media_events();
    }

    if (event_flag & UPDATE_SPACE_WINDOWS_CHANGE) {
      begin_receiving_space_window_events();
    }

    bar_item->update_mask |= event_flag;

    if (!event_flag) {
      respond(rsp, "[?] Event: '%s' not found\n", event.text);
    }

    event = get_token(&message);
  }
}


================================================
FILE: src/bar_item.h
================================================
#pragma once

#include "alias.h"
#include "custom_events.h"
#include "graph.h"
#include "group.h"
#include "misc/env_vars.h"
#include "misc/helpers.h"
#include "popup.h"
#include "text.h"
#include "slider.h"

#define BAR_ITEM             'i'
#define BAR_COMPONENT_GRAPH  'g'
#define BAR_COMPONENT_SPACE  's'
#define BAR_COMPONENT_ALIAS  'a'
#define BAR_COMPONENT_GROUP  'b'
#define BAR_COMPONENT_SLIDER 't'
#define BAR_PLUGIN           'p'

struct bar_item {
  char type;
  char* name;

  // Update Modifiers
  uint32_t counter;
  bool needs_update;
  bool updates;
  bool updates_only_when_shown;
  bool lazy;
  bool selected;
  bool mouse_over;
  bool ignore_association;
  bool overrides_association;

  // Drawing Modifiers
  bool drawing;
  bool shadow;
  bool has_const_width;
  bool scroll_texts;
  char align;
  uint32_t custom_width;
  uint32_t blur_radius;

  // These are 32bit masks where the ith bit represents the ith screen/display/bar association
  bool associated_to_active_display;
  uint32_t associated_bar;
  uint32_t associated_display;
  uint32_t associated_space;
  uint32_t update_frequency;

  char* script;
  char* click_script;
  struct signal_args signal_args;
  
  // The position in the bar: l,r,c
  char position;
  int y_offset;

  // Background
  struct background background;

  // Icon properties
  struct text icon;

  // Label properties
  struct text label;

  // Graph Data
  bool has_graph;
  struct graph graph;

  // Alias Data
  bool has_alias;
  struct alias alias;

  // Slider Properties
  bool has_slider;
  struct slider slider;

  // Group Properties
  struct group* group;

  // Update Events
  uint64_t update_mask;

  // Windows
  uint32_t num_windows;
  struct window** windows;

  // Popup
  struct popup popup;
  struct bar_item* parent;

  // Mach
  mach_port_t event_port;
};

struct bar_item* bar_item_create();
void bar_item_inherit_from_item(struct bar_item* bar_item, struct bar_item* ancestor);
void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item);
void bar_item_serialize(struct bar_item* bar_item, FILE* rsp);
void bar_item_destroy(struct bar_item* bar_item, bool free_memory);

bool bar_item_is_shown(struct bar_item* bar_item);
void bar_item_needs_update(struct bar_item* bar_item);
bool bar_item_update(struct bar_item* bar_item, char* sender, bool forced, struct env_vars* env_vars);

void bar_item_on_click(struct bar_item* bar_item, uint32_t type, uint32_t mouse_button_code, uint32_t modifier, CGPoint point);
void bar_item_on_scroll(struct bar_item* bar_item, int scroll_delta, uint32_t modifier);
void bar_item_on_drag(struct bar_item* bar_item, CGPoint point);
void bar_item_mouse_entered(struct bar_item* bar_item);
void bar_item_mouse_exited(struct bar_item* bar_item);
void bar_item_cancel_drag(struct bar_item* bar_item);

void bar_item_append_associated_space(struct bar_item* bar_item, uint32_t bit);
void bar_item_append_associated_display(struct bar_item* bar_item, uint32_t bit);
void bar_item_append_associated_bar(struct bar_item* bar_item, uint32_t adid);
void bar_item_remove_associated_bar(struct bar_item* bar_item, uint32_t adid);
void bar_item_reset_associated_bar(struct bar_item* bar_item);

bool bar_item_set_name(struct bar_item* bar_item, char* name);
bool bar_item_set_type(struct bar_item* bar_item, char* type);
bool bar_item_set_position(struct bar_item* bar_item, char* position);
bool bar_item_set_media_cover(struct bar_item* bar_item, struct image* image);

uint32_t bar_item_get_length(struct bar_item* bar_item, bool ignore_override);
uint32_t bar_item_get_height(struct bar_item* bar_item);

struct window* bar_item_get_window(struct bar_item* bar_item, uint32_t adid);
void bar_item_remove_window(struct bar_item* bar_item, uint32_t adid);

CGPoint bar_item_calculate_shadow_offsets(struct bar_item* bar_item);
uint32_t bar_item_calculate_bounds(struct bar_item* bar_item, uint32_t bar_height, uint32_t x, uint32_t y);
void* draw_item_proc(void* context);
void bar_item_draw(struct bar_item* bar_item, CGContextRef context);
bool bar_item_clip_needs_update_for_bar(struct bar_item* bar_item, struct bar* bar);
void bar_item_clip_bar(struct bar_item* bar_item, int offset, struct bar* bar);
bool bar_item_clips_bar(struct bar_item* bar_item);

void bar_item_change_space(struct bar_item* bar_item, uint64_t dsid, uint32_t adid);

void bar_item_parse_set_message(struct bar_item* bar_item, char* message, FILE* rsp);
void bar_item_parse_subscribe_message(struct bar_item* bar_item, char* message, FILE* rsp);


================================================
FILE: src/bar_manager.c
================================================
#include "bar_manager.h"
#include "bar.h"
#include "bar_item.h"
#include "event.h"
#include "misc/env_vars.h"
#include "misc/helpers.h"
#include "wifi.h"
#include "volume.h"
#include "power.h"
#include "mouse.h"
#include "media.h"
#include "app_windows.h"

extern void forced_front_app_event();

static CLOCK_CALLBACK(clock_handler) {
  struct event event = { NULL, SHELL_REFRESH };
  event_post(&event);
}

void bar_manager_init(struct bar_manager* bar_manager) {
  bar_manager->font_smoothing = false;
  bar_manager->any_bar_hidden = false;
  bar_manager->needs_ordering = false;
  bar_manager->bar_needs_update = false;
  bar_manager->bars = NULL;
  bar_manager->bar_count = 0;
  bar_manager->bar_items = NULL;
  bar_manager->bar_item_count = 0;
  bar_manager->displays = DISPLAY_ALL_PATTERN;
  bar_manager->position = POSITION_TOP;
  bar_manager->shadow = false;
  bar_manager->blur_radius = 0;
  bar_manager->margin = 0;
  bar_manager->frozen = false;
  bar_manager->sleeps = false;
  bar_manager->window_level = kCGBackstopMenuLevel;
  bar_manager->topmost = false;
  bar_manager->notch_width = 200;
  bar_manager->notch_offset = 0;
  bar_manager->notch_display_height = 0;
  bar_manager->active_adid = display_active_display_adid();
  bar_manager->might_need_clipping = false;

  bar_manager->sticky = true;

  bar_manager->show_in_fullscreen = false;

  image_init(&bar_manager->current_artwork);
  background_init(&bar_manager->background);
  bar_manager->background.bounds.size.height = 25;
  bar_manager->background.overrides_height = true;
  bar_manager->background.padding_left = 20;
  bar_manager->background.padding_right = 20;

  color_set_hex(&bar_manager->background.border_color, 0xffff0000);
  color_set_hex(&bar_manager->background.color, 0x44000000);

  bar_item_init(&bar_manager->default_item, NULL);
  bar_item_set_name(&bar_manager->default_item, string_copy("defaults"));
  custom_events_init(&bar_manager->custom_events);

  animator_init(&bar_manager->animator);

  int shell_refresh_frequency = 1;

  bar_manager->clock = CFRunLoopTimerCreate(NULL,
                                            CFAbsoluteTimeGetCurrent()
                                            + shell_refresh_frequency,
                                            shell_refresh_frequency,
                                            0,
                                            0,
                                            clock_handler,
                                            NULL                      );

  CFRunLoopAddTimer(CFRunLoopGetMain(),
                    bar_manager->clock,
                    kCFRunLoopCommonModes);
}

void bar_manager_sort(struct bar_manager* bar_manager, struct bar_item** ordering, uint32_t count) {
  int index = 0;
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    for (int j = 0; j < count; j++) {
      if (bar_manager->bar_items[i] == ordering[j]
          && bar_manager->bar_items[i] != ordering[index]) {
        bar_manager->bar_items[i] = ordering[index];
        index++;
        bar_item_needs_update(bar_manager->bar_items[i]);
        break;
      }
      else if (bar_manager->bar_items[i] == ordering[j]
               && bar_manager->bar_items[i] == ordering[index]) {
        index++;
        break;
      }
    }
  }
  bar_manager->needs_ordering = true;
}

int bar_manager_get_item_index_for_name(struct bar_manager* bar_manager, char* name) {
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    if (strcmp(bar_manager->bar_items[i]->name, name) == 0) {
      return i;
    }
  }
  return -1;
}

int bar_manager_get_item_index_by_address(struct bar_manager* bar_manager, struct bar_item* bar_item) {
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    if (bar_manager->bar_items[i] == bar_item) {
      return i;
    }
  }
  return -1;
}

void bar_manager_move_item(struct bar_manager* bar_manager, struct bar_item* item, struct bar_item* reference, bool before) {
  if (bar_manager->bar_item_count <= 0) return;
  struct bar_item* tmp[bar_manager->bar_item_count];
  int count = 0;
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    if (bar_manager->bar_items[i] == item) continue;
    if (bar_manager->bar_items[i] == reference && before) {
      tmp[count++] = item;
      tmp[count++] = bar_manager->bar_items[i];
      continue;
    } else if (bar_manager->bar_items[i] == reference && !before) {
      tmp[count++] = bar_manager->bar_items[i];
      tmp[count++] = item;
      continue;
    }
    tmp[count++] = bar_manager->bar_items[i];
  }
  bar_manager->bar_items = realloc(
                        bar_manager->bar_items,
                        sizeof(struct bar_item*)*bar_manager->bar_item_count);

  memcpy(bar_manager->bar_items,
         tmp,
         sizeof(struct bar_item*)*bar_manager->bar_item_count);

  bar_manager->needs_ordering = true;
}

void bar_manager_remove_item(struct bar_manager* bar_manager, struct bar_item* bar_item) {
  if (bar_manager->bar_item_count <= 0 || !bar_item
      || bar_manager_get_item_index_by_address(bar_manager, bar_item) < 0) {
    return;
  }

  if (bar_item->position == POSITION_POPUP) {
    for (int i = 0; i < bar_manager->bar_item_count; i++) {
      popup_remove_item(&bar_manager->bar_items[i]->popup, bar_item);
    }
  }
  if (bar_manager->bar_item_count == 1) {
    free(bar_manager->bar_items);
    bar_manager->bar_items = NULL;
    bar_manager->bar_item_count = 0;
  } else {
    struct bar_item* tmp[bar_manager->bar_item_count - 1];
    int count = 0;
    for (int i = 0; i < bar_manager->bar_item_count; i++) {
      if (bar_manager->bar_items[i] == bar_item) continue;
      tmp[count++] = bar_manager->bar_items[i];
    }
    bar_manager->bar_item_count--;
    bar_manager->bar_items = realloc(
                         bar_manager->bar_items,
                         sizeof(struct bar_item*)*bar_manager->bar_item_count);

    memcpy(bar_manager->bar_items,
           tmp,
           sizeof(struct bar_item*)*bar_manager->bar_item_count);
  }

  bar_item_destroy(bar_item, true);
}

bool bar_manager_set_margin(struct bar_manager* bar_manager, int margin) {
  if (bar_manager->margin == margin) return false;
  bar_manager->margin = margin;
  bar_manager->bar_needs_resize = true;
  return true;
}

bool bar_manager_set_y_offset(struct bar_manager* bar_manager, int y_offset) {
  if (bar_manager->background.y_offset == y_offset) return false;
  bar_manager->background.y_offset = y_offset;
  bar_manager->bar_needs_resize = true;
  return true;
}

bool bar_manager_set_bar_height(struct bar_manager* bar_manager, int height) {
  bar_manager->bar_needs_resize |= background_set_height(&bar_manager->background, height);
  return bar_manager->bar_needs_resize;
}

bool bar_manager_set_background_blur(struct bar_manager* bar_manager, uint32_t radius) {
  if (bar_manager->blur_radius == radius) return false;
  bar_manager->blur_radius = radius;
  for (int i = 0; i < bar_manager->bar_count; i++) {
    window_set_blur_radius(&bar_manager->bars[i]->window, radius);
  }
  return false;
}

bool bar_manager_set_position(struct bar_manager* bar_manager, char pos) {
  if (bar_manager->position == pos) return false;
  bar_manager->position = pos;
  bar_manager->bar_needs_resize = true;
  return true;
}

bool bar_manager_set_displays(struct bar_manager* bar_manager, uint32_t displays) {
  if (bar_manager->displays == displays) return false;
  bar_manager->displays = displays;

  bar_manager_reset(bar_manager);
  return true;
}

bool bar_manager_set_shadow(struct bar_manager* bar_manager, bool shadow) {
  if (bar_manager->shadow == shadow) return false;
  bar_manager->shadow = shadow;
  bar_manager_reset(bar_manager);
  return true;
}

bool bar_manager_set_notch_width(struct bar_manager* bar_manager, uint32_t width) {
  if (bar_manager->notch_width == width) return false;

  bar_manager->notch_width = width;
  return true;
}

bool bar_manager_set_notch_offset(struct bar_manager* bar_manager, uint32_t offset) {
  if (bar_manager->notch_offset == offset) return false;

  bar_manager->notch_offset = offset;
  bar_manager->bar_needs_resize = true;
  return true;
}

bool bar_manager_set_notch_display_height(struct bar_manager* bar_manager, uint32_t offset) {
  if (bar_manager->notch_display_height == offset) return false;

  bar_manager->notch_display_height = offset;
  bar_manager->bar_needs_resize = true;
  return true;
}

bool bar_manager_set_font_smoothing(struct bar_manager* bar_manager, bool smoothing) {
  if (bar_manager->font_smoothing == smoothing) return false;
  bar_manager->font_smoothing = smoothing;
  for (int i = 0; i < bar_manager->bar_count; i++)
    context_set_font_smoothing(bar_manager->bars[i]->window.context, smoothing);
  return true;
}

bool bar_manager_set_show_in_fullscreen(struct bar_manager* bar_manager, bool show_in_fullscreen) {
    if (bar_manager->show_in_fullscreen == show_in_fullscreen) return false;
    bar_manager->show_in_fullscreen = show_in_fullscreen;
    return true;
}

bool bar_manager_set_hidden(struct bar_manager *bar_manager, uint32_t adid, bool hidden) {
  bar_manager->any_bar_hidden = false;
  if (adid > 0) {
    bar_set_hidden(bar_manager->bars[adid - 1], hidden);
    bar_manager->any_bar_hidden |= hidden;
  }
  else {
    for (int i = 0; i < bar_manager->bar_count; i++) {
      bar_set_hidden(bar_manager->bars[i], hidden);
      bar_manager->any_bar_hidden |= hidden;
    }
  }

  if (hidden) {
    for (int i = 0; i < bar_manager->bar_item_count; i++) {
      popup_set_drawing(&bar_manager->bar_items[i]->popup, false);
    }
  }

  bar_manager->bar_needs_update = true;
  return true;
}

bool bar_manager_set_topmost(struct bar_manager *bar_manager, char level, bool topmost) {
  if (topmost) {
    if (level == TOPMOST_LEVEL_WINDOW) {
      bar_manager->window_level = kCGFloatingWindowLevel;
    } else if (level == TOPMOST_LEVEL_ALL) {
      bar_manager->window_level = kCGStatusWindowLevel;
    }
  } else {
    bar_manager->window_level = kCGBackstopMenuLevel;
  }

  bar_manager_reset(bar_manager);
  bar_manager->topmost = topmost;
  return true;
}

bool bar_manager_set_sticky(struct bar_manager *bar_manager, bool sticky) {
  if (sticky == bar_manager->sticky) return false;

  bar_manager->sticky = sticky;
  bar_manager_reset(bar_manager);
  return true;
}

void bar_manager_freeze(struct bar_manager *bar_manager) {
  bar_manager->frozen = true;
}

void bar_manager_unfreeze(struct bar_manager *bar_manager) {
  bar_manager->frozen = false;
}

uint32_t bar_manager_length_for_bar_side(struct bar_manager* bar_manager, struct bar* bar, char side) {
  uint32_t total_length = 0;
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    struct bar_item* bar_item = bar_manager->bar_items[i];
    if (bar_item->position == side
        && bar_item->type != BAR_COMPONENT_GROUP
        && bar_draws_item(bar, bar_item)        ) {
      int item_length = (bar_manager->position == POSITION_LEFT
                         || bar_manager->position == POSITION_RIGHT)
                        ? bar_item_get_height(bar_item)
                        : bar_item_get_length(bar_item, false);

      total_length += item_length + (bar_item->has_const_width
                                     ? 0
                                     : bar_item->background.padding_left
                                       + bar_item->background.padding_right);
    }
  }
  return total_length;
}

bool bar_manager_bar_needs_redraw(struct bar_manager* bar_manager, struct bar* bar) {
  if (bar_manager->bar_needs_update) return true;

  uint32_t bar_mask = 1 << bar->adid;
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    struct bar_item* bar_item = bar_manager->bar_items[i];
    bool draws_item = bar_draws_item(bar, bar_item);

    bool regular_update = bar_item->needs_update
                          && draws_item;

    if (regular_update) return true;

    bool disabled_item_drawn_on_bar = !bar_item->drawing
                                      && (bar_item->associated_bar != 0);

    if (disabled_item_drawn_on_bar) return true;

    if (bar_item->ignore_association) continue;

    bool not_drawn_on_associated_display =
      (draws_item
       && (bar_item->associated_display > 0)
       && (bar_item->associated_display & bar_mask)
       && !(((bar_item->associated_bar << 1) & bar_mask)))
      || (draws_item
          && bar_item->associated_to_active_display
          && bar_manager->active_adid == bar->adid
          && !((bar_item->associated_bar << 1) & bar_mask));

    if (not_drawn_on_associated_display) return true;

    bool drawn_on_non_associated_display =
      (!bar_item->associated_to_active_display
       && (bar_item->associated_display > 0)
       && !(bar_item->associated_display & bar_mask)
       && (((bar_item->associated_bar << 1) & bar_mask)))
      || (bar_item->drawing
       && bar_item->associated_to_active_display
       && (((bar_item->associated_bar << 1) & bar_mask))
       && (bar->adid != bar_manager->active_adid));

    if (drawn_on_non_associated_display) return true;

    if (bar_item->type == BAR_COMPONENT_SPACE) continue;

    bool drawn_on_non_associated_space = bar_item->associated_space > 0
                                         && !(bar_item->associated_space
                                              & (1 << bar->sid))
                                         && ((bar_item->associated_bar << 1)
                                             & bar_mask);

    if (drawn_on_non_associated_space) return true;

    bool not_drawn_on_associated_space = draws_item
                                         && bar_item->associated_space > 0
                                         && (bar_item->associated_space
                                             & (1 << bar->sid))
                                         && !((bar_item->associated_bar << 1)
                                              & bar_mask);

    if (not_drawn_on_associated_space) return true;

  }
  return false;
}

void bar_manager_clear_needs_update(struct bar_manager* bar_manager) {
  for (int i = 0; i < bar_manager->bar_item_count; i++)
    bar_manager->bar_items[i]->needs_update = false;

  bar_manager->needs_ordering = false;
  bar_manager->bar_needs_update = false;
}

void bar_manager_reset_bar_association(struct bar_manager* bar_manager) {
  for (int i = 0; i < bar_manager->bar_item_count; i++)
    bar_item_reset_associated_bar(bar_manager->bar_items[i]);
}

void bar_manager_refresh(struct bar_manager* bar_manager, bool forced, bool threaded) {
  if (bar_manager->frozen) return;
  if (forced) {
    bar_manager_reset_bar_association(bar_manager);
    for (int j = 0; j < bar_manager->bar_item_count; j++) {
      bar_item_needs_update(bar_manager->bar_items[j]);
    }
  }

  if (forced || bar_manager->bar_needs_resize) bar_manager_resize(bar_manager);

  for (int i = 0; i < bar_manager->bar_count; ++i) {
    if (forced
        || bar_manager_bar_needs_redraw(bar_manager, bar_manager->bars[i])) {
      bar_calculate_bounds(bar_manager->bars[i]);
      bar_draw(bar_manager->bars[i], false, threaded);
      if (bar_manager->needs_ordering) {
        bar_order_item_windows(bar_manager->bars[i]);
      }
    }
  }

  bar_manager_clear_needs_update(bar_manager);
  if (threaded) join_render_threads();
}

void bar_manager_resize(struct bar_manager* bar_manager) {
  for (int i = 0; i < bar_manager->bar_count; ++i)
    bar_resize(bar_manager->bars[i]);

  bar_manager->bar_needs_resize = false;
}

struct bar_item* bar_manager_create_item(struct bar_manager* bar_manager) {
  bar_manager->bar_items = (struct bar_item**) realloc(
                 bar_manager->bar_items,
                 sizeof(struct bar_item*) * (bar_manager->bar_item_count + 1));

  bar_manager->bar_item_count += 1;
  struct bar_item* bar_item = bar_item_create();
  bar_item_init(bar_item, &bar_manager->default_item);
  bar_manager->bar_items[bar_manager->bar_item_count - 1] = bar_item;
  bar_manager->needs_ordering = true;
  return bar_item;
}

void bar_manager_update_alias_components(struct bar_manager* bar_manager, bool forced) {
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    if ((!bar_item_is_shown(bar_manager->bar_items[i]) && !forced)
        || bar_manager->bar_items[i]->type != BAR_COMPONENT_ALIAS ) {
      continue;
    }

    alias_update(&bar_manager->bar_items[i]->alias, forced);
  }
}

void bar_manager_update_space_components(struct bar_manager* bar_manager, bool forced) {
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    struct bar_item* bar_item = bar_manager->bar_items[i];
    if (bar_item->type != BAR_COMPONENT_SPACE) continue;

    if (!bar_item->overrides_association) {
      uint32_t space = get_set_bit_position(bar_item->associated_space);
      uint32_t space_did = display_id_for_space(space);
      if (space_did) {
        bar_item->associated_display = 1 << (display_arrangement(space_did));
      }
      else {
        bar_item->associated_display = 1 << 30;
      }
    }
    for (int j = 0; j < bar_manager->bar_count; j++) {
      struct bar* bar = bar_manager->bars[j];
      uint32_t did = bar->adid;

      if ((1 << did) & bar_item->associated_display) {
        uint32_t sid = bar->sid;
        if (sid == 0) continue;
        if ((!bar_item->selected || forced)
            && bar_item->associated_space & (1 << sid)) {
          bar_item->selected = true;
          bar_item->updates = true;
          env_vars_set(&bar_item->signal_args.env_vars,
                       string_copy("SELECTED"),
                       string_copy("true")             );
        }
        else if ((bar_item->selected || forced)
                 && !(bar_item->associated_space & (1 << sid))) {
          bar_item->selected = false;
          bar_item->updates = true;
          env_vars_set(&bar_item->signal_args.env_vars,
                       string_copy("SELECTED"),
                       string_copy("false")            );
        }
        else {
          bar_item->updates = false;
        }
      }
    }
  }
}

void bar_manager_animator_refresh(struct bar_manager* bar_manager, uint64_t time) {
  bar_manager_freeze(bar_manager);
  if (animator_update(&bar_manager->animator, time)) {
    bar_manager_unfreeze(bar_manager);

    if (bar_manager->bar_needs_resize) bar_manager_resize(bar_manager);
    bar_manager_refresh(bar_manager, false, false);
  }
  bar_manager_unfreeze(bar_manager);
}

void bar_manager_update(struct bar_manager* bar_manager, bool forced) {
  if ((bar_manager->frozen && !forced) || bar_manager->sleeps) return;

  if (forced) {
    bar_manager_handle_space_change(bar_manager, true);
    forced_network_event();
    forced_volume_event();
    forced_brightness_event();
    forced_power_event();
    forced_front_app_event();
    forced_media_change_event();
    forced_space_windows_event();
  }

  bool needs_refresh = false;
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    struct bar_item* bar_item = bar_manager->bar_items[i];
    needs_refresh |= bar_item_update(bar_item, NULL, forced, NULL);

    if (bar_item->has_alias
        && bar_item_is_shown(bar_item)
        && alias_update(&bar_item->alias, false)) {
      bar_item_needs_update(bar_item);
      needs_refresh = true;
    }
  }

  if (needs_refresh || forced) bar_manager_refresh(bar_manager, forced, false);
}

void bar_manager_reset(struct bar_manager* bar_manager) {
  bar_manager_reset_bar_association(bar_manager);
  for (int i = 0; i < bar_manager->bar_count; i++) {
    for (int j = 0; j < bar_manager->bar_item_count; j++) {
      struct bar_item* bar_item = bar_manager->bar_items[j];
      bar_item_remove_window(bar_item, bar_manager->bars[i]->adid);
    }

    bar_destroy(bar_manager->bars[i]);
    bar_manager->bars[i] = NULL;
  }
  bar_manager->bar_count = 0;

  bar_manager_begin(bar_manager);
}

void bar_manager_begin(struct bar_manager* bar_manager) {
  if (bar_manager->displays == DISPLAY_MAIN_PATTERN) {
    uint32_t did = display_main_display_id();
    bar_manager->bar_count = 1;
    bar_manager->bars = (struct bar **) realloc(
                                bar_manager->bars,
                                sizeof(struct bar *) * bar_manager->bar_count);

    memset(bar_manager->bars, 0, sizeof(struct bar*) * bar_manager->bar_count);
    bar_manager->bars[0] = bar_create(did);
    bar_manager->bars[0]->adid = display_arrangement(did);
  }
  else {
    uint32_t display_count = display_active_display_count();
    uint32_t bar_count = 0;
    for (uint32_t index = 1; index <= display_count; index++) {
      if (!(bar_manager->displays & 1 << (index - 1))) continue;
      bar_count++;
    }

    bar_manager->bar_count = bar_count;
    bar_manager->bars = (struct bar **) realloc(
                                bar_manager->bars,
                                sizeof(struct bar *) * bar_manager->bar_count);

    memset(bar_manager->bars, 0, sizeof(struct bar*) * bar_manager->bar_count);

    uint32_t bar_index = 0;
    for (uint32_t index = 1; index <= display_count; index++) {
      if (!(bar_manager->displays & 1 << (index - 1))) continue;
      uint32_t did = display_arrangement_display_id(index);
      bar_manager->bars[bar_index] = bar_create(did);
      bar_manager->bars[bar_index]->adid = index;
      if (bar_manager->any_bar_hidden)
        bar_set_hidden(bar_manager->bars[bar_index], true);

      bar_index++;
    }
  }

  bar_manager->active_displays = 0;
  for (int i = 0; i < bar_manager->bar_count; i++) {
    bar_manager->active_displays |= 1 << bar_manager->bars[i]->adid;
  }

  bar_manager->active_adid = display_active_display_adid();
  bar_manager->needs_ordering = true;
}

struct bar_item* bar_manager_get_item_by_point(struct bar_manager* bar_manager, CGPoint point, struct window** window_out) {
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    struct bar_item* bar_item = bar_manager->bar_items[i];
    if (!bar_item->drawing) continue;

    for (int adid = 1; adid <= bar_item->num_windows; adid++) {
      struct window* window = bar_item_get_window(bar_item, adid);
      if (!window) continue;

      CGRect frame = window->frame;
      frame.origin = window->origin;
      if (cgrect_contains_point(&frame, &point)) {
        if (window_out) *window_out = window;
        return bar_item;
      }
    }
  }
  return NULL;
}

struct bar_item* bar_manager_get_item_by_wid(struct bar_manager* bar_manager, uint32_t wid, struct window** window_out) {
  for (int i = 0; i < bar_manager->bar_item_count; i++) {
    struct bar_item* bar_item = bar_manager->bar_items[i];
    if (!bar_item->drawing) continue;

    for (int adid = 1; adid <= bar_item->num_windows; adid++) {
      struct window* window = bar_item_get_window(bar_item, adid);
      if (!window) continue;

      if (window->id == wid) {
        if (window_out) *window_out = window;
        return bar_item;
      }
    }
  }
  return NULL;
}

struct bar* bar_manager_get_bar_by_wid(struct bar_manager* bar_manager, uint32_t wid) {
  for (int i = 0; i < bar_manager->bar_count; i++) {
    if (
Download .txt
gitextract_dn_wj_wt/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── makefile
├── plugins/
│   ├── battery.sh
│   ├── clock.sh
│   ├── front_app.sh
│   ├── space.sh
│   └── volume.sh
├── sketchybarrc
└── src/
    ├── alias.c
    ├── alias.h
    ├── animation.c
    ├── animation.h
    ├── app_windows.c
    ├── app_windows.h
    ├── background.c
    ├── background.h
    ├── bar.c
    ├── bar.h
    ├── bar_item.c
    ├── bar_item.h
    ├── bar_manager.c
    ├── bar_manager.h
    ├── color.c
    ├── color.h
    ├── custom_events.c
    ├── custom_events.h
    ├── display.c
    ├── display.h
    ├── event.c
    ├── event.h
    ├── font.c
    ├── font.h
    ├── graph.c
    ├── graph.h
    ├── group.c
    ├── group.h
    ├── hotload.c
    ├── hotload.h
    ├── image.c
    ├── image.h
    ├── mach.c
    ├── mach.h
    ├── media.h
    ├── media.m
    ├── message.c
    ├── message.h
    ├── misc/
    │   ├── defines.h
    │   ├── env_vars.h
    │   ├── extern.h
    │   ├── help.h
    │   └── helpers.h
    ├── mouse.c
    ├── mouse.h
    ├── popup.c
    ├── popup.h
    ├── power.c
    ├── power.h
    ├── shadow.c
    ├── shadow.h
    ├── sketchybar.c
    ├── slider.c
    ├── slider.h
    ├── text.c
    ├── text.h
    ├── volume.c
    ├── volume.h
    ├── wifi.h
    ├── wifi.m
    ├── window.c
    ├── window.h
    ├── workspace.h
    └── workspace.m
Download .txt
SYMBOL INDEX (936 symbols across 51 files)

FILE: src/alias.c
  function print_all_menu_items (line 6) | void print_all_menu_items(FILE* rsp) {
  function alias_get_permission (line 101) | void alias_get_permission(struct alias* alias) {
  function alias_init (line 118) | void alias_init(struct alias* alias) {
  function alias_find_window (line 130) | static void alias_find_window(struct alias* alias) {
  function alias_update_image (line 198) | static bool alias_update_image(struct alias* alias, bool forced) {
  function alias_setup (line 219) | void alias_setup(struct alias* alias, char* owner, char* name) {
  function alias_get_length (line 226) | uint32_t alias_get_length(struct alias* alias) {
  function alias_get_height (line 231) | uint32_t alias_get_height(struct alias* alias) {
  function alias_update (line 236) | bool alias_update(struct alias* alias, bool forced) {
  function alias_draw (line 249) | void alias_draw(struct alias* alias, CGContextRef context) {
  function alias_destroy (line 268) | void alias_destroy(struct alias* alias) {
  function alias_calculate_bounds (line 276) | void alias_calculate_bounds(struct alias* alias, uint32_t x, uint32_t y) {
  function alias_parse_sub_domain (line 280) | bool alias_parse_sub_domain(struct alias* alias, FILE* rsp, struct token...

FILE: src/alias.h
  type alias (line 9) | struct alias {
  type alias (line 26) | struct alias
  type alias (line 27) | struct alias
  type alias (line 28) | struct alias
  type alias (line 29) | struct alias
  type alias (line 31) | struct alias
  type alias (line 32) | struct alias
  type alias (line 33) | struct alias
  type alias (line 34) | struct alias
  type alias (line 38) | struct alias
  type token (line 38) | struct token

FILE: src/animation.c
  function CVReturn (line 4) | static CVReturn animation_frame_callback(CVDisplayLinkRef display_link, ...
  type animation (line 13) | struct animation
  type animation (line 14) | struct animation
  type animation (line 14) | struct animation
  type animation (line 15) | struct animation
  function animation_destroy (line 20) | static void animation_destroy(struct animation* animation) {
  function animation_lock (line 24) | static void animation_lock(struct animation* animation) {
  function animation_setup (line 28) | void animation_setup(struct animation* animation, void* target, animator...
  function animation_update (line 54) | static bool animation_update(struct animation* animation, uint64_t time,...
  function animator_init (line 125) | void animator_init(struct animator* animator) {
  function animator_renew_display_link (line 135) | void animator_renew_display_link(struct animator* animator) {
  function animator_destroy_display_link (line 147) | void animator_destroy_display_link(struct animator* animator) {
  function animator_lock (line 155) | void animator_lock(struct animator* animator) {
  function animator_calculate_offset_for_animation (line 161) | static void animator_calculate_offset_for_animation(struct animator* ani...
  function animator_add (line 182) | void animator_add(struct animator* animator, struct animation* animation) {
  function animator_remove (line 192) | static void animator_remove(struct animator* animator, struct animation*...
  function animator_cancel_locked (line 220) | void animator_cancel_locked(struct animator* animator, void* target, ani...
  function animator_cancel (line 239) | bool animator_cancel(struct animator* animator, void* target, animator_f...
  function animator_update (line 262) | bool animator_update(struct animator* animator, uint64_t time) {
  function animator_destroy (line 286) | void animator_destroy(struct animator* animator) {

FILE: src/animation.h
  type bar_manager (line 5) | struct bar_manager
  type ANIMATOR_FUNCTION (line 69) | typedef ANIMATOR_FUNCTION(animator_function);
  type ANIMATION_FUNCTION (line 72) | typedef ANIMATION_FUNCTION(animation_function);
  type animation (line 84) | struct animation {
  type animation (line 105) | struct animation
  type animation (line 106) | struct animation
  type animator (line 108) | struct animator {
  type animator (line 118) | struct animator
  type animator (line 119) | struct animator
  type animation (line 119) | struct animation
  type animator (line 121) | struct animator
  type animator (line 122) | struct animator
  type animator (line 124) | struct animator
  type animator (line 125) | struct animator
  type animator (line 126) | struct animator
  type animator (line 128) | struct animator
  type animator (line 129) | struct animator

FILE: src/app_windows.c
  type app_windows (line 7) | struct app_windows
  type app_windows (line 8) | struct app_windows
  function iterator_window_suitable (line 11) | static bool iterator_window_suitable(CFTypeRef iterator) {
  function app_window_clear (line 26) | void app_window_clear(struct app_window* window) {
  function app_windows_add (line 30) | void app_windows_add(struct app_windows* windows, struct app_window* win...
  function app_windows_clear_space (line 45) | void app_windows_clear_space(struct app_windows* windows, uint64_t sid) {
  function app_windows_register_notifications (line 51) | void app_windows_register_notifications() {
  function app_windows_find (line 66) | bool app_windows_find(struct app_windows* windows, struct app_window* wi...
  type app_window (line 76) | struct app_window
  type app_windows (line 76) | struct app_windows
  function app_window_suitable (line 83) | static bool app_window_suitable(struct app_window* window) {
  function app_windows_post_event_for_space (line 107) | static void app_windows_post_event_for_space(struct app_windows* windows...
  function app_windows_update_space (line 177) | static void app_windows_update_space(struct app_windows* windows, uint64...
  type window_spawn_data (line 225) | struct window_spawn_data {
  function window_spawn_handler (line 230) | static void window_spawn_handler(uint32_t event, struct window_spawn_dat...
  function window_hide_handler (line 248) | static void window_hide_handler(uint32_t event, uint32_t* window_id, siz...
  function update_all_spaces (line 269) | static void update_all_spaces(struct app_windows* windows, bool silent) {
  function space_handler (line 283) | static void space_handler(uint32_t event, void* data, size_t data_length...
  function forced_space_windows_event (line 287) | void forced_space_windows_event() {
  function begin_receiving_space_window_events (line 291) | void begin_receiving_space_window_events() {

FILE: src/app_windows.h
  type app_window (line 4) | struct app_window {
  type app_windows (line 10) | struct app_windows {

FILE: src/background.c
  function background_init (line 8) | void background_init(struct background* background) {
  function background_set_height (line 30) | bool background_set_height(struct background* background, uint32_t heigh...
  function background_reset_clip (line 37) | static void background_reset_clip(struct background* background) {
  function background_set_enabled (line 46) | bool background_set_enabled(struct background* background, bool enabled) {
  function background_set_color (line 59) | bool background_set_color(struct background* background, uint32_t color) {
  function background_set_clip (line 64) | static bool background_set_clip(struct background* background, float cli...
  function background_set_border_color (line 73) | static bool background_set_border_color(struct background* background, u...
  function background_set_border_width (line 77) | static bool background_set_border_width(struct background* background, u...
  function background_set_corner_radius (line 83) | static bool background_set_corner_radius(struct background* background, ...
  function background_set_xoffset (line 89) | static bool background_set_xoffset(struct background* background, int of...
  function background_set_yoffset (line 95) | static bool background_set_yoffset(struct background* background, int of...
  function background_set_padding_left (line 101) | bool background_set_padding_left(struct background* background, uint32_t...
  function background_set_padding_right (line 107) | bool background_set_padding_right(struct background* background, uint32_...
  function background_clip_needs_update (line 113) | bool background_clip_needs_update(struct background* background, struct ...
  function background_update_clip (line 123) | static void background_update_clip(struct background* background, struct...
  type background (line 128) | struct background
  type background (line 128) | struct background
  type background (line 131) | struct background
  type background (line 132) | struct background
  type background (line 135) | struct background
  type background (line 141) | struct background
  type background (line 141) | struct background
  function background_clips_bar (line 151) | bool background_clips_bar(struct background* background) {
  function background_clip_bar (line 155) | void background_clip_bar(struct background* background, int offset, stru...
  function background_calculate_bounds (line 171) | void background_calculate_bounds(struct background* background, uint32_t...
  function draw_rect (line 181) | static void draw_rect(CGContextRef context, CGRect region, struct color*...
  function background_draw (line 196) | void background_draw(struct background* background, CGContextRef context) {
  function background_clear_pointers (line 232) | void background_clear_pointers(struct background* background) {
  function background_destroy (line 238) | void background_destroy(struct background* background) {
  function background_serialize (line 248) | void background_serialize(struct background* background, char* indent, F...
  function background_parse_sub_domain (line 286) | bool background_parse_sub_domain(struct background* background, FILE* rs...

FILE: src/background.h
  type background (line 4) | struct background {
  type bar (line 26) | struct bar
  type background (line 28) | struct background
  type background (line 29) | struct background
  type background (line 31) | struct background
  type background (line 32) | struct background
  type background (line 33) | struct background
  type background (line 34) | struct background
  type background (line 35) | struct background
  type background (line 37) | struct background
  type background (line 39) | struct background
  type background (line 39) | struct background
  type background (line 40) | struct background
  type bar (line 40) | struct bar
  type background (line 41) | struct background
  type bar (line 41) | struct bar
  type background (line 42) | struct background
  type background (line 44) | struct background
  type background (line 45) | struct background
  type background (line 47) | struct background
  type background (line 48) | struct background
  type token (line 48) | struct token

FILE: src/bar.c
  function join_render_threads (line 12) | void join_render_threads() {
  function bar_draws_item (line 18) | bool bar_draws_item(struct bar* bar, struct bar_item* bar_item) {
  function bar_calculate_popup_anchor_for_bar_item (line 43) | static void bar_calculate_popup_anchor_for_bar_item(struct bar* bar, str...
  function bar_order_item_windows (line 92) | void bar_order_item_windows(struct bar* bar) {
  function bar_check_for_clip_updates (line 123) | static void bar_check_for_clip_updates(struct bar* bar) {
  function bar_draw (line 150) | void bar_draw(struct bar* bar, bool forced, bool threaded) {
  function bar_calculate_bounds_top_bottom (line 228) | static void bar_calculate_bounds_top_bottom(struct bar* bar) {
  function bar_calculate_bounds_left_right (line 348) | static void bar_calculate_bounds_left_right(struct bar* bar) {
  function bar_calculate_bounds (line 454) | void bar_calculate_bounds(struct bar* bar) {
  function CGRect (line 465) | static CGRect bar_get_frame(struct bar *bar) {
  function bar_resize (line 524) | void bar_resize(struct bar* bar) {
  function bar_set_hidden (line 536) | void bar_set_hidden(struct bar* bar, bool hidden) {
  function bar_create_window (line 544) | static void bar_create_window(struct bar* bar) {
  function bar_change_space (line 554) | void bar_change_space(struct bar* bar, uint64_t dsid) {
  type bar (line 565) | struct bar
  type bar (line 566) | struct bar
  type bar (line 566) | struct bar
  type bar (line 567) | struct bar
  function bar_destroy (line 579) | void bar_destroy(struct bar *bar) {

FILE: src/bar.h
  type bar (line 6) | struct bar {
  type bar (line 19) | struct bar
  type bar (line 20) | struct bar
  type bar (line 21) | struct bar
  type bar (line 22) | struct bar
  type bar (line 23) | struct bar
  type bar (line 24) | struct bar
  type bar (line 25) | struct bar
  type bar (line 26) | struct bar
  type bar (line 28) | struct bar
  type bar_item (line 28) | struct bar_item
  type bar (line 30) | struct bar

FILE: src/bar_item.c
  type bar_item (line 9) | struct bar_item
  type bar_item (line 10) | struct bar_item
  type bar_item (line 10) | struct bar_item
  type bar_item (line 11) | struct bar_item
  function bar_item_init (line 15) | void bar_item_init(struct bar_item* bar_item, struct bar_item* default_i...
  function bar_item_append_associated_space (line 66) | void bar_item_append_associated_space(struct bar_item* bar_item, uint32_...
  function bar_item_append_associated_display (line 79) | void bar_item_append_associated_display(struct bar_item* bar_item, uint3...
  function bar_item_is_shown (line 93) | bool bar_item_is_shown(struct bar_item* bar_item) {
  function bar_item_append_associated_bar (line 98) | void bar_item_append_associated_bar(struct bar_item* bar_item, uint32_t ...
  function bar_item_remove_associated_bar (line 102) | void bar_item_remove_associated_bar(struct bar_item* bar_item, uint32_t ...
  function bar_item_reset_associated_bar (line 106) | void bar_item_reset_associated_bar(struct bar_item* bar_item) {
  function bar_item_update (line 110) | bool bar_item_update(struct bar_item* bar_item, char* sender, bool force...
  function bar_item_needs_update (line 176) | void bar_item_needs_update(struct bar_item* bar_item) {
  function bar_item_cancel_drag (line 180) | void bar_item_cancel_drag(struct bar_item* bar_item) {
  function bar_item_on_drag (line 192) | void bar_item_on_drag(struct bar_item* bar_item, CGPoint point) {
  function bar_item_on_click (line 200) | void bar_item_on_click(struct bar_item* bar_item, uint32_t type, uint32_...
  function bar_item_on_scroll (line 259) | void bar_item_on_scroll(struct bar_item* bar_item, int scroll_delta, uin...
  function bar_item_mouse_entered (line 297) | void bar_item_mouse_entered(struct bar_item* bar_item) {
  function bar_item_mouse_exited (line 304) | void bar_item_mouse_exited(struct bar_item* bar_item) {
  function bar_item_set_drawing (line 311) | static bool bar_item_set_drawing(struct bar_item* bar_item, bool state) {
  function bar_item_set_script (line 317) | static void bar_item_set_script(struct bar_item* bar_item, char* script) {
  function bar_item_set_click_script (line 332) | static void bar_item_set_click_script(struct bar_item* bar_item, char* s...
  function bar_item_set_yoffset (line 347) | static bool bar_item_set_yoffset(struct bar_item* bar_item, int offset) {
  function bar_item_set_blur_radius (line 353) | static bool bar_item_set_blur_radius(struct bar_item* bar_item, uint32_t...
  function bar_item_set_width (line 363) | static bool bar_item_set_width(struct bar_item* bar_item, int width) {
  function bar_item_set_event_port (line 377) | static void bar_item_set_event_port(struct bar_item* bar_item, char* bs_...
  function bar_item_set_name (line 382) | bool bar_item_set_name(struct bar_item* bar_item, char* name) {
  function bar_item_set_type (line 400) | bool bar_item_set_type(struct bar_item* bar_item, char* type) {
  function bar_item_set_position (line 456) | bool bar_item_set_position(struct bar_item* bar_item, char* position) {
  function bar_item_set_media_cover (line 486) | bool bar_item_set_media_cover(struct bar_item* bar_item, struct image* i...
  function bar_item_get_content_length (line 494) | static uint32_t bar_item_get_content_length(struct bar_item* bar_item) {
  function bar_item_get_length (line 504) | uint32_t bar_item_get_length(struct bar_item* bar_item, bool ignore_over...
  function bar_item_get_height (line 521) | uint32_t bar_item_get_height(struct bar_item* bar_item) {
  type window (line 542) | struct window
  type bar_item (line 542) | struct bar_item
  type window (line 545) | struct window
  type window (line 546) | struct window
  type window (line 549) | struct window
  type window (line 555) | struct window
  function bar_item_remove_window (line 573) | void bar_item_remove_window(struct bar_item* bar_item, uint32_t adid) {
  function CGPoint (line 581) | CGPoint bar_item_calculate_shadow_offsets(struct bar_item* bar_item) {
  function bar_item_calculate_bounds (line 623) | uint32_t bar_item_calculate_bounds(struct bar_item* bar_item, uint32_t b...
  function bar_item_clip_needs_update_for_bar (line 697) | bool bar_item_clip_needs_update_for_bar(struct bar_item* bar_item, struc...
  function bar_item_clips_bar (line 707) | bool bar_item_clips_bar(struct bar_item* bar_item) {
  function bar_item_clip_bar (line 713) | void bar_item_clip_bar(struct bar_item* bar_item, int offset, struct bar...
  type window (line 720) | struct window
  type bar_item (line 720) | struct bar_item
  function bar_item_draw (line 729) | void bar_item_draw(struct bar_item* bar_item, CGContextRef context) {
  function bar_item_change_space (line 741) | void bar_item_change_space(struct bar_item* bar_item, uint64_t dsid, uin...
  function bar_item_clear_pointers (line 748) | static void bar_item_clear_pointers(struct bar_item* bar_item) {
  function bar_item_inherit_from_item (line 765) | void bar_item_inherit_from_item(struct bar_item* bar_item, struct bar_it...
  function bar_item_destroy (line 815) | void bar_item_destroy(struct bar_item* bar_item, bool free_memory) {
  function bar_item_serialize (line 844) | void bar_item_serialize(struct bar_item* bar_item, FILE* rsp) {
  function bar_item_parse_set_message (line 993) | void bar_item_parse_set_message(struct bar_item* bar_item, char* message...
  function bar_item_parse_subscribe_message (line 1248) | void bar_item_parse_subscribe_message(struct bar_item* bar_item, char* m...

FILE: src/bar_item.h
  type bar_item (line 21) | struct bar_item {
  type bar_item (line 99) | struct bar_item
  type bar_item (line 100) | struct bar_item
  type bar_item (line 100) | struct bar_item
  type bar_item (line 101) | struct bar_item
  type bar_item (line 101) | struct bar_item
  type bar_item (line 102) | struct bar_item
  type bar_item (line 103) | struct bar_item
  type bar_item (line 105) | struct bar_item
  type bar_item (line 106) | struct bar_item
  type bar_item (line 107) | struct bar_item
  type env_vars (line 107) | struct env_vars
  type bar_item (line 109) | struct bar_item
  type bar_item (line 110) | struct bar_item
  type bar_item (line 111) | struct bar_item
  type bar_item (line 112) | struct bar_item
  type bar_item (line 113) | struct bar_item
  type bar_item (line 114) | struct bar_item
  type bar_item (line 116) | struct bar_item
  type bar_item (line 117) | struct bar_item
  type bar_item (line 118) | struct bar_item
  type bar_item (line 119) | struct bar_item
  type bar_item (line 120) | struct bar_item
  type bar_item (line 122) | struct bar_item
  type bar_item (line 123) | struct bar_item
  type bar_item (line 124) | struct bar_item
  type bar_item (line 125) | struct bar_item
  type image (line 125) | struct image
  type bar_item (line 127) | struct bar_item
  type bar_item (line 128) | struct bar_item
  type window (line 130) | struct window
  type bar_item (line 130) | struct bar_item
  type bar_item (line 131) | struct bar_item
  type bar_item (line 133) | struct bar_item
  type bar_item (line 134) | struct bar_item
  type bar_item (line 136) | struct bar_item
  type bar_item (line 137) | struct bar_item
  type bar (line 137) | struct bar
  type bar_item (line 138) | struct bar_item
  type bar (line 138) | struct bar
  type bar_item (line 139) | struct bar_item
  type bar_item (line 141) | struct bar_item
  type bar_item (line 143) | struct bar_item
  type bar_item (line 144) | struct bar_item

FILE: src/bar_manager.c
  function CLOCK_CALLBACK (line 16) | static CLOCK_CALLBACK(clock_handler) {
  function bar_manager_init (line 21) | void bar_manager_init(struct bar_manager* bar_manager) {
  function bar_manager_sort (line 81) | void bar_manager_sort(struct bar_manager* bar_manager, struct bar_item**...
  function bar_manager_get_item_index_for_name (line 102) | int bar_manager_get_item_index_for_name(struct bar_manager* bar_manager,...
  function bar_manager_get_item_index_by_address (line 111) | int bar_manager_get_item_index_by_address(struct bar_manager* bar_manage...
  function bar_manager_move_item (line 120) | void bar_manager_move_item(struct bar_manager* bar_manager, struct bar_i...
  function bar_manager_remove_item (line 148) | void bar_manager_remove_item(struct bar_manager* bar_manager, struct bar...
  function bar_manager_set_margin (line 183) | bool bar_manager_set_margin(struct bar_manager* bar_manager, int margin) {
  function bar_manager_set_y_offset (line 190) | bool bar_manager_set_y_offset(struct bar_manager* bar_manager, int y_off...
  function bar_manager_set_bar_height (line 197) | bool bar_manager_set_bar_height(struct bar_manager* bar_manager, int hei...
  function bar_manager_set_background_blur (line 202) | bool bar_manager_set_background_blur(struct bar_manager* bar_manager, ui...
  function bar_manager_set_position (line 211) | bool bar_manager_set_position(struct bar_manager* bar_manager, char pos) {
  function bar_manager_set_displays (line 218) | bool bar_manager_set_displays(struct bar_manager* bar_manager, uint32_t ...
  function bar_manager_set_shadow (line 226) | bool bar_manager_set_shadow(struct bar_manager* bar_manager, bool shadow) {
  function bar_manager_set_notch_width (line 233) | bool bar_manager_set_notch_width(struct bar_manager* bar_manager, uint32...
  function bar_manager_set_notch_offset (line 240) | bool bar_manager_set_notch_offset(struct bar_manager* bar_manager, uint3...
  function bar_manager_set_notch_display_height (line 248) | bool bar_manager_set_notch_display_height(struct bar_manager* bar_manage...
  function bar_manager_set_font_smoothing (line 256) | bool bar_manager_set_font_smoothing(struct bar_manager* bar_manager, boo...
  function bar_manager_set_show_in_fullscreen (line 264) | bool bar_manager_set_show_in_fullscreen(struct bar_manager* bar_manager,...
  function bar_manager_set_hidden (line 270) | bool bar_manager_set_hidden(struct bar_manager *bar_manager, uint32_t ad...
  function bar_manager_set_topmost (line 293) | bool bar_manager_set_topmost(struct bar_manager *bar_manager, char level...
  function bar_manager_set_sticky (line 309) | bool bar_manager_set_sticky(struct bar_manager *bar_manager, bool sticky) {
  function bar_manager_freeze (line 317) | void bar_manager_freeze(struct bar_manager *bar_manager) {
  function bar_manager_unfreeze (line 321) | void bar_manager_unfreeze(struct bar_manager *bar_manager) {
  function bar_manager_length_for_bar_side (line 325) | uint32_t bar_manager_length_for_bar_side(struct bar_manager* bar_manager...
  function bar_manager_bar_needs_redraw (line 346) | bool bar_manager_bar_needs_redraw(struct bar_manager* bar_manager, struc...
  function bar_manager_clear_needs_update (line 413) | void bar_manager_clear_needs_update(struct bar_manager* bar_manager) {
  function bar_manager_reset_bar_association (line 421) | void bar_manager_reset_bar_association(struct bar_manager* bar_manager) {
  function bar_manager_refresh (line 426) | void bar_manager_refresh(struct bar_manager* bar_manager, bool forced, b...
  function bar_manager_resize (line 452) | void bar_manager_resize(struct bar_manager* bar_manager) {
  type bar_item (line 459) | struct bar_item
  type bar_manager (line 459) | struct bar_manager
  type bar_item (line 460) | struct bar_item
  type bar_item (line 462) | struct bar_item
  type bar_item (line 465) | struct bar_item
  function bar_manager_update_alias_components (line 472) | void bar_manager_update_alias_components(struct bar_manager* bar_manager...
  function bar_manager_update_space_components (line 483) | void bar_manager_update_space_components(struct bar_manager* bar_manager...
  function bar_manager_animator_refresh (line 529) | void bar_manager_animator_refresh(struct bar_manager* bar_manager, uint6...
  function bar_manager_update (line 540) | void bar_manager_update(struct bar_manager* bar_manager, bool forced) {
  function bar_manager_reset (line 570) | void bar_manager_reset(struct bar_manager* bar_manager) {
  function bar_manager_begin (line 586) | void bar_manager_begin(struct bar_manager* bar_manager) {
  type bar_item (line 635) | struct bar_item
  type bar_manager (line 635) | struct bar_manager
  type window (line 635) | struct window
  type bar_item (line 637) | struct bar_item
  type window (line 641) | struct window
  type bar_item (line 655) | struct bar_item
  type bar_manager (line 655) | struct bar_manager
  type window (line 655) | struct window
  type bar_item (line 657) | struct bar_item
  type window (line 661) | struct window
  type bar (line 673) | struct bar
  type bar_manager (line 673) | struct bar_manager
  function bar_manager_mouse_over_any_bar (line 682) | bool bar_manager_mouse_over_any_bar(struct bar_manager* bar_manager) {
  type popup (line 689) | struct popup
  type bar_manager (line 689) | struct bar_manager
  type bar_item (line 691) | struct bar_item
  type window (line 696) | struct window
  type popup (line 705) | struct popup
  type bar_manager (line 705) | struct bar_manager
  type bar_item (line 707) | struct bar_item
  type window (line 712) | struct window
  type bar (line 723) | struct bar
  type bar_manager (line 723) | struct bar_manager
  type window (line 725) | struct window
  function bar_manager_mouse_over_any_popup (line 735) | bool bar_manager_mouse_over_any_popup(struct bar_manager* bar_manager) {
  function bar_manager_custom_events_trigger (line 746) | void bar_manager_custom_events_trigger(struct bar_manager* bar_manager, ...
  function bar_manager_display_resized (line 757) | void bar_manager_display_resized(struct bar_manager* bar_manager, uint32...
  function bar_manager_display_moved (line 761) | void bar_manager_display_moved(struct bar_manager* bar_manager, uint32_t...
  function bar_manager_display_removed (line 765) | void bar_manager_display_removed(struct bar_manager* bar_manager, uint32...
  function bar_manager_display_added (line 769) | void bar_manager_display_added(struct bar_manager* bar_manager, uint32_t...
  function bar_manager_display_changed (line 773) | void bar_manager_display_changed(struct bar_manager* bar_manager) {
  function bar_manager_cancel_drag (line 786) | void bar_manager_cancel_drag(struct bar_manager* bar_manager) {
  function bar_manager_handle_mouse_entered_global (line 792) | void bar_manager_handle_mouse_entered_global(struct bar_manager* bar_man...
  function bar_manager_handle_mouse_exited_global (line 798) | void bar_manager_handle_mouse_exited_global(struct bar_manager* bar_mana...
  function bar_manager_handle_mouse_scrolled_global (line 806) | void bar_manager_handle_mouse_scrolled_global(struct bar_manager* bar_ma...
  function bar_manager_handle_mouse_entered (line 843) | void bar_manager_handle_mouse_entered(struct bar_manager* bar_manager, s...
  function bar_manager_handle_mouse_exited (line 848) | void bar_manager_handle_mouse_exited(struct bar_manager* bar_manager, st...
  function bar_manager_handle_volume_change (line 857) | void bar_manager_handle_volume_change(struct bar_manager* bar_manager, f...
  function bar_manager_handle_wifi_change (line 869) | void bar_manager_handle_wifi_change(struct bar_manager* bar_manager, cha...
  function bar_manager_handle_brightness_change (line 879) | void bar_manager_handle_brightness_change(struct bar_manager* bar_manage...
  function bar_manager_handle_power_source_change (line 891) | void bar_manager_handle_power_source_change(struct bar_manager* bar_mana...
  function bar_manager_handle_media_change (line 901) | void bar_manager_handle_media_change(struct bar_manager* bar_manager, ch...
  function bar_manager_handle_media_cover_change (line 911) | void bar_manager_handle_media_cover_change(struct bar_manager* bar_manag...
  function bar_manager_handle_front_app_switch (line 924) | void bar_manager_handle_front_app_switch(struct bar_manager* bar_manager...
  function bar_manager_handle_space_windows_change (line 934) | void bar_manager_handle_space_windows_change(struct bar_manager* bar_man...
  function bar_manager_handle_space_change (line 944) | void bar_manager_handle_space_change(struct bar_manager* bar_manager, bo...
  function bar_manager_poll_active_display (line 996) | void bar_manager_poll_active_display(struct bar_manager* bar_manager) {
  function bar_manager_handle_display_change (line 1003) | void bar_manager_handle_display_change(struct bar_manager* bar_manager) {
  function bar_manager_handle_system_will_sleep (line 1019) | void bar_manager_handle_system_will_sleep(struct bar_manager* bar_manage...
  function bar_manager_handle_system_woke (line 1027) | void bar_manager_handle_system_woke(struct bar_manager* bar_manager) {
  function bar_manager_handle_notification (line 1048) | void bar_manager_handle_notification(struct bar_manager* bar_manager, st...
  function bar_manager_destroy (line 1066) | void bar_manager_destroy(struct bar_manager* bar_manager) {
  function bar_manager_serialize (line 1099) | void bar_manager_serialize(struct bar_manager* bar_manager, FILE* rsp) {

FILE: src/bar_manager.h
  type CLOCK_CALLBACK (line 7) | typedef CLOCK_CALLBACK(clock_callback);
  type bar_manager (line 15) | struct bar_manager {
  type bar_manager (line 57) | struct bar_manager
  type bar_manager (line 58) | struct bar_manager
  type bar_manager (line 59) | struct bar_manager
  type bar_item (line 61) | struct bar_item
  type bar_manager (line 61) | struct bar_manager
  type bar_manager (line 62) | struct bar_manager
  type bar_item (line 62) | struct bar_item
  type bar_manager (line 63) | struct bar_manager
  type bar_item (line 63) | struct bar_item
  type bar_item (line 63) | struct bar_item
  type bar_manager (line 64) | struct bar_manager
  type notification (line 64) | struct notification
  type bar_manager (line 66) | struct bar_manager
  type bar_manager (line 67) | struct bar_manager
  type bar_manager (line 68) | struct bar_manager
  type bar_manager (line 69) | struct bar_manager
  type bar_manager (line 70) | struct bar_manager
  type bar_manager (line 71) | struct bar_manager
  type bar_manager (line 72) | struct bar_manager
  type bar_manager (line 73) | struct bar_manager
  type bar_manager (line 74) | struct bar_manager
  type bar_manager (line 75) | struct bar_manager
  type bar_manager (line 76) | struct bar_manager
  type bar_manager (line 77) | struct bar_manager
  type bar_manager (line 78) | struct bar_manager
  type bar_manager (line 79) | struct bar_manager
  type bar_manager (line 80) | struct bar_manager
  type bar_manager (line 81) | struct bar_manager
  type bar_manager (line 82) | struct bar_manager
  type bar_manager (line 83) | struct bar_manager
  type bar_manager (line 84) | struct bar_manager
  type bar_manager (line 85) | struct bar_manager
  type bar_manager (line 86) | struct bar_manager
  type bar_item (line 86) | struct bar_item
  type bar_item (line 88) | struct bar_item
  type bar_manager (line 88) | struct bar_manager
  type window (line 88) | struct window
  type bar (line 89) | struct bar
  type bar_manager (line 89) | struct bar_manager
  type popup (line 90) | struct popup
  type bar_manager (line 90) | struct bar_manager
  type bar_item (line 91) | struct bar_item
  type bar_manager (line 91) | struct bar_manager
  type window (line 91) | struct window
  type popup (line 92) | struct popup
  type bar_manager (line 92) | struct bar_manager
  type bar (line 93) | struct bar
  type bar_manager (line 93) | struct bar_manager
  type bar_manager (line 94) | struct bar_manager
  type bar_manager (line 95) | struct bar_manager
  type bar (line 95) | struct bar
  type bar_manager (line 96) | struct bar_manager
  type bar_manager (line 97) | struct bar_manager
  type bar_manager (line 99) | struct bar_manager
  type bar_manager (line 100) | struct bar_manager
  type bar_manager (line 102) | struct bar_manager
  type bar_manager (line 103) | struct bar_manager
  type bar_manager (line 104) | struct bar_manager
  type bar_manager (line 105) | struct bar_manager
  type bar_manager (line 106) | struct bar_manager
  type bar_manager (line 107) | struct bar_manager
  type bar_manager (line 108) | struct bar_manager
  type bar_manager (line 110) | struct bar_manager
  type bar_manager (line 111) | struct bar_manager
  type bar_manager (line 112) | struct bar_manager
  type bar_manager (line 113) | struct bar_manager
  type bar_manager (line 114) | struct bar_manager
  type bar_item (line 114) | struct bar_item
  type bar_manager (line 115) | struct bar_manager
  type bar_item (line 115) | struct bar_item
  type bar_manager (line 116) | struct bar_manager
  type bar_manager (line 117) | struct bar_manager
  type bar_manager (line 118) | struct bar_manager
  type bar_manager (line 119) | struct bar_manager
  type bar_manager (line 120) | struct bar_manager
  type bar_manager (line 121) | struct bar_manager
  type bar_manager (line 122) | struct bar_manager
  type bar_manager (line 123) | struct bar_manager
  type bar_manager (line 124) | struct bar_manager
  type bar_manager (line 125) | struct bar_manager
  type bar_manager (line 126) | struct bar_manager
  type bar_manager (line 127) | struct bar_manager
  type bar_manager (line 128) | struct bar_manager
  type env_vars (line 128) | struct env_vars
  type bar_manager (line 130) | struct bar_manager
  type bar_manager (line 132) | struct bar_manager

FILE: src/color.c
  function color_update_hex (line 5) | static bool color_update_hex(struct color* color) {
  function color_init (line 15) | void color_init(struct color* color, uint32_t hex) {
  function color_set_hex (line 19) | bool color_set_hex(struct color* color, uint32_t hex) {
  function color_set_alpha (line 27) | bool color_set_alpha(struct color* color, float alpha) {
  function color_set_r (line 32) | bool color_set_r(struct color* color, float red) {
  function color_set_g (line 37) | bool color_set_g(struct color* color, float green) {
  function color_set_b (line 42) | bool color_set_b(struct color* color, float blue) {
  function color_parse_sub_domain (line 47) | bool color_parse_sub_domain(struct color* color, FILE* rsp, struct token...

FILE: src/color.h
  type color (line 6) | struct color {
  type color (line 14) | struct color
  type color (line 16) | struct color
  type color (line 17) | struct color
  type color (line 18) | struct color
  type color (line 19) | struct color
  type color (line 20) | struct color
  type color (line 21) | struct color
  type color (line 23) | struct color
  type token (line 23) | struct token

FILE: src/custom_events.c
  type custom_event (line 3) | struct custom_event
  type custom_event (line 4) | struct custom_event
  function custom_event_init (line 7) | void custom_event_init(struct custom_event* custom_event, char* name, ch...
  function custom_event_destroy (line 12) | void custom_event_destroy(struct custom_event* custom_event) {
  function custom_events_init (line 18) | void custom_events_init(struct custom_events* custom_events) {
  function custom_events_append (line 43) | void custom_events_append(struct custom_events* custom_events, char* nam...
  function custom_events_get_flag_for_name (line 61) | uint64_t custom_events_get_flag_for_name(struct custom_events* custom_ev...
  type custom_events (line 70) | struct custom_events
  function custom_events_destroy (line 80) | void custom_events_destroy(struct custom_events* custom_events) {
  function custom_events_serialize (line 87) | void custom_events_serialize(struct custom_events* custom_events, FILE* ...

FILE: src/custom_events.h
  type custom_event (line 26) | struct custom_event {
  type custom_event (line 31) | struct custom_event
  type custom_events (line 33) | struct custom_events {
  type custom_events (line 38) | struct custom_events
  type custom_events (line 39) | struct custom_events
  type custom_events (line 40) | struct custom_events
  type custom_events (line 41) | struct custom_events
  type custom_events (line 42) | struct custom_events
  type custom_events (line 44) | struct custom_events

FILE: src/display.c
  function brightness_handler (line 11) | static void brightness_handler(void* notification_center, uint32_t did, ...
  function DISPLAY_EVENT_HANDLER (line 23) | static DISPLAY_EVENT_HANDLER(display_handler) {
  function CFStringRef (line 45) | CFStringRef display_uuid(uint32_t did) {
  function CGRect (line 55) | CGRect display_bounds(uint32_t did) {
  function display_space_id (line 59) | uint64_t display_space_id(uint32_t did) {
  function display_arrangement (line 103) | int display_arrangement(uint32_t did) {
  function display_main_display_id (line 135) | uint32_t display_main_display_id(void) {
  function CFStringRef (line 139) | static CFStringRef display_active_display_uuid(void) {
  function display_active_display_id (line 160) | uint32_t display_active_display_id(void) {
  function CFStringRef (line 181) | CFStringRef display_arrangement_display_uuid(int arrangement) {
  function display_arrangement_display_id (line 196) | uint32_t display_arrangement_display_id(int arrangement) {
  function display_active_display_adid (line 214) | uint32_t display_active_display_adid(void) {
  function display_menu_bar_visible (line 239) | bool display_menu_bar_visible(void) {
  function CGRect (line 245) | CGRect display_menu_bar_rect(uint32_t did) {
  function display_active_display_count (line 264) | uint32_t display_active_display_count(void) {
  function display_begin (line 277) | bool display_begin() {
  function display_end (line 282) | bool display_end() {
  function forced_brightness_event (line 287) | void forced_brightness_event() {
  function begin_receiving_brightness_events (line 292) | void begin_receiving_brightness_events() {
  function display_serialize (line 305) | void display_serialize(FILE* rsp) {

FILE: src/display.h
  type DISPLAY_EVENT_HANDLER (line 6) | typedef DISPLAY_EVENT_HANDLER(display_callback);

FILE: src/event.c
  type bar_manager (line 6) | struct bar_manager
  function event_distributed_notification (line 10) | static void event_distributed_notification(void* context) {
  function event_application_front_switched (line 14) | static void event_application_front_switched(void* context) {
  function event_space_changed (line 18) | static void event_space_changed(void* context) {
  function event_display_changed (line 22) | static void event_display_changed(void* context) {
  function event_display_added (line 26) | static void event_display_added(void* context) {
  function event_display_removed (line 31) | static void event_display_removed(void* context) {
  function event_display_moved (line 36) | static void event_display_moved(void* context) {
  function event_display_resized (line 41) | static void event_display_resized(void* context) {
  function event_menu_bar_hidden_changed (line 46) | static void event_menu_bar_hidden_changed(void* context) {
  function event_system_woke (line 52) | static void event_system_woke(void* context) {
  function event_system_will_sleep (line 56) | static void event_system_will_sleep(void* context) {
  function event_shell_refresh (line 60) | static void event_shell_refresh(void* context) {
  function event_animator_refresh (line 64) | static void event_animator_refresh(void* context) {
  function event_mach_message (line 68) | static void event_mach_message(void* context) {
  function event_mouse_up (line 72) | static void event_mouse_up(void* context) {
  function event_mouse_dragged (line 108) | static void event_mouse_dragged(void* context) {
  function event_mouse_entered (line 131) | static void event_mouse_entered(void* context) {
  function event_mouse_exited (line 163) | static void event_mouse_exited(void* context) {
  function event_mouse_scrolled (line 239) | static void event_mouse_scrolled(void* context) {
  function event_volume_changed (line 311) | static void event_volume_changed(void* context) {
  function event_wifi_changed (line 315) | static void event_wifi_changed(void* context) {
  function event_brightness_changed (line 319) | static void event_brightness_changed(void* context) {
  function event_power_source_changed (line 323) | static void event_power_source_changed(void* context) {
  function event_media_changed (line 327) | static void event_media_changed(void* context) {
  function event_cover_changed (line 331) | static void event_cover_changed(void* context) {
  function event_space_windows_changed (line 335) | static void event_space_windows_changed(void* context) {
  function event_hotload (line 339) | static void event_hotload(void* context) {
  function event_post (line 377) | void event_post(struct event *event) {

FILE: src/event.h
  type event_type (line 5) | enum event_type {
  type event (line 39) | struct event {
  type event (line 44) | struct event

FILE: src/font.c
  type feature_mapping (line 5) | struct feature_mapping {
  type feature_mapping (line 12) | struct feature_mapping
  function get_truetype_feature (line 49) | void get_truetype_feature(const char* opentype_tag, int* truetype_featur...
  function font_register (line 59) | void font_register(char* font_path) {
  function font_create_ctfont (line 78) | void font_create_ctfont(struct font* font) {
  function font_init (line 155) | void font_init(struct font* font) {
  function font_set_style (line 162) | bool font_set_style(struct font* font, char* style, bool forced) {
  function font_set_family (line 175) | bool font_set_family(struct font* font, char* family, bool forced) {
  function font_set_size (line 188) | bool font_set_size(struct font* font, float size) {
  function font_set_features (line 197) | bool font_set_features(struct font* font, char* features) {
  function font_set (line 210) | bool font_set(struct font* font, char* font_string, bool forced) {
  function font_clear_pointers (line 230) | void font_clear_pointers(struct font* font) {
  function font_destroy (line 237) | void font_destroy(struct font* font) {
  function font_parse_sub_domain (line 245) | bool font_parse_sub_domain(struct font* font, FILE* rsp, struct token pr...

FILE: src/font.h
  type font (line 5) | struct font {
  type font (line 17) | struct font
  type font (line 18) | struct font
  type font (line 19) | struct font
  type font (line 20) | struct font
  type font (line 21) | struct font
  type font (line 22) | struct font
  type font (line 23) | struct font
  type font (line 24) | struct font
  type font (line 26) | struct font
  type token (line 26) | struct token

FILE: src/graph.c
  function graph_init (line 3) | void graph_init(struct graph* graph) {
  function graph_setup (line 16) | void graph_setup(struct graph* graph, uint32_t width) {
  function graph_get_y (line 22) | float graph_get_y(struct graph* graph, uint32_t i) {
  function graph_push_back (line 27) | void graph_push_back(struct graph* graph, float y) {
  function graph_get_length (line 35) | uint32_t graph_get_length(struct graph* graph) {
  function graph_calculate_bounds (line 40) | void graph_calculate_bounds(struct graph* graph, uint32_t x, uint32_t y,...
  function graph_draw (line 47) | void graph_draw(struct graph* graph, CGContextRef context) {
  function graph_serialize (line 111) | void graph_serialize(struct graph* graph, char* indent, FILE* rsp) {
  function graph_destroy (line 127) | void graph_destroy(struct graph* graph) {
  function graph_parse_sub_domain (line 133) | bool graph_parse_sub_domain(struct graph* graph, FILE* rsp, struct token...

FILE: src/graph.h
  type graph (line 5) | struct graph {
  type graph (line 21) | struct graph
  type graph (line 22) | struct graph
  type graph (line 23) | struct graph
  type graph (line 24) | struct graph
  type graph (line 25) | struct graph
  type graph (line 27) | struct graph
  type graph (line 28) | struct graph
  type graph (line 29) | struct graph
  type graph (line 31) | struct graph
  type graph (line 32) | struct graph
  type token (line 32) | struct token

FILE: src/group.c
  type bar_item (line 4) | struct bar_item
  type group (line 4) | struct group
  type bar (line 4) | struct bar
  type bar_item (line 8) | struct bar_item
  type bar_item (line 11) | struct bar_item
  type window (line 13) | struct window
  type bar_item (line 24) | struct bar_item
  type group (line 24) | struct group
  type bar (line 24) | struct bar
  type bar_item (line 28) | struct bar_item
  type bar_item (line 31) | struct bar_item
  type window (line 33) | struct window
  type group (line 44) | struct group
  type group (line 45) | struct group
  type group (line 45) | struct group
  type group (line 46) | struct group
  function group_init (line 50) | void group_init(struct group* group) {
  function group_is_item_member (line 55) | bool group_is_item_member(struct group* group, struct bar_item* item) {
  function group_add_member (line 62) | void group_add_member(struct group* group, struct bar_item* item) {
  function group_get_length (line 77) | uint32_t group_get_length(struct group* group, struct bar* bar) {
  function group_remove_member (line 87) | void group_remove_member(struct group* group, struct bar_item* bar_item) {
  function group_destroy (line 101) | void group_destroy(struct group* group) {
  function group_calculate_bounds (line 109) | void group_calculate_bounds(struct group* group, struct bar* bar, uint32...
  function group_serialize (line 140) | void group_serialize(struct group* group, char* indent, FILE* rsp) {

FILE: src/group.h
  type bar (line 4) | struct bar
  type group (line 6) | struct group {
  type group (line 19) | struct group
  type group (line 20) | struct group
  type group (line 21) | struct group
  type group (line 22) | struct group
  type bar_item (line 22) | struct bar_item
  type group (line 23) | struct group
  type bar_item (line 23) | struct bar_item
  type group (line 24) | struct group
  type bar (line 24) | struct bar
  type group (line 26) | struct group
  type bar (line 26) | struct bar
  type group (line 27) | struct group
  type group (line 29) | struct group

FILE: src/hotload.c
  function hotload_set_state (line 11) | void hotload_set_state(int state) {
  function hotload_get_state (line 15) | int hotload_get_state() {
  function set_config_file_path (line 19) | bool set_config_file_path(char* file) {
  function get_config_file (line 29) | static bool get_config_file(char *restrict filename, char *restrict buff...
  function exec_config_file (line 46) | void exec_config_file() {
  function handler (line 72) | static void handler(ConstFSEventStreamRef stream, void* context, size_t ...
  function begin_receiving_config_change_events (line 84) | int begin_receiving_config_change_events() {

FILE: src/image.c
  function image_init (line 7) | void image_init(struct image* image) {
  function image_set_enabled (line 26) | bool image_set_enabled(struct image* image, bool enabled) {
  function image_set_link (line 32) | bool image_set_link(struct image* image, struct image* link) {
  function image_load (line 39) | bool image_load(struct image* image, char* path, FILE* rsp) {
  function image_data_equals (line 128) | static bool image_data_equals(struct image* image, CFDataRef new_data_re...
  function image_copy (line 143) | void image_copy(struct image* image, CGImageRef source) {
  function image_set_image (line 147) | bool image_set_image(struct image* image, CGImageRef new_image_ref, CGRe...
  function image_set_scale (line 179) | bool image_set_scale(struct image* image, float scale) {
  function image_set_corner_radius (line 188) | bool image_set_corner_radius(struct image* image, uint32_t corner_radius) {
  function image_set_border_width (line 195) | bool image_set_border_width(struct image* image, float border_width) {
  function image_set_border_color (line 202) | bool image_set_border_color(struct image* image, uint32_t color) {
  function image_set_padding_left (line 206) | bool image_set_padding_left(struct image* image, int padding_left) {
  function image_set_padding_right (line 213) | bool image_set_padding_right(struct image* image, int padding_right) {
  function image_set_yoffset (line 220) | bool image_set_yoffset(struct image* image, int yoffset) {
  function CGSize (line 227) | CGSize image_get_size(struct image* image) {
  function image_calculate_bounds (line 237) | void image_calculate_bounds(struct image* image, uint32_t x, uint32_t y) {
  function image_draw (line 254) | void image_draw(struct image* image, CGContextRef context) {
  function image_clear_pointers (line 318) | void image_clear_pointers(struct image* image) {
  function image_destroy (line 324) | void image_destroy(struct image* image) {
  function image_serialize (line 331) | void image_serialize(struct image* image, char* indent, FILE* rsp) {
  function image_parse_sub_domain (line 340) | bool image_parse_sub_domain(struct image* image, FILE* rsp, struct token...

FILE: src/image.h
  type image (line 7) | struct image {
  type image (line 32) | struct image
  type image (line 33) | struct image
  type image (line 34) | struct image
  type image (line 35) | struct image
  type image (line 36) | struct image
  type image (line 37) | struct image
  type image (line 39) | struct image
  type image (line 40) | struct image
  type image (line 41) | struct image
  type image (line 42) | struct image
  type image (line 43) | struct image
  type image (line 45) | struct image
  type image (line 46) | struct image
  type token (line 46) | struct token

FILE: src/mach.c
  function mach_port_t (line 7) | mach_port_t mach_get_bs_port(char* bs_name) {
  function mach_receive_message (line 27) | void mach_receive_message(mach_port_t port, struct mach_buffer* buffer, ...
  type mach_message (line 70) | struct mach_message
  type mach_message (line 87) | struct mach_message
  type mach_message (line 98) | struct mach_message
  type mach_buffer (line 105) | struct mach_buffer
  function mach_message_callback (line 127) | void mach_message_callback(CFMachPortRef port, void* message, CFIndex si...
  function mach_server_begin (line 138) | bool mach_server_begin(struct mach_server* mach_server, mach_handler han...

FILE: src/mach.h
  type mach_message (line 11) | struct mach_message {
  type mach_buffer (line 17) | struct mach_buffer {
  type MACH_HANDLER (line 23) | typedef MACH_HANDLER(mach_handler);
  type mach_server (line 25) | struct mach_server {
  type mach_server (line 34) | struct mach_server

FILE: src/message.c
  type bar_manager (line 12) | struct bar_manager
  type bar_item (line 14) | struct bar_item
  type token (line 14) | struct token
  type bar_item (line 15) | struct bar_item
  type bar_item (line 30) | struct bar_item
  type bar_item (line 35) | struct bar_item
  function handle_domain_subscribe (line 52) | static void handle_domain_subscribe(FILE* rsp, struct token domain, char...
  function handle_domain_trigger (line 66) | static void handle_domain_trigger(FILE* rsp, struct token domain, char* ...
  function handle_domain_push (line 103) | static void handle_domain_push(FILE* rsp, struct token domain, char* mes...
  function handle_domain_rename (line 126) | static void handle_domain_rename(FILE* rsp, struct token domain, char* m...
  function handle_domain_clone (line 142) | static void handle_domain_clone(FILE* rsp, struct token domain, char* me...
  function handle_domain_add (line 172) | static void handle_domain_add(FILE* rsp, struct token domain, char* mess...
  function handle_domain_default (line 322) | static void handle_domain_default(FILE* rsp, struct token domain, char* ...
  function handle_domain_bar (line 326) | static bool handle_domain_bar(FILE *rsp, struct token domain, char *mess...
  type token (line 456) | struct token
  type key_value_pair (line 457) | struct key_value_pair
  function handle_domain_query (line 490) | static void handle_domain_query(FILE* rsp, struct token domain, char* me...
  function handle_domain_remove (line 524) | static void handle_domain_remove(FILE* rsp, struct token domain, char* m...
  function handle_domain_move (line 553) | static void handle_domain_move(FILE* rsp, struct token domain, char* mes...
  function handle_domain_order (line 573) | static void handle_domain_order(FILE* rsp, struct token domain, char* me...
  function handle_message_mach (line 596) | void handle_message_mach(struct mach_buffer* buffer) {
  function MACH_HANDLER (line 778) | MACH_HANDLER(mach_message_handler) {

FILE: src/message.h
  type mach_buffer (line 18) | struct mach_buffer

FILE: src/misc/env_vars.h
  type key_value_pair (line 6) | struct key_value_pair {
  type env_vars (line 11) | struct env_vars {
  function env_vars_init (line 16) | static inline void env_vars_init(struct env_vars* env_vars) {
  function env_vars_unset (line 21) | static inline void env_vars_unset(struct env_vars* env_vars, char* key) {
  function env_vars_set (line 55) | static inline void env_vars_set(struct env_vars* env_vars, char* key, ch...
  type env_vars (line 67) | struct env_vars
  type env_vars (line 75) | struct env_vars
  function env_vars_destroy (line 118) | static inline void env_vars_destroy(struct env_vars* env_vars) {

FILE: src/misc/helpers.h
  type signal_args (line 22) | struct signal_args {
  type token (line 32) | struct token {
  type notification (line 37) | struct notification {
  type notification (line 42) | struct notification
  type notification (line 43) | struct notification
  type notification (line 43) | struct notification
  type notification (line 44) | struct notification
  function notification_destroy (line 48) | static inline void notification_destroy(struct notification* notificatio...
  function function_linear (line 54) | static inline double function_linear(double x) {
  function function_square (line 58) | static inline double function_square(double x) {
  function function_tanh (line 62) | static inline double function_tanh(double x) {
  function function_sin (line 67) | static inline double function_sin(double x) {
  function function_exp (line 71) | static inline double function_exp(double x) {
  function function_circ (line 75) | static inline double function_circ(double x) {
  function respond (line 105) | static inline void respond(FILE* rsp, char* response, ...) {
  function get_key_value_pair (line 126) | static inline struct key_value_pair get_key_value_pair(char *token, char...
  function pack_key_value_pair (line 149) | static inline void pack_key_value_pair(char* cursor, struct key_value_pa...
  function is_root (line 161) | static inline bool is_root(void) {
  function string_equals (line 165) | static inline bool string_equals(const char *a, const char *b) {
  type token (line 203) | struct token
  function token_equals (line 220) | static inline bool token_equals(struct token token, char *match) {
  type token (line 230) | struct token
  function token_to_uint32t (line 239) | static inline uint32_t token_to_uint32t(struct token token) {
  function token_to_int (line 246) | static inline int token_to_int(struct token token) {
  function token_to_float (line 253) | static inline float token_to_float(struct token token) {
  function get_token (line 260) | static inline struct token get_token(char **message) {
  function evaluate_boolean_state (line 278) | static inline bool evaluate_boolean_state(struct token state, bool previ...
  function get_set_bit_position (line 293) | static inline uint32_t get_set_bit_position(uint32_t mask) {
  function clip_rect (line 303) | static inline void clip_rect(CGContextRef context, CGRect region, float ...
  function CGRect (line 316) | static inline CGRect cgrect_mirror_y(CGRect rect, float y) {
  function cgrect_contains_point (line 322) | static inline bool cgrect_contains_point(CGRect* r, CGPoint* p) {
  function CFArrayRef (line 352) | static inline CFArrayRef cfarray_of_cfnumbers(void *values, size_t size,...
  function file_exists (line 413) | static inline bool file_exists(char *filename) {
  function ensure_executable_permission (line 427) | static inline bool ensure_executable_permission(char *filename) {
  function sync_exec (line 441) | static inline bool sync_exec(char *command, struct env_vars *env_vars) {
  function fork_exec (line 454) | static inline bool fork_exec(char *command, struct env_vars* env_vars) {
  function mission_control_index (line 464) | static inline int mission_control_index(uint64_t sid) {
  function dsid_from_sid (line 492) | static inline uint64_t dsid_from_sid(uint32_t sid) {
  function CGImageRef (line 520) | static inline CGImageRef space_capture(uint32_t sid) {
  function display_id_for_space (line 534) | static inline uint32_t display_id_for_space(uint32_t sid) {
  function error (line 549) | static inline void error(const char *format, ...) {
  function get_wid_from_cg_event (line 557) | static inline int get_wid_from_cg_event(CGEventRef event) {

FILE: src/mouse.c
  function pascal (line 22) | static pascal OSStatus mouse_handler(EventHandlerCallRef next, EventRef ...
  function mouse_begin (line 33) | void mouse_begin(void) {

FILE: src/popup.c
  function popup_init (line 7) | void popup_init(struct popup* popup, struct bar_item* host) {
  function CGRect (line 30) | static CGRect popup_get_frame(struct popup* popup) {
  function popup_set_blur_radius (line 36) | static bool popup_set_blur_radius(struct popup* popup, uint32_t radius) {
  function popup_order_windows (line 43) | static void popup_order_windows(struct popup* popup) {
  function popup_calculate_popup_anchor_for_bar_item (line 74) | static void popup_calculate_popup_anchor_for_bar_item(struct popup* popu...
  function popup_calculate_bounds (line 111) | void popup_calculate_bounds(struct popup* popup, struct bar* bar) {
  function popup_create_window (line 233) | static void popup_create_window(struct popup* popup) {
  function popup_close_window (line 255) | static void popup_close_window(struct popup* popup) {
  function popup_contains_item (line 260) | static bool popup_contains_item(struct popup* popup, struct bar_item* ba...
  function popup_add_item (line 267) | void popup_add_item(struct popup* popup, struct bar_item* bar_item) {
  function popup_remove_item (line 283) | void popup_remove_item(struct popup* popup, struct bar_item* bar_item) {
  function popup_set_anchor (line 306) | void popup_set_anchor(struct popup* popup, CGPoint anchor, uint32_t adid) {
  function popup_clear_pointers (line 320) | void popup_clear_pointers(struct popup* popup) {
  function popup_set_drawing (line 327) | bool popup_set_drawing(struct popup* popup, bool drawing) {
  function popup_draw (line 335) | void popup_draw(struct popup* popup) {
  function popup_change_space (line 362) | void popup_change_space(struct popup* popup, uint64_t dsid, uint32_t adi...
  function popup_destroy (line 373) | void popup_destroy(struct popup* popup) {
  function popup_serialize (line 382) | void popup_serialize(struct popup* popup, char* indent, FILE* rsp) {
  function popup_set_yoffset (line 431) | static bool popup_set_yoffset(struct popup* popup, int y_offset) {
  function popup_set_cell_size (line 437) | static bool popup_set_cell_size(struct popup* popup, int size) {
  function popup_set_topmost (line 444) | static bool popup_set_topmost(struct popup* popup, bool topmost) {
  function popup_parse_sub_domain (line 451) | bool popup_parse_sub_domain(struct popup* popup, FILE* rsp, struct token...

FILE: src/popup.h
  type bar_item (line 6) | struct bar_item
  type bar (line 7) | struct bar
  type popup (line 9) | struct popup {
  type popup (line 34) | struct popup
  type bar_item (line 34) | struct bar_item
  type popup (line 35) | struct popup
  type popup (line 36) | struct popup
  type bar_item (line 36) | struct bar_item
  type popup (line 37) | struct popup
  type popup (line 38) | struct popup
  type bar_item (line 38) | struct bar_item
  type popup (line 40) | struct popup
  type popup (line 42) | struct popup
  type popup (line 43) | struct popup
  type bar (line 43) | struct bar
  type popup (line 44) | struct popup
  type popup (line 45) | struct popup
  type popup (line 47) | struct popup
  type popup (line 48) | struct popup
  type popup (line 49) | struct popup
  type token (line 49) | struct token

FILE: src/power.c
  function power_handler (line 6) | void power_handler(void* context) {
  function forced_power_event (line 31) | void forced_power_event() {
  function begin_receiving_power_events (line 36) | void begin_receiving_power_events() {

FILE: src/shadow.c
  function shadow_init (line 4) | void shadow_init(struct shadow* shadow) {
  function shadow_set_enabled (line 16) | static bool shadow_set_enabled(struct shadow* shadow, bool enabled) {
  function shadow_set_angle (line 22) | static bool shadow_set_angle(struct shadow* shadow, uint32_t angle) {
  function shadow_set_distance (line 30) | static bool shadow_set_distance(struct shadow* shadow, uint32_t distance) {
  function shadow_set_color (line 40) | static bool shadow_set_color(struct shadow* shadow, uint32_t color) {
  function CGRect (line 45) | CGRect shadow_get_bounds(struct shadow* shadow, CGRect reference_bounds) {
  function shadow_serialize (line 51) | void shadow_serialize(struct shadow* shadow, char* indent, FILE* rsp) {
  function shadow_parse_sub_domain (line 62) | bool shadow_parse_sub_domain(struct shadow* shadow, FILE* rsp, struct to...

FILE: src/shadow.h
  type shadow (line 5) | struct shadow {
  type shadow (line 15) | struct shadow
  type shadow (line 16) | struct shadow
  type shadow (line 18) | struct shadow
  type shadow (line 19) | struct shadow
  type token (line 19) | struct token

FILE: src/sketchybar.c
  type bar_manager (line 45) | struct bar_manager
  type mach_server (line 46) | struct mach_server
  function client_send_message (line 57) | static int client_send_message(int argc, char **argv) {
  function acquire_lockfile (line 107) | static void acquire_lockfile(void) {
  function init_misc_settings (line 128) | static inline void init_misc_settings(void) {
  function parse_arguments (line 149) | static void parse_arguments(int argc, char **argv) {
  function space_events (line 175) | static void space_events(uint32_t event, void* data, size_t data_length,...
  function system_events (line 180) | static void system_events(uint32_t event, void* data, size_t data_length...
  function main (line 190) | int main(int argc, char **argv) {

FILE: src/slider.c
  function slider_set_width (line 5) | static bool slider_set_width(struct slider* slider, uint32_t width) {
  function slider_set_foreground_color (line 11) | static bool slider_set_foreground_color(struct slider* slider, uint32_t ...
  function slider_set_percentage (line 17) | static bool slider_set_percentage(struct slider* slider, uint32_t percen...
  function slider_get_percentage_for_point (line 23) | uint32_t slider_get_percentage_for_point(struct slider* slider, CGPoint ...
  function slider_cancel_drag (line 32) | void slider_cancel_drag(struct slider* slider) {
  function slider_handle_drag (line 36) | bool slider_handle_drag(struct slider* slider, CGPoint point) {
  function slider_init (line 42) | void slider_init(struct slider* slider) {
  function slider_clear_pointers (line 55) | void slider_clear_pointers(struct slider* slider) {
  function slider_setup (line 61) | void slider_setup(struct slider* slider, uint32_t width) {
  function slider_get_length (line 67) | uint32_t slider_get_length(struct slider* slider) {
  function slider_calculate_bounds (line 71) | void slider_calculate_bounds(struct slider* slider, uint32_t x, uint32_t...
  function slider_draw (line 96) | void slider_draw(struct slider* slider, CGContextRef context) {
  function slider_destroy (line 102) | void slider_destroy(struct slider* slider) {
  function slider_serialize (line 109) | void slider_serialize(struct slider* slider, char* indent, FILE* rsp) {
  function slider_parse_sub_domain (line 129) | bool slider_parse_sub_domain(struct slider* slider, FILE* rsp, struct to...

FILE: src/slider.h
  type slider (line 6) | struct slider {
  type slider (line 16) | struct slider
  type slider (line 17) | struct slider
  type slider (line 18) | struct slider
  type slider (line 19) | struct slider
  type slider (line 20) | struct slider
  type slider (line 21) | struct slider
  type slider (line 23) | struct slider
  type slider (line 24) | struct slider
  type slider (line 26) | struct slider
  type slider (line 27) | struct slider
  type slider (line 28) | struct slider
  type slider (line 29) | struct slider
  type token (line 29) | struct token

FILE: src/text.c
  function text_calculate_truncated_width (line 4) | static void text_calculate_truncated_width(struct text* text, CFDictiona...
  function text_prepare_line (line 42) | static void text_prepare_line(struct text* text) {
  function text_destroy_line (line 94) | static void text_destroy_line(struct text* text) {
  function text_set_max_chars (line 99) | bool text_set_max_chars(struct text* text, uint32_t max_chars) {
  function text_set_string (line 108) | bool text_set_string(struct text* text, char* string, bool forced) {
  function text_copy (line 121) | void text_copy(struct text* text, struct text* source) {
  function text_set_font (line 128) | bool text_set_font(struct text* text, char* font_string, bool forced) {
  function text_init (line 133) | void text_init(struct text* text) {
  function text_set_color (line 156) | static bool text_set_color(struct text* text, uint32_t color) {
  function text_set_highlight_color (line 160) | static bool text_set_highlight_color(struct text* text, uint32_t color) {
  function text_set_padding_left (line 164) | static bool text_set_padding_left(struct text* text, int padding) {
  function text_set_padding_right (line 170) | static bool text_set_padding_right(struct text* text, int padding) {
  function text_set_yoffset (line 176) | static bool text_set_yoffset(struct text* text, int offset) {
  function text_set_scroll_duration (line 182) | static bool text_set_scroll_duration(struct text* text, int duration) {
  function text_set_width (line 188) | static bool text_set_width(struct text* text, int width) {
  function text_clear_pointers (line 201) | void text_clear_pointers(struct text* text) {
  function text_get_length (line 208) | uint32_t text_get_length(struct text* text, bool override) {
  function text_get_height (line 229) | uint32_t text_get_height(struct text* text) {
  function text_destroy (line 233) | void text_destroy(struct text* text) {
  function text_calculate_bounds (line 242) | void text_calculate_bounds(struct text* text, uint32_t x, uint32_t y) {
  function text_set_scroll (line 268) | bool text_set_scroll(struct text* text, float scroll) {
  function text_animate_scroll (line 274) | bool text_animate_scroll(struct text* text) {
  function text_draw (line 313) | void text_draw(struct text* text, CGContextRef context) {
  function text_serialize (line 359) | void text_serialize(struct text* text, char* indent, FILE* rsp) {
  function text_parse_sub_domain (line 417) | bool text_parse_sub_domain(struct text* text, FILE* rsp, struct token pr...

FILE: src/text.h
  type text_line (line 6) | struct text_line {
  type text (line 12) | struct text {
  type text (line 40) | struct text
  type text (line 41) | struct text
  type text (line 42) | struct text
  type text (line 43) | struct text
  type text (line 44) | struct text
  type text (line 45) | struct text
  type text (line 46) | struct text
  type text (line 46) | struct text
  type text (line 48) | struct text
  type text (line 49) | struct text
  type text (line 50) | struct text
  type text (line 51) | struct text
  type text (line 53) | struct text
  type text (line 54) | struct text
  type token (line 54) | struct token

FILE: src/volume.c
  function OSStatus (line 36) | static OSStatus handler(AudioObjectID id, uint32_t address_count, const ...
  function OSStatus (line 93) | OSStatus device_changed(AudioObjectID id, uint32_t address_count, const ...
  function forced_volume_event (line 150) | void forced_volume_event() {
  function begin_receiving_volume_events (line 155) | void begin_receiving_volume_events() {

FILE: src/window.c
  type bar_manager (line 5) | struct bar_manager
  function window_init (line 9) | void window_init(struct window* window) {
  function CFTypeRef (line 21) | static CFTypeRef window_create_region(struct window* window, CGRect fram...
  function window_create (line 27) | void window_create(struct window* window, CGRect frame) {
  function window_clear (line 94) | void window_clear(struct window* window) {
  function window_flush (line 104) | void window_flush(struct window* window) {
  function windows_freeze (line 108) | void windows_freeze() {
  function windows_unfreeze (line 115) | void windows_unfreeze() {
  function window_set_frame (line 124) | void window_set_frame(struct window* window, CGRect frame) {
  function window_move (line 138) | void window_move(struct window* window, CGPoint point) {
  function window_apply_frame (line 160) | bool window_apply_frame(struct window* window, bool forced) {
  function window_send_to_space (line 207) | void window_send_to_space(struct window* window, uint64_t dsid) {
  function window_close (line 220) | void window_close(struct window* window) {
  function window_set_level (line 231) | void window_set_level(struct window* window, uint32_t level) {
  function window_order (line 243) | void window_order(struct window* window, struct window* parent, int mode) {
  function window_assign_mouse_tracking_area (line 260) | void window_assign_mouse_tracking_area(struct window* window, CGRect rec...
  function window_set_blur_radius (line 265) | void window_set_blur_radius(struct window* window, uint32_t blur_radius) {
  function context_set_font_smoothing (line 269) | void context_set_font_smoothing(CGContextRef context, bool smoothing) {
  function window_disable_shadow (line 273) | void window_disable_shadow(struct window* window) {
  function CGImageRef (line 293) | CGImageRef window_capture(struct window* window, bool* disabled) {

FILE: src/window.h
  type window (line 13) | struct window {
  type window (line 27) | struct window
  type window (line 28) | struct window
  type window (line 29) | struct window
  type window (line 30) | struct window
  type window (line 31) | struct window
  type window (line 33) | struct window
  type window (line 34) | struct window
  type window (line 35) | struct window
  type window (line 36) | struct window
  type window (line 38) | struct window
  type window (line 39) | struct window
  type window (line 40) | struct window
  type window (line 41) | struct window
  type window (line 41) | struct window
  type window (line 42) | struct window
  type window (line 44) | struct window
Condensed preview — 75 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (493K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 18,
    "preview": "ko_fi: felixkratz\n"
  },
  {
    "path": ".gitignore",
    "chars": 145,
    "preview": "test\nbin\ntodo.md\nnotifications.md\n.ccls-cache\n.DS_Store\n.ccls\n.cache\n.cmake\nCMakeCache.txt\nCMakeFiles/\ncmake_install.cma"
  },
  {
    "path": "LICENSE.md",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README.md",
    "chars": 5446,
    "preview": "<p align=\"center\">\n  <img src=\"images/Sbar.svg\" />\n</p>\n\n<p align=\"center\">\n<a href=\"https://felixkratz.github.io/Sketch"
  },
  {
    "path": "makefile",
    "chars": 1955,
    "preview": "CFLAGS   = -std=c99 -Wall -O3 -ffast-math -fvisibility=hidden -fno-common\n\nLIBS     = -framework Carbon \\\n\t\t\t\t\t -framewo"
  },
  {
    "path": "plugins/battery.sh",
    "chars": 545,
    "preview": "#!/bin/sh\n\nPERCENTAGE=\"$(pmset -g batt | grep -Eo \"\\d+%\" | cut -d% -f1)\"\nCHARGING=\"$(pmset -g batt | grep 'AC Power')\"\n\n"
  },
  {
    "path": "plugins/clock.sh",
    "chars": 248,
    "preview": "#!/bin/sh\n\n# The $NAME variable is passed from sketchybar and holds the name of\n# the item invoking this script:\n# https"
  },
  {
    "path": "plugins/front_app.sh",
    "chars": 375,
    "preview": "#!/bin/sh\n\n# Some events send additional information specific to the event in the $INFO\n# variable. E.g. the front_app_s"
  },
  {
    "path": "plugins/space.sh",
    "chars": 334,
    "preview": "#!/bin/sh\n\n# The $SELECTED variable is available for space components and indicates if\n# the space invoking this script "
  },
  {
    "path": "plugins/volume.sh",
    "chars": 399,
    "preview": "#!/bin/sh\n\n# The volume_change event supplies a $INFO variable in which the current volume\n# percentage is passed to the"
  },
  {
    "path": "sketchybarrc",
    "chars": 3533,
    "preview": "# This is a demo config to showcase some of the most important commands.\n# It is meant to be changed and configured, as "
  },
  {
    "path": "src/alias.c",
    "chars": 10363,
    "preview": "#include \"alias.h\"\n#include \"misc/helpers.h\"\n#include <CoreFoundation/CFBase.h>\n#include <CoreFoundation/CoreFoundation."
  },
  {
    "path": "src/alias.h",
    "chars": 918,
    "preview": "#pragma once\n#include <stdbool.h>\n#include \"misc/helpers.h\"\n#include \"window.h\"\n#include \"image.h\"\n\n#define MENUBAR_LAYE"
  },
  {
    "path": "src/animation.c",
    "chars": 10052,
    "preview": "#include \"animation.h\"\n#include \"event.h\"\n\nstatic CVReturn animation_frame_callback(CVDisplayLinkRef display_link, const"
  },
  {
    "path": "src/animation.h",
    "chars": 4330,
    "preview": "#pragma once\n#include <CoreVideo/CoreVideo.h>\n#include \"misc/helpers.h\"\n\nextern struct bar_manager g_bar_manager;\n\n#defi"
  },
  {
    "path": "src/app_windows.c",
    "chars": 10637,
    "preview": "#include \"app_windows.h\"\n#include \"workspace.h\"\n#include \"misc/helpers.h\"\n#include \"event.h\"\n\nextern pid_t g_pid;\nstruct"
  },
  {
    "path": "src/app_windows.h",
    "chars": 260,
    "preview": "#pragma once\n#include \"event.h\"\n\nstruct app_window {\n  uint32_t wid;\n  uint64_t sid;\n  pid_t pid;\n};\n\nstruct app_windows"
  },
  {
    "path": "src/background.c",
    "chars": 14836,
    "preview": "#include \"background.h\"\n#include \"image.h\"\n#include \"misc/helpers.h\"\n#include \"shadow.h\"\n#include \"animation.h\"\n#include"
  },
  {
    "path": "src/background.h",
    "chars": 1699,
    "preview": "#pragma once\n#include \"image.h\"\n\nstruct background {\n  bool enabled;\n  float clip;\n  bool overrides_height;\n\n  int paddi"
  },
  {
    "path": "src/bar.c",
    "chars": 21428,
    "preview": "#include \"bar.h\"\n#include \"bar_manager.h\"\n#include \"event.h\"\n#include \"display.h\"\n#include \"misc/helpers.h\"\n#include \"wi"
  },
  {
    "path": "src/bar.h",
    "chars": 809,
    "preview": "#pragma once\n#include \"bar_item.h\"\n#include \"misc/helpers.h\"\n#include \"window.h\"\n\nstruct bar {\n  bool shown;\n  bool hidd"
  },
  {
    "path": "src/bar_item.c",
    "chars": 45929,
    "preview": "#include \"bar_item.h\"\n#include \"bar_manager.h\"\n#include \"event.h\"\n#include \"volume.h\"\n#include \"power.h\"\n#include \"media"
  },
  {
    "path": "src/bar_item.h",
    "chars": 4539,
    "preview": "#pragma once\n\n#include \"alias.h\"\n#include \"custom_events.h\"\n#include \"graph.h\"\n#include \"group.h\"\n#include \"misc/env_var"
  },
  {
    "path": "src/bar_manager.c",
    "chars": 40224,
    "preview": "#include \"bar_manager.h\"\n#include \"bar.h\"\n#include \"bar_item.h\"\n#include \"event.h\"\n#include \"misc/env_vars.h\"\n#include \""
  },
  {
    "path": "src/bar_manager.h",
    "chars": 6871,
    "preview": "#pragma once\n#include \"bar.h\"\n#include \"bar_item.h\"\n#include \"animation.h\"\n\n#define CLOCK_CALLBACK(name) void name(CFRun"
  },
  {
    "path": "src/color.c",
    "chars": 2572,
    "preview": "#include \"color.h\"\n#include \"bar_manager.h\"\n#include \"animation.h\"\n\nstatic bool color_update_hex(struct color* color) {\n"
  },
  {
    "path": "src/color.h",
    "chars": 620,
    "preview": "#pragma once\n#include <stdbool.h>\n#include <stdint.h>\n#include \"misc/helpers.h\"\n\nstruct color {\n  float r;\n  float g;\n  "
  },
  {
    "path": "src/custom_events.c",
    "chars": 4449,
    "preview": "#include \"custom_events.h\"\n\nstatic struct custom_event* custom_event_create(void) {\n  return malloc(sizeof(struct custom"
  },
  {
    "path": "src/custom_events.h",
    "chars": 1743,
    "preview": "#pragma once\n#include \"misc/helpers.h\"\n\n#define UPDATE_FRONT_APP_SWITCHED   1ULL\n#define UPDATE_SPACE_CHANGE         (1U"
  },
  {
    "path": "src/display.c",
    "chars": 9730,
    "preview": "#include \"display.h\"\n#include \"misc/helpers.h\"\n\nextern int workspace_display_notch_height(uint32_t did);\nextern int g_co"
  },
  {
    "path": "src/display.h",
    "chars": 960,
    "preview": "#pragma once\n#include \"event.h\"\n#include \"misc/helpers.h\"\n\n#define DISPLAY_EVENT_HANDLER(name) void name(uint32_t did, C"
  },
  {
    "path": "src/event.c",
    "chars": 14263,
    "preview": "#include \"event.h\"\n#include \"bar_manager.h\"\n#include \"custom_events.h\"\n#include \"hotload.h\"\n\nextern struct bar_manager g"
  },
  {
    "path": "src/event.h",
    "chars": 748,
    "preview": "#pragma once\n#include \"bar_manager.h\"\n#include \"message.h\"\n\nenum event_type {\n  EVENT_TYPE_UNKNOWN,\n  APPLICATION_FRONT_"
  },
  {
    "path": "src/font.c",
    "chars": 8722,
    "preview": "#include \"font.h\"\n#include \"animation.h\"\n#include \"bar_manager.h\"\n\nstruct feature_mapping {\n  char opentype_tag[5];\n  in"
  },
  {
    "path": "src/font.h",
    "chars": 743,
    "preview": "#pragma once\n#include <CoreText/CoreText.h>\n#include \"misc/helpers.h\"\n\nstruct font {\n  CTFontRef ct_font;\n\n  bool font_c"
  },
  {
    "path": "src/graph.c",
    "chars": 5605,
    "preview": "#include \"graph.h\"\n\nvoid graph_init(struct graph* graph) {\n  graph->width = 0;\n  graph->cursor = 0;\n\n  graph->line_width"
  },
  {
    "path": "src/graph.h",
    "chars": 896,
    "preview": "#pragma once\n#include \"misc/helpers.h\"\n#include \"color.h\"\n\nstruct graph {\n  bool rtl;\n  bool fill;\n  bool enabled;\n  boo"
  },
  {
    "path": "src/group.c",
    "chars": 4855,
    "preview": "#include \"group.h\"\n#include \"bar.h\"\n\nstatic struct bar_item* group_get_first_member(struct group* group, struct bar* bar"
  },
  {
    "path": "src/group.h",
    "chars": 782,
    "preview": "#pragma once\n#include \"bar_item.h\"\n\nstruct bar;\n\nstruct group {\n  CGRect bounds;\n\n  struct window* first_window;\n  struc"
  },
  {
    "path": "src/hotload.c",
    "chars": 3455,
    "preview": "#include \"bar_manager.h\"\n#include \"event.h\"\n#include <ApplicationServices/ApplicationServices.h>\n#include <libgen.h>\n\nex"
  },
  {
    "path": "src/hotload.h",
    "chars": 264,
    "preview": "#include <stdbool.h>\n\n#define HOTLOAD_STATE_ENABLED true\n#define HOTLOAD_STATE_DISABLED false\n\nvoid exec_config_file();\n"
  },
  {
    "path": "src/image.c",
    "chars": 14387,
    "preview": "#include \"image.h\"\n#include \"misc/helpers.h\"\n#include \"shadow.h\"\n#include \"workspace.h\"\n#include \"media.h\"\n\nvoid image_i"
  },
  {
    "path": "src/image.h",
    "chars": 1249,
    "preview": "#pragma once\n#include \"shadow.h\"\n#include \"misc/defines.h\"\n\nextern CGImageRef workspace_icon_for_app(char* app);\n\nstruct"
  },
  {
    "path": "src/mach.c",
    "chars": 6715,
    "preview": "#include \"mach.h\"\n#include <mach/mach_port.h>\n#include <mach/message.h>\n#include <stdint.h>\n#include <CoreFoundation/Cor"
  },
  {
    "path": "src/mach.h",
    "chars": 866,
    "preview": "#pragma once\n#include <bootstrap.h>\n#include <mach/mach.h>\n#include <mach/message.h>\n#include <pthread.h>\n#include <stdl"
  },
  {
    "path": "src/media.h",
    "chars": 103,
    "preview": "void initialize_media_events();\nvoid begin_receiving_media_events();\nvoid forced_media_change_event();\n"
  },
  {
    "path": "src/media.m",
    "chars": 7104,
    "preview": "#include \"event.h\"\n#include <Foundation/Foundation.h>\n\n// The media remote private framework was locked for use on macOS"
  },
  {
    "path": "src/message.c",
    "chars": 30626,
    "preview": "#include \"message.h\"\n#include \"app_windows.h\"\n#include \"bar_manager.h\"\n#include \"misc/defines.h\"\n#include \"hotload.h\"\n#i"
  },
  {
    "path": "src/message.h",
    "chars": 364,
    "preview": "#pragma once\n\n#include <regex.h>\n#include \"alias.h\"\n#include \"background.h\"\n#include \"bar_item.h\"\n#include \"bar_manager."
  },
  {
    "path": "src/misc/defines.h",
    "chars": 9204,
    "preview": "#pragma once\n\n#define DOMAIN_ADD                             \"--add\"\n#define COMMAND_ADD_ITEM                       \"ite"
  },
  {
    "path": "src/misc/env_vars.h",
    "chars": 3473,
    "preview": "#pragma once\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n\nstruct key_value_pair {\n  char* key;\n  char* v"
  },
  {
    "path": "src/misc/extern.h",
    "chars": 7397,
    "preview": "#include <CoreGraphics/CoreGraphics.h>\n\nextern CGError DisplayServicesRegisterForBrightnessChangeNotifications(uint32_t "
  },
  {
    "path": "src/misc/help.h",
    "chars": 3756,
    "preview": "static const char help_str[] = {\n  \"Usage: %s [options]\\n\\n\"\n  \"Startup: \\n\"\n  \"  -c, --config CONFIGFILE\\tRead CONFIGFI"
  },
  {
    "path": "src/misc/helpers.h",
    "chars": 14894,
    "preview": "#pragma once\n#include <CoreFoundation/CoreFoundation.h>\n#include <CoreGraphics/CoreGraphics.h>\n#include <ApplicationServ"
  },
  {
    "path": "src/mouse.c",
    "chars": 1235,
    "preview": "#include <Carbon/Carbon.h>\n#include \"mouse.h\"\n\nstatic const EventTypeSpec mouse_events [] = {\n    { kEventClassMouse, kE"
  },
  {
    "path": "src/mouse.h",
    "chars": 57,
    "preview": "#pragma once\n#include \"event.h\"\n\nvoid mouse_begin(void);\n"
  },
  {
    "path": "src/popup.c",
    "chars": 17250,
    "preview": "#include \"popup.h\"\n#include \"bar_item.h\"\n#include \"bar_manager.h\"\n#include \"bar.h\"\n#include \"animation.h\"\n\nvoid popup_in"
  },
  {
    "path": "src/popup.h",
    "chars": 1319,
    "preview": "#pragma once\n#include \"background.h\"\n#include \"misc/helpers.h\"\n#include \"window.h\"\n\nstruct bar_item;\nstruct bar;\n\nstruct"
  },
  {
    "path": "src/power.c",
    "chars": 1107,
    "preview": "#include \"power.h\"\n#include \"event.h\"\n\nuint32_t g_power_source = 0;\n\nvoid power_handler(void* context) {\n  CFTypeRef inf"
  },
  {
    "path": "src/power.h",
    "chars": 343,
    "preview": "#include <CoreFoundation/CoreFoundation.h>\n#include <IOKit/ps/IOPowerSources.h>\n\n#define POWER_AC_KEY      CFSTR(kIOPMAC"
  },
  {
    "path": "src/shadow.c",
    "chars": 4047,
    "preview": "#include \"shadow.h\"\n#include \"bar_manager.h\"\n\nvoid shadow_init(struct shadow* shadow) {\n  shadow->enabled = false;\n  sha"
  },
  {
    "path": "src/shadow.h",
    "chars": 468,
    "preview": "#pragma once\n#include \"misc/helpers.h\"\n#include \"color.h\"\n\nstruct shadow {\n  bool enabled;\n\n  uint32_t angle;\n  uint32_t"
  },
  {
    "path": "src/sketchybar.c",
    "chars": 6588,
    "preview": "#include \"bar_manager.h\"\n#include \"event.h\"\n#include \"workspace.h\"\n#include \"mach.h\"\n#include \"mouse.h\"\n#include \"messag"
  },
  {
    "path": "src/slider.c",
    "chars": 6826,
    "preview": "#include \"slider.h\"\n#include \"bar_manager.h\"\n#include \"animation.h\"\n\nstatic bool slider_set_width(struct slider* slider,"
  },
  {
    "path": "src/slider.h",
    "chars": 983,
    "preview": "#pragma once\n\n#include \"background.h\"\n#include \"text.h\"\n\nstruct slider {\n  bool is_dragged;\n  uint32_t percentage;\n  uin"
  },
  {
    "path": "src/text.c",
    "chars": 20801,
    "preview": "#include \"text.h\"\n#include \"bar_manager.h\"\n\nstatic void text_calculate_truncated_width(struct text* text, CFDictionaryRe"
  },
  {
    "path": "src/text.h",
    "chars": 1365,
    "preview": "#pragma once\n#include <CoreText/CoreText.h>\n#include \"background.h\"\n#include \"font.h\"\n\nstruct text_line {\n  CTLineRef li"
  },
  {
    "path": "src/volume.c",
    "chars": 7540,
    "preview": "#include \"volume.h\"\n#include \"event.h\"\n\nextern bool g_volume_events;\n\n#if __MAC_OS_X_VERSION_MAX_ALLOWED < 120000\n#defin"
  },
  {
    "path": "src/volume.h",
    "chars": 137,
    "preview": "#include \"CoreAudio/CoreAudio.h\"\n#include <CoreAudio/AudioHardware.h>\n\nvoid forced_volume_event();\nvoid begin_receiving_"
  },
  {
    "path": "src/wifi.h",
    "chars": 68,
    "preview": "void forced_network_event();\nvoid begin_receiving_network_events();\n"
  },
  {
    "path": "src/wifi.m",
    "chars": 1451,
    "preview": "#include <CoreWLAN/CoreWLAN.h>\n#include <SystemConfiguration/SystemConfiguration.h>\n#include \"wifi.h\"\n#include \"event.h\""
  },
  {
    "path": "src/window.c",
    "chars": 10597,
    "preview": "#include \"window.h\"\n#include \"bar_manager.h\"\n#include \"misc/helpers.h\"\n\nextern struct bar_manager g_bar_manager;\nextern "
  },
  {
    "path": "src/window.h",
    "chars": 1429,
    "preview": "#pragma once\n#include \"misc/helpers.h\"\n\n#define kCGSExposeFadeTagBit         (1ULL <<  1)\n#define kCGSPreventsActivation"
  },
  {
    "path": "src/workspace.h",
    "chars": 437,
    "preview": "#pragma once\n#include \"event.h\"\n\nvoid workspace_create_custom_observer (void **context, char* notification);\nvoid worksp"
  },
  {
    "path": "src/workspace.m",
    "chars": 7712,
    "preview": "#include \"workspace.h\"\n#include \"misc/helpers.h\"\n\n#include <AppKit/AppKit.h>\n@interface workspace_context : NSObject {\n}"
  }
]

About this extraction

This page contains the full source code of the FelixKratz/SketchyBar GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 75 files (462.3 KB), approximately 111.5k tokens, and a symbol index with 936 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!