Compare commits
No commits in common. "0bc2decb7c29cd684c9e1237f305b0d29d8aa469" and "fcc080871a9754ce028d7bbbc4a3a0bd16b089a9" have entirely different histories.
0bc2decb7c
...
fcc080871a
16 changed files with 114 additions and 1154 deletions
|
@ -1,33 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
charset = utf-8
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
[*.c]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
tab_width = 2
|
|
||||||
|
|
||||||
[*.h]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
tab_width = 2
|
|
||||||
|
|
||||||
[Makefile]
|
|
||||||
indent_style = tab
|
|
||||||
tab_width = 4
|
|
||||||
trim_trailing_whitespace = false
|
|
||||||
|
|
||||||
[*.mk]
|
|
||||||
indent_style = tab
|
|
||||||
tab_width = 4
|
|
||||||
trim_trailing_whitespace = false
|
|
||||||
|
|
||||||
[*.sh]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
tab_width = 2
|
|
||||||
|
|
1
.envrc
1
.envrc
|
@ -1 +0,0 @@
|
||||||
use flake
|
|
8
.gitattributes
vendored
8
.gitattributes
vendored
|
@ -1,8 +0,0 @@
|
||||||
# Vendored headers are vendored code, to the surprise of absolutely noone.
|
|
||||||
# See:
|
|
||||||
# <https://github.com/github-linguist/linguist/blob/main/docs/overrides.md#vendored-code>
|
|
||||||
/include/chroma.h linguist-vendored
|
|
||||||
|
|
||||||
# Don't think linguist can detect XML, but let's tell it that the protocols are
|
|
||||||
# vendored *anyway*.
|
|
||||||
/protocols/*.xml linguist-vendored
|
|
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -1,8 +0,0 @@
|
||||||
/bin
|
|
||||||
/obj
|
|
||||||
|
|
||||||
# Generated by wayland-scanner
|
|
||||||
include/xdg-shell.h
|
|
||||||
include/wlr-layer-shell-unstable-v1.h
|
|
||||||
src/xdg-shell.c
|
|
||||||
src/wlr-layer-shell-unstable-v1.c
|
|
328
LICENSE
328
LICENSE
|
@ -1,328 +0,0 @@
|
||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. “Contributor”
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. “Contributor Version”
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor’s Contribution.
|
|
||||||
|
|
||||||
1.3. “Contribution”
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. “Covered Software”
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form,
|
|
||||||
and Modifications of such Source Code Form, in each case
|
|
||||||
including portions thereof.
|
|
||||||
|
|
||||||
1.5. “Incompatible With Secondary Licenses”
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described
|
|
||||||
in Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the terms
|
|
||||||
of a Secondary License.
|
|
||||||
|
|
||||||
1.6. “Executable Form”
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. “Larger Work”
|
|
||||||
means a work that combines Covered Software with other material,
|
|
||||||
in a separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. “License”
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. “Licensable”
|
|
||||||
means having the right to grant, to the maximum extent possible,
|
|
||||||
whether at the time of the initial grant or subsequently,
|
|
||||||
any and all of the rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. “Modifications”
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. “Patent Claims” of a Contributor
|
|
||||||
means any patent claim(s), including without limitation, method, process,
|
|
||||||
and apparatus claims, in any patent Licensable by such Contributor that
|
|
||||||
would be infringed, but for the grant of the License, by the making,
|
|
||||||
using, selling, offering for sale, having made, import, or transfer of
|
|
||||||
either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. “Secondary License”
|
|
||||||
means either the GNU General Public License, Version 2.0, the
|
|
||||||
GNU Lesser General Public License, Version 2.1, the GNU Affero General
|
|
||||||
Public License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. “Source Code Form”
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. “You” (or “Your”)
|
|
||||||
means an individual or a legal entity exercising rights under this License.
|
|
||||||
For legal entities, “You” includes any entity that controls,
|
|
||||||
is controlled by, or is under common control with You. For purposes of
|
|
||||||
this definition, “control” means (a) the power, direct or indirect,
|
|
||||||
to cause the direction or management of such entity, whether by contract
|
|
||||||
or otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications,
|
|
||||||
or as part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell,
|
|
||||||
offer for sale, have made, import, and otherwise transfer either
|
|
||||||
its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor
|
|
||||||
first distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
The licenses granted in this Section 2 are the only rights granted
|
|
||||||
under this License. No additional rights or licenses will be implied
|
|
||||||
from the distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted
|
|
||||||
by a Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from
|
|
||||||
Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party’s
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its
|
|
||||||
Contributor Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the
|
|
||||||
absence of its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License
|
|
||||||
(if permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights
|
|
||||||
to grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing,
|
|
||||||
or other equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the
|
|
||||||
licenses granted in Section 2.1.
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
All distribution of Covered Software in Source Code Form, including
|
|
||||||
any Modifications that You create or to which You contribute, must be
|
|
||||||
under the terms of this License. You must inform recipients that the
|
|
||||||
Source Code Form of the Covered Software is governed by the terms
|
|
||||||
of this License, and how they can obtain a copy of this License.
|
|
||||||
You may not attempt to alter or restrict the recipients’ rights
|
|
||||||
in the Source Code Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code
|
|
||||||
Form, as described in Section 3.1, and You must inform recipients of
|
|
||||||
the Executable Form how they can obtain a copy of such Source Code
|
|
||||||
Form by reasonable means in a timely manner, at a charge no more than
|
|
||||||
the cost of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter
|
|
||||||
the recipients’ rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of
|
|
||||||
Covered Software with a work governed by one or more Secondary Licenses,
|
|
||||||
and the Covered Software is not Incompatible With Secondary Licenses,
|
|
||||||
this License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the
|
|
||||||
Covered Software under the terms of either this License or such
|
|
||||||
Secondary License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty,
|
|
||||||
or limitations of liability) contained within the Source Code Form of
|
|
||||||
the Covered Software, except that You may alter any license notices to
|
|
||||||
the extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of
|
|
||||||
Covered Software. However, You may do so only on Your own behalf,
|
|
||||||
and not on behalf of any Contributor. You must make it absolutely clear
|
|
||||||
that any such warranty, support, indemnity, or liability obligation is
|
|
||||||
offered by You alone, and You hereby agree to indemnify every Contributor
|
|
||||||
for any liability incurred by such Contributor as a result of warranty,
|
|
||||||
support, indemnity or liability terms You offer. You may include
|
|
||||||
additional disclaimers of warranty and limitations of liability
|
|
||||||
specific to any jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute,
|
|
||||||
judicial order, or regulation then You must: (a) comply with the terms of
|
|
||||||
this License to the maximum extent possible; and (b) describe the limitations
|
|
||||||
and the code they affect. Such description must be placed in a text file
|
|
||||||
included with all distributions of the Covered Software under this License.
|
|
||||||
Except to the extent prohibited by statute or regulation, such description
|
|
||||||
must be sufficiently detailed for a recipient of ordinary skill
|
|
||||||
to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically
|
|
||||||
if You fail to comply with any of its terms. However, if You become
|
|
||||||
compliant, then the rights granted under this License from a particular
|
|
||||||
Contributor are reinstated (a) provisionally, unless and until such
|
|
||||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
|
||||||
ongoing basis, if such Contributor fails to notify You of the
|
|
||||||
non-compliance by some reasonable means prior to 60 days after You have
|
|
||||||
come back into compliance. Moreover, Your grants from a particular
|
|
||||||
Contributor are reinstated on an ongoing basis if such Contributor
|
|
||||||
notifies You of the non-compliance by some reasonable means,
|
|
||||||
this is the first time You have received notice of non-compliance with
|
|
||||||
this License from such Contributor, and You become compliant prior to
|
|
||||||
30 days after Your receipt of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted
|
|
||||||
to You by any and all Contributors for the Covered Software under
|
|
||||||
Section 2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
|
||||||
end user license agreements (excluding distributors and resellers) which
|
|
||||||
have been validly granted by You or Your distributors under this License
|
|
||||||
prior to termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an “as is” basis, without
|
|
||||||
warranty of any kind, either expressed, implied, or statutory, including,
|
|
||||||
without limitation, warranties that the Covered Software is free of defects,
|
|
||||||
merchantable, fit for a particular purpose or non-infringing. The entire risk
|
|
||||||
as to the quality and performance of the Covered Software is with You.
|
|
||||||
Should any Covered Software prove defective in any respect, You
|
|
||||||
(not any Contributor) assume the cost of any necessary servicing, repair,
|
|
||||||
or correction. This disclaimer of warranty constitutes an essential part of
|
|
||||||
this License. No use of any Covered Software is authorized under this
|
|
||||||
License except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort
|
|
||||||
(including negligence), contract, or otherwise, shall any Contributor, or
|
|
||||||
anyone who distributes Covered Software as permitted above, be liable to
|
|
||||||
You for any direct, indirect, special, incidental, or consequential damages
|
|
||||||
of any character including, without limitation, damages for lost profits,
|
|
||||||
loss of goodwill, work stoppage, computer failure or malfunction, or any and
|
|
||||||
all other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from
|
|
||||||
such party’s negligence to the extent applicable law prohibits such
|
|
||||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
|
||||||
incidental or consequential damages, so this exclusion and limitation may
|
|
||||||
not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts of
|
|
||||||
a jurisdiction where the defendant maintains its principal place of business
|
|
||||||
and such litigation shall be governed by laws of that jurisdiction, without
|
|
||||||
reference to its conflict-of-law provisions. Nothing in this Section shall
|
|
||||||
prevent a party’s ability to bring cross-claims or counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject matter
|
|
||||||
hereof. If any provision of this License is held to be unenforceable,
|
|
||||||
such provision shall be reformed only to the extent necessary to make it
|
|
||||||
enforceable. Any law or regulation which provides that the language of a
|
|
||||||
contract shall be construed against the drafter shall not be used to construe
|
|
||||||
this License against a Contributor.
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in
|
|
||||||
Section 10.3, no one other than the license steward has the right to
|
|
||||||
modify or publish new versions of this License. Each version will be
|
|
||||||
given a distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published
|
|
||||||
by the license steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a modified
|
|
||||||
version of this License if you rename the license and remove any
|
|
||||||
references to the name of the license steward (except to note that such
|
|
||||||
modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is
|
|
||||||
Incompatible With Secondary Licenses
|
|
||||||
If You choose to distribute Source Code Form that is
|
|
||||||
Incompatible With Secondary Licenses under the terms of this version of
|
|
||||||
the License, the notice described in Exhibit B of this
|
|
||||||
License must be attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the terms of the
|
|
||||||
Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed
|
|
||||||
with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file,
|
|
||||||
then You may include the notice in a location (such as a LICENSE file in a
|
|
||||||
relevant directory) where a recipient would be likely to
|
|
||||||
look for such a notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
|
||||||
|
|
||||||
This Source Code Form is “Incompatible With Secondary Licenses”,
|
|
||||||
as defined by the Mozilla Public License, v. 2.0.
|
|
173
Makefile
173
Makefile
|
@ -1,173 +0,0 @@
|
||||||
PROJECT_NAME = chroma
|
|
||||||
VERSION = 1.0.0
|
|
||||||
|
|
||||||
# Directories
|
|
||||||
SRCDIR = src
|
|
||||||
INCDIR = include
|
|
||||||
OBJDIR = obj
|
|
||||||
BINDIR = bin
|
|
||||||
SYSTEMD_DIR = systemd
|
|
||||||
PROTOCOLDIR = protocols
|
|
||||||
|
|
||||||
# Install directories
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
BINDIR_INSTALL = $(PREFIX)/bin
|
|
||||||
SYSTEMD_INSTALL = $(HOME)/.config/systemd/user
|
|
||||||
|
|
||||||
# Compiler and flags
|
|
||||||
CC = gcc
|
|
||||||
CFLAGS = -std=c11 -Wall -Wextra -Werror -pedantic -O2 -g
|
|
||||||
CFLAGS += -D_GNU_SOURCE -DCHROMA_VERSION=\"$(VERSION)\"
|
|
||||||
CPPFLAGS = -I$(INCDIR)
|
|
||||||
|
|
||||||
# Debug build flags
|
|
||||||
DEBUG_CFLAGS = -std=c11 -Wall -Wextra -Werror -pedantic -Og -g3 -DDEBUG
|
|
||||||
DEBUG_CFLAGS += -D_GNU_SOURCE -DCHROMA_VERSION=\"$(VERSION)-debug\"
|
|
||||||
DEBUG_CFLAGS += -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
|
|
||||||
|
|
||||||
# Libraries using pkg-config
|
|
||||||
PKG_DEPS = wayland-client wayland-egl egl glesv2 wayland-protocols
|
|
||||||
CFLAGS += $(shell pkg-config --cflags $(PKG_DEPS))
|
|
||||||
LDFLAGS += $(shell pkg-config --libs $(PKG_DEPS))
|
|
||||||
|
|
||||||
# Protocol files
|
|
||||||
PROTOCOL_XML = $(PROTOCOLDIR)/xdg-shell.xml $(PROTOCOLDIR)/wlr-layer-shell-unstable-v1.xml
|
|
||||||
PROTOCOL_HEADERS = $(PROTOCOL_XML:$(PROTOCOLDIR)/%.xml=$(INCDIR)/%.h)
|
|
||||||
PROTOCOL_SOURCES = $(PROTOCOL_XML:$(PROTOCOLDIR)/%.xml=$(SRCDIR)/%.c)
|
|
||||||
PROTOCOL_OBJECTS = $(PROTOCOL_SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
|
|
||||||
|
|
||||||
# Additional libraries
|
|
||||||
LDFLAGS += -lm -ldl
|
|
||||||
|
|
||||||
# Source files (excluding generated protocol files)
|
|
||||||
SOURCES = $(filter-out $(PROTOCOL_SOURCES), $(wildcard $(SRCDIR)/*.c))
|
|
||||||
OBJECTS = $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o) $(PROTOCOL_OBJECTS)
|
|
||||||
DEPENDS = $(OBJECTS:.o=.d)
|
|
||||||
|
|
||||||
# Default target
|
|
||||||
TARGET = $(BINDIR)/$(PROJECT_NAME)
|
|
||||||
all: $(TARGET)
|
|
||||||
|
|
||||||
# Create directories
|
|
||||||
$(OBJDIR):
|
|
||||||
@mkdir -p $(OBJDIR)
|
|
||||||
|
|
||||||
$(BINDIR):
|
|
||||||
@mkdir -p $(BINDIR)
|
|
||||||
|
|
||||||
# Protocol generation
|
|
||||||
$(INCDIR)/%.h: $(PROTOCOLDIR)/%.xml | $(INCDIR)
|
|
||||||
@echo " PROTO $<"
|
|
||||||
@wayland-scanner client-header $< $@
|
|
||||||
|
|
||||||
$(SRCDIR)/%.c: $(PROTOCOLDIR)/%.xml
|
|
||||||
@echo " PROTO $<"
|
|
||||||
@wayland-scanner private-code $< $@
|
|
||||||
|
|
||||||
# Make sure include directory exists
|
|
||||||
$(INCDIR):
|
|
||||||
@mkdir -p $(INCDIR)
|
|
||||||
|
|
||||||
# Build main executable
|
|
||||||
$(TARGET): $(PROTOCOL_HEADERS) $(OBJECTS) | $(BINDIR)
|
|
||||||
@echo " LINK $@"
|
|
||||||
@$(CC) $(OBJECTS) -o $@ $(LDFLAGS)
|
|
||||||
|
|
||||||
# Compile source files
|
|
||||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(PROTOCOL_HEADERS) | $(OBJDIR)
|
|
||||||
@echo " CC $<"
|
|
||||||
@$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -c $< -o $@
|
|
||||||
|
|
||||||
# Debug build
|
|
||||||
debug: CFLAGS = $(DEBUG_CFLAGS)
|
|
||||||
debug: $(TARGET)
|
|
||||||
|
|
||||||
# Static build (for distribution)
|
|
||||||
static: LDFLAGS += -static
|
|
||||||
static: $(TARGET)
|
|
||||||
|
|
||||||
# Check if required dependencies are available
|
|
||||||
check-deps:
|
|
||||||
@echo "Checking dependencies..."
|
|
||||||
@pkg-config --exists $(PKG_DEPS) || (echo "Missing dependencies. Install: wayland-protocols libwayland-dev libegl1-mesa-dev libgl1-mesa-dev wayland-scanner" && exit 1)
|
|
||||||
@which wayland-scanner >/dev/null || (echo "wayland-scanner not found. Please install wayland-scanner." && exit 1)
|
|
||||||
@echo "All dependencies found."
|
|
||||||
|
|
||||||
# Install
|
|
||||||
install: $(TARGET)
|
|
||||||
@echo "Installing $(PROJECT_NAME)..."
|
|
||||||
install -Dm755 $(TARGET) $(DESTDIR)$(BINDIR_INSTALL)/$(PROJECT_NAME)
|
|
||||||
@if [ -f $(SYSTEMD_DIR)/$(PROJECT_NAME).service ]; then \
|
|
||||||
echo "Installing systemd service..."; \
|
|
||||||
install -Dm644 $(SYSTEMD_DIR)/$(PROJECT_NAME).service $(DESTDIR)$(SYSTEMD_INSTALL)/$(PROJECT_NAME).service; \
|
|
||||||
fi
|
|
||||||
@echo "Installation complete."
|
|
||||||
|
|
||||||
# Uninstall
|
|
||||||
uninstall:
|
|
||||||
@echo "Uninstalling $(PROJECT_NAME)..."
|
|
||||||
rm -f $(DESTDIR)$(BINDIR_INSTALL)/$(PROJECT_NAME)
|
|
||||||
rm -f $(DESTDIR)$(SYSTEMD_INSTALL)/$(PROJECT_NAME).service
|
|
||||||
@echo "Uninstall complete."
|
|
||||||
|
|
||||||
# Create systemd service file
|
|
||||||
systemd-service: $(SYSTEMD_DIR)/$(PROJECT_NAME).service
|
|
||||||
|
|
||||||
|
|
||||||
# Clean build artifacts
|
|
||||||
clean:
|
|
||||||
@echo "Cleaning build artifacts..."
|
|
||||||
rm -rf $(OBJDIR) $(BINDIR)
|
|
||||||
rm -f $(PROTOCOL_HEADERS) $(PROTOCOL_SOURCES)
|
|
||||||
|
|
||||||
# Format source code (requires clang-format)
|
|
||||||
format:
|
|
||||||
@echo "Formatting source code..."
|
|
||||||
@find $(SRCDIR) $(INCDIR) -name "*.c" -o -name "*.h" | xargs clang-format -i
|
|
||||||
|
|
||||||
# Static analysis (requires cppcheck)
|
|
||||||
analyze:
|
|
||||||
@echo "Running static analysis..."
|
|
||||||
@cppcheck --enable=all --std=c11 --language=c \
|
|
||||||
--include=$(INCDIR) \
|
|
||||||
--suppress=missingIncludeSystem \
|
|
||||||
--quiet \
|
|
||||||
$(SRCDIR)
|
|
||||||
|
|
||||||
# Run tests
|
|
||||||
# FIXME: add tests
|
|
||||||
test: $(TARGET)
|
|
||||||
@echo "Running tests..."
|
|
||||||
@echo "Tests not implemented yet."
|
|
||||||
|
|
||||||
# Help target
|
|
||||||
help:
|
|
||||||
@echo "Available targets:"
|
|
||||||
@echo " all - Build the main executable (default)"
|
|
||||||
@echo " debug - Build with debug symbols and sanitizers"
|
|
||||||
@echo " static - Build statically linked executable"
|
|
||||||
@echo " check-deps - Check if all dependencies are available"
|
|
||||||
@echo " install - Install the executable and systemd service"
|
|
||||||
@echo " uninstall - Remove installed files"
|
|
||||||
@echo " clean - Remove build artifacts"
|
|
||||||
@echo " distclean - Remove all generated files"
|
|
||||||
@echo " format - Format source code (requires clang-format)"
|
|
||||||
@echo " analyze - Run static analysis (requires cppcheck)"
|
|
||||||
@echo " test - Run tests"
|
|
||||||
@echo " help - Show this help message"
|
|
||||||
@echo ""
|
|
||||||
@echo "Examples:"
|
|
||||||
@echo " make # Build with default settings"
|
|
||||||
@echo " make debug # Build debug version"
|
|
||||||
@echo " make PREFIX=/usr install # Install to /usr instead of /usr/local"
|
|
||||||
@echo " make CC=clang # Use clang instead of gcc"
|
|
||||||
|
|
||||||
# Include dependency files
|
|
||||||
-include $(DEPENDS)
|
|
||||||
|
|
||||||
# Phony targets
|
|
||||||
.PHONY: all debug static check-deps install uninstall systemd-service sample-config clean distclean format analyze test help
|
|
||||||
|
|
||||||
# Print variables
|
|
||||||
print-%:
|
|
||||||
@echo '$*=$($*)'
|
|
211
README.md
211
README.md
|
@ -1,211 +0,0 @@
|
||||||
# Chroma
|
|
||||||
|
|
||||||
A simple, lightweight and efficientt wallpaper daeemon for Wayland compositors
|
|
||||||
with multi-monitor & automatic hotplugging support. Born from my woes with
|
|
||||||
Hyprpaper, swaybg and most ironically SWWW, which turned out to be NOT a
|
|
||||||
solution to my Wayland wallpaper woes.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
I did not expect to be writing something too feature-rich, but I still ended up
|
|
||||||
with something relatively convoluted. Chroma (mostly) reliably supports:
|
|
||||||
|
|
||||||
- **Multi-monitors**: Automatically detects and manages wallpapers for all
|
|
||||||
connected displays
|
|
||||||
- **Hotplugging**: Dynamically handles monitor connection/disconnection events
|
|
||||||
- **Per-output configuration**: Set different wallpapers for each monitor
|
|
||||||
- **Multiple image formats**: Supports JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC,
|
|
||||||
PPM, PGM
|
|
||||||
- **EGL/OpenGL rendering**: Hardware-accelerated wallpaper rendering
|
|
||||||
- **Configuration file support**: Easy setup with INI-style config files
|
|
||||||
- **Signal handling**: Graceful shutdown and configuration reload (SIGHUP)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Requirements
|
|
||||||
|
|
||||||
#### Dependencies
|
|
||||||
|
|
||||||
- **Wayland**: wayland-client, wayland-egl
|
|
||||||
- **Graphics**: EGL, OpenGL
|
|
||||||
- **System**: glibc, libm, libdl
|
|
||||||
|
|
||||||
#### Development Dependencies
|
|
||||||
|
|
||||||
- GCC or Clang compiler
|
|
||||||
- Make
|
|
||||||
- pkg-config
|
|
||||||
- Wayland development headers
|
|
||||||
- EGL/OpenGL development headers
|
|
||||||
|
|
||||||
### Building
|
|
||||||
|
|
||||||
#### Quick Build
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check dependencies
|
|
||||||
make check-deps
|
|
||||||
|
|
||||||
# Build the daemon
|
|
||||||
make
|
|
||||||
|
|
||||||
# Or build debug version
|
|
||||||
make debug
|
|
||||||
```
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install to /usr/local (default)
|
|
||||||
sudo make install
|
|
||||||
|
|
||||||
# Install to /usr
|
|
||||||
sudo make PREFIX=/usr install
|
|
||||||
|
|
||||||
# Create systemd service file
|
|
||||||
make systemd-service
|
|
||||||
|
|
||||||
# Create sample configuration
|
|
||||||
make sample-config
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
#### Configuration File
|
|
||||||
|
|
||||||
Chroma looks for configuration files in this order:
|
|
||||||
|
|
||||||
1. `~/.config/chroma/chroma.conf`
|
|
||||||
2. `$XDG_CONFIG_HOME/chroma/chroma.conf`
|
|
||||||
3. `./chroma.conf` (current directory)
|
|
||||||
|
|
||||||
#### Sample Configuration
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Default wallpaper for outputs without specific mapping
|
|
||||||
default_image = ~/.config/chroma/default.jpg
|
|
||||||
|
|
||||||
# Output-specific wallpapers
|
|
||||||
# Format: output.OUTPUT_NAME = /path/to/image.jpg
|
|
||||||
output.DP-1 = ~/Pictures/monitor1.jpg
|
|
||||||
output.DP-2 = ~/Pictures/monitor2.png
|
|
||||||
output.HDMI-A-1 = ~/Pictures/hdmi_wallpaper.jpg
|
|
||||||
```
|
|
||||||
|
|
||||||
### Finding Output Names
|
|
||||||
|
|
||||||
Use `wlr-randr` or similar tools to find your output names:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
wlr-randr
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command Line Options
|
|
||||||
|
|
||||||
```plaintext
|
|
||||||
Usage: chroma [OPTIONS]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-c, --config FILE Configuration file path
|
|
||||||
-d, --daemon Run as daemon
|
|
||||||
-v, --verbose Verbose logging
|
|
||||||
-h, --help Show help
|
|
||||||
--version Show version information
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
chroma -c ~/.config/chroma/chroma.conf
|
|
||||||
chroma --daemon
|
|
||||||
```
|
|
||||||
|
|
||||||
### Running Manually
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run in foreground
|
|
||||||
chroma
|
|
||||||
|
|
||||||
# Run as daemon
|
|
||||||
chroma --daemon
|
|
||||||
|
|
||||||
# Use custom config
|
|
||||||
chroma -c /path/to/config.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
### Systemd Service
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Enable and start the service
|
|
||||||
systemctl --user enable chroma.service
|
|
||||||
systemctl --user start chroma.service
|
|
||||||
|
|
||||||
# Check status
|
|
||||||
systemctl --user status chroma.service
|
|
||||||
|
|
||||||
# View logs
|
|
||||||
journalctl --user -u chroma.service -f
|
|
||||||
|
|
||||||
# Reload configuration
|
|
||||||
systemctl --user reload chroma.service
|
|
||||||
```
|
|
||||||
|
|
||||||
### Auto-start with Desktop Session
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Enable the service for auto-start
|
|
||||||
systemctl --user enable chroma.service
|
|
||||||
|
|
||||||
# The service will start automatically with your graphical session
|
|
||||||
```
|
|
||||||
|
|
||||||
### Supported Wayland Compositors
|
|
||||||
|
|
||||||
Chroma works with any Wayland compositor that supports:
|
|
||||||
|
|
||||||
- `wl_compositor` interface
|
|
||||||
- `wl_output` interface
|
|
||||||
- EGL window surface creation
|
|
||||||
|
|
||||||
Tested only on Hyprland.
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
### Building Debug Version
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make debug
|
|
||||||
```
|
|
||||||
|
|
||||||
### Code Formatting
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make format # requires clang-format
|
|
||||||
```
|
|
||||||
|
|
||||||
### Static Analysis
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make analyze # requires cppcheck
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
1. Fork the repository
|
|
||||||
2. Create a feature branch
|
|
||||||
3. Make your changes
|
|
||||||
4. Test thoroughly
|
|
||||||
5. Submit a pull request
|
|
||||||
|
|
||||||
### Code Style
|
|
||||||
|
|
||||||
- C11 standard
|
|
||||||
- 2-space indentation
|
|
||||||
- No tabs
|
|
||||||
- Function names: `chroma_function_name`
|
|
||||||
- Constants: `CHROMA_CONSTANT_NAME`
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
<!--markdownlint-disable MD059 -->
|
|
||||||
|
|
||||||
This project is made available under Mozilla Public License (MPL) version 2.0.
|
|
||||||
See [LICENSE](LICENSE) for more details on the exact conditions. An online copy
|
|
||||||
is provided [here](https://www.mozilla.org/en-US/MPL/2.0/).
|
|
|
@ -1,48 +0,0 @@
|
||||||
# This is a sample configuration file for the Chroma wallpaper daemon.
|
|
||||||
# Lines starting with # are comments and are ignored.
|
|
||||||
#
|
|
||||||
# Configuration file locations (checked in order):
|
|
||||||
# 1. ~/.config/chroma/chroma.conf
|
|
||||||
# 2. $XDG_CONFIG_HOME/chroma/chroma.conf
|
|
||||||
# 3. ./chroma.conf (current directory)
|
|
||||||
#
|
|
||||||
# To get started:
|
|
||||||
# 1. Copy this file to ~/.config/chroma/chroma.conf
|
|
||||||
# 2. Modify the paths to point to your wallpaper images
|
|
||||||
# 3. Use 'wlr-randr' or similar tools to find your output names
|
|
||||||
# 4. Restart chroma or send SIGHUP to reload configuration
|
|
||||||
|
|
||||||
# This image will be used for any output that doesn't have a specific mapping.
|
|
||||||
# Supports: JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC, PPM, PGM
|
|
||||||
# Paths can be absolute or relative, ~ expansion is supported.
|
|
||||||
#
|
|
||||||
# Alternative examples:
|
|
||||||
# default_image = ~/Pictures/wallpapers/default.png
|
|
||||||
# default_image = /usr/share/wallpapers/default.jpg
|
|
||||||
# default_image = ./wallpapers/fallback.jpg
|
|
||||||
default_image = ~/.config/chroma/default.jpg
|
|
||||||
|
|
||||||
|
|
||||||
# Whether to run as a background daemon
|
|
||||||
# Usually set via command line option --daemon, but can be set here too
|
|
||||||
daemon_mode = false
|
|
||||||
|
|
||||||
# Output-specific wallpaper mappings
|
|
||||||
# ==================================
|
|
||||||
# Format: output.OUTPUT_NAME = /path/to/image.ext
|
|
||||||
#
|
|
||||||
# To find your output names, run one of these commands:
|
|
||||||
# - wlr-randr (for wlroots-based compositors like Sway, Hyprland)
|
|
||||||
# - wayland-info | grep wl_output
|
|
||||||
# - kanshi list-outputs
|
|
||||||
#
|
|
||||||
# Common output name patterns:
|
|
||||||
# - DP-1, DP-2, DP-3, etc. (DisplayPort)
|
|
||||||
# - HDMI-A-1, HDMI-A-2, etc. (HDMI)
|
|
||||||
# - eDP-1 (embedded DisplayPort, laptops)
|
|
||||||
# - DVI-D-1, DVI-I-1 (DVI)
|
|
||||||
# - VGA-1 (VGA, legacy)
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# output.HDMI-A-1 = ~/Pictures/wallpaper.jpg
|
|
||||||
|
|
26
flake.lock
generated
26
flake.lock
generated
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1759155593,
|
|
||||||
"narHash": "sha256-potIJyEY7ExgfiMzr44/KBODFednyzRUAE2vs4aThHs=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "13ca7febc86978bdb67c0ae94f568b189ae84eef",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
22
flake.nix
22
flake.nix
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
description = "Wayland Wallpaper Daemon";
|
|
||||||
|
|
||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs?ref?nixos-unstable";
|
|
||||||
outputs = {nixpkgs, ...}: let
|
|
||||||
systems = ["x86_64-linux" "aarch64-linux"];
|
|
||||||
forAllSystems = f:
|
|
||||||
builtins.listToAttrs (map (system: {
|
|
||||||
name = system;
|
|
||||||
value = f system;
|
|
||||||
})
|
|
||||||
systems);
|
|
||||||
|
|
||||||
pkgsFor = system: nixpkgs.legacyPackages.${system};
|
|
||||||
in {
|
|
||||||
devShells = forAllSystems (system: let
|
|
||||||
pkgs = pkgsFor system;
|
|
||||||
in {
|
|
||||||
default = pkgs.callPackage ./shell.nix {};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -62,14 +62,6 @@ typedef struct {
|
||||||
|
|
||||||
// Associated wallpaper
|
// Associated wallpaper
|
||||||
chroma_image_t *image;
|
chroma_image_t *image;
|
||||||
|
|
||||||
// OpenGL resource cache
|
|
||||||
GLuint texture_id;
|
|
||||||
GLuint shader_program;
|
|
||||||
GLuint vbo;
|
|
||||||
GLuint ebo;
|
|
||||||
bool gl_resources_initialized;
|
|
||||||
bool texture_uploaded;
|
|
||||||
} chroma_output_t;
|
} chroma_output_t;
|
||||||
|
|
||||||
// Config mapping structure
|
// Config mapping structure
|
||||||
|
@ -158,7 +150,6 @@ void chroma_egl_cleanup(chroma_state_t *state);
|
||||||
int chroma_surface_create(chroma_state_t *state, chroma_output_t *output);
|
int chroma_surface_create(chroma_state_t *state, chroma_output_t *output);
|
||||||
void chroma_surface_destroy(chroma_output_t *output);
|
void chroma_surface_destroy(chroma_output_t *output);
|
||||||
int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output);
|
int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output);
|
||||||
void chroma_output_invalidate_texture(chroma_output_t *output);
|
|
||||||
|
|
||||||
// Layer shell functions
|
// Layer shell functions
|
||||||
void chroma_layer_surface_configure(void *data,
|
void chroma_layer_surface_configure(void *data,
|
||||||
|
@ -228,4 +219,4 @@ extern const struct zwlr_layer_surface_v1_listener
|
||||||
// Global state for signal handling
|
// Global state for signal handling
|
||||||
extern volatile sig_atomic_t chroma_should_quit;
|
extern volatile sig_atomic_t chroma_should_quit;
|
||||||
|
|
||||||
#endif // CHROMA_H
|
#endif // CHROMA_H
|
51
shell.nix
51
shell.nix
|
@ -1,51 +0,0 @@
|
||||||
{pkgs ? import <nixpkgs> {}}:
|
|
||||||
pkgs.mkShell {
|
|
||||||
name = "chroma";
|
|
||||||
buildInputs = with pkgs; [
|
|
||||||
gnumake
|
|
||||||
|
|
||||||
# Optional development tools
|
|
||||||
gdb
|
|
||||||
valgrind
|
|
||||||
strace
|
|
||||||
|
|
||||||
# Code formatting and analysis
|
|
||||||
clang-tools # includes clang-format
|
|
||||||
cppcheck
|
|
||||||
|
|
||||||
# Wayland libraries
|
|
||||||
wayland.dev
|
|
||||||
wayland-protocols
|
|
||||||
wayland-scanner
|
|
||||||
libxkbcommon
|
|
||||||
|
|
||||||
# EGL/OpenGL libraries
|
|
||||||
libGL
|
|
||||||
mesa
|
|
||||||
|
|
||||||
# System libraries
|
|
||||||
glibc.dev
|
|
||||||
];
|
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [
|
|
||||||
pkg-config
|
|
||||||
];
|
|
||||||
|
|
||||||
shellHook = ''
|
|
||||||
echo "Available commands:"
|
|
||||||
echo " make - Build the project"
|
|
||||||
echo " make debug - Build with debug symbols"
|
|
||||||
echo " make clean - Clean build artifacts"
|
|
||||||
echo " make install - Install to ~/.local"
|
|
||||||
echo " make help - Show all available targets"
|
|
||||||
echo
|
|
||||||
echo "Run 'make check-deps' to verify all dependencies are available."
|
|
||||||
echo
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Environment variables for the build system
|
|
||||||
env = {
|
|
||||||
CHROMA_VERSION = "1.0.0";
|
|
||||||
WAYLAND_DEBUG = 1;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -87,14 +87,6 @@ static int assign_wallpaper_to_output(chroma_state_t *state,
|
||||||
return CHROMA_ERROR_IMAGE;
|
return CHROMA_ERROR_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if image changed and invalidate texture cache if neceessary
|
|
||||||
bool image_changed = (output->image != image);
|
|
||||||
if (image_changed && output->image) {
|
|
||||||
chroma_output_invalidate_texture(output);
|
|
||||||
chroma_log("DEBUG", "Image changed for output %u, invalidated texture",
|
|
||||||
output->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign image to output
|
// Assign image to output
|
||||||
output->image = image;
|
output->image = image;
|
||||||
|
|
||||||
|
|
49
src/image.c
49
src/image.c
|
@ -49,12 +49,11 @@ int chroma_image_load(chroma_image_t *image, const char *path) {
|
||||||
(double)file_size / (1024.0 * 1024.0));
|
(double)file_size / (1024.0 * 1024.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load image data using stb_image, force RGBA format to avoid conversion
|
// Load image data using stb_image
|
||||||
stbi_set_flip_vertically_on_load(0); // keep images right-side up
|
stbi_set_flip_vertically_on_load(0); // Keep images right-side up
|
||||||
|
|
||||||
image->data =
|
image->data =
|
||||||
stbi_load(path, &image->width, &image->height, &image->channels, 4);
|
stbi_load(path, &image->width, &image->height, &image->channels, 0);
|
||||||
image->channels = 4; // always RGBA after forced conversion
|
|
||||||
if (!image->data) {
|
if (!image->data) {
|
||||||
chroma_log("ERROR", "Failed to load image %s: %s", path,
|
chroma_log("ERROR", "Failed to load image %s: %s", path,
|
||||||
stbi_failure_reason());
|
stbi_failure_reason());
|
||||||
|
@ -69,14 +68,39 @@ int chroma_image_load(chroma_image_t *image, const char *path) {
|
||||||
return CHROMA_ERROR_IMAGE;
|
return CHROMA_ERROR_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate we have RGBA data (should always be true with forced conversion)
|
// Check supported formats
|
||||||
if (image->channels != 4) {
|
if (image->channels < 3 || image->channels > 4) {
|
||||||
chroma_log("ERROR", "Failed to load image as RGBA: got %d channels",
|
chroma_log("ERROR",
|
||||||
|
"Unsupported image format: %d channels (need RGB or RGBA)",
|
||||||
image->channels);
|
image->channels);
|
||||||
chroma_image_free(image);
|
chroma_image_free(image);
|
||||||
return CHROMA_ERROR_IMAGE;
|
return CHROMA_ERROR_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert RGB to RGBA if necessary for consistent handling
|
||||||
|
if (image->channels == 3) {
|
||||||
|
int pixel_count = image->width * image->height;
|
||||||
|
unsigned char *rgba_data = malloc(pixel_count * 4);
|
||||||
|
if (!rgba_data) {
|
||||||
|
chroma_log("ERROR", "Failed to allocate memory for RGBA conversion");
|
||||||
|
chroma_image_free(image);
|
||||||
|
return CHROMA_ERROR_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert RGB to RGBA
|
||||||
|
for (int i = 0; i < pixel_count; i++) {
|
||||||
|
rgba_data[i * 4 + 0] = image->data[i * 3 + 0]; // R
|
||||||
|
rgba_data[i * 4 + 1] = image->data[i * 3 + 1]; // G
|
||||||
|
rgba_data[i * 4 + 2] = image->data[i * 3 + 2]; // B
|
||||||
|
rgba_data[i * 4 + 3] = 255; // A
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace original data
|
||||||
|
stbi_image_free(image->data);
|
||||||
|
image->data = rgba_data;
|
||||||
|
image->channels = 4;
|
||||||
|
}
|
||||||
|
|
||||||
image->loaded = true;
|
image->loaded = true;
|
||||||
|
|
||||||
chroma_log("INFO", "Loaded image: %s (%dx%d, %d channels, %.2f MB)", path,
|
chroma_log("INFO", "Loaded image: %s (%dx%d, %d channels, %.2f MB)", path,
|
||||||
|
@ -94,8 +118,13 @@ void chroma_image_free(chroma_image_t *image) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image->data) {
|
if (image->data) {
|
||||||
// Always use stbi_image_free since we load directly with stbi_load
|
if (image->channels == 4 && strlen(image->path) > 0) {
|
||||||
stbi_image_free(image->data);
|
// If we converted from RGB to RGBA, use regular free()
|
||||||
|
free(image->data);
|
||||||
|
} else {
|
||||||
|
// If loaded directly by stb_image, use stbi_image_free()
|
||||||
|
stbi_image_free(image->data);
|
||||||
|
}
|
||||||
image->data = NULL;
|
image->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,4 +265,4 @@ void chroma_image_init_stb(void) {
|
||||||
stbi_ldr_to_hdr_scale(1.0f);
|
stbi_ldr_to_hdr_scale(1.0f);
|
||||||
|
|
||||||
chroma_log("DEBUG", "Initialized stb_image library");
|
chroma_log("DEBUG", "Initialized stb_image library");
|
||||||
}
|
}
|
267
src/render.c
267
src/render.c
|
@ -1,3 +1,4 @@
|
||||||
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -6,7 +7,6 @@
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
|
|
||||||
#include "../include/chroma.h"
|
#include "../include/chroma.h"
|
||||||
#include "../include/stb_image.h"
|
|
||||||
|
|
||||||
// Vertex shader for simple texture rendering
|
// Vertex shader for simple texture rendering
|
||||||
static const char *vertex_shader_source =
|
static const char *vertex_shader_source =
|
||||||
|
@ -31,17 +31,18 @@ static const char *fragment_shader_source =
|
||||||
// Vertices for a fullscreen quad
|
// Vertices for a fullscreen quad
|
||||||
static const float vertices[] = {
|
static const float vertices[] = {
|
||||||
// Position Texcoord
|
// Position Texcoord
|
||||||
-1.0f, -1.0f, 0.0f, 1.0f, // bottom left
|
-1.0f, -1.0f, 0.0f, 1.0f, // Bottom left
|
||||||
1.0f, -1.0f, 1.0f, 1.0f, // bottom right
|
1.0f, -1.0f, 1.0f, 1.0f, // Bottom right
|
||||||
1.0f, 1.0f, 1.0f, 0.0f, // top right
|
1.0f, 1.0f, 1.0f, 0.0f, // Top right
|
||||||
-1.0f, 1.0f, 0.0f, 0.0f, // top left
|
-1.0f, 1.0f, 0.0f, 0.0f, // Top left
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned int indices[] = {
|
static const unsigned int indices[] = {
|
||||||
0, 1, 2, // first triangle
|
0, 1, 2, // First triangle
|
||||||
2, 3, 0 // second triangle
|
2, 3, 0 // Second triangle
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Shader compilation helper
|
||||||
static GLuint compile_shader(GLenum type, const char *source) {
|
static GLuint compile_shader(GLenum type, const char *source) {
|
||||||
GLuint shader = glCreateShader(type);
|
GLuint shader = glCreateShader(type);
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
|
@ -65,6 +66,7 @@ static GLuint compile_shader(GLenum type, const char *source) {
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shader program creation helper
|
||||||
static GLuint create_shader_program(void) {
|
static GLuint create_shader_program(void) {
|
||||||
GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_source);
|
GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_source);
|
||||||
if (!vertex_shader) {
|
if (!vertex_shader) {
|
||||||
|
@ -106,145 +108,6 @@ static GLuint create_shader_program(void) {
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize OpenGL resources for output
|
|
||||||
static int init_gl_resources(chroma_output_t *output) {
|
|
||||||
if (!output || output->gl_resources_initialized) {
|
|
||||||
return CHROMA_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create shader prog
|
|
||||||
output->shader_program = create_shader_program();
|
|
||||||
if (!output->shader_program) {
|
|
||||||
chroma_log("ERROR", "Failed to create shader program for output %u",
|
|
||||||
output->id);
|
|
||||||
return CHROMA_ERROR_EGL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and setup VBO/EBO
|
|
||||||
glGenBuffers(1, &output->vbo);
|
|
||||||
glGenBuffers(1, &output->ebo);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, output->vbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, output->ebo);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
|
|
||||||
GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
output->texture_id = 0; // will be created when image is assigned
|
|
||||||
output->gl_resources_initialized = true;
|
|
||||||
|
|
||||||
chroma_log("DEBUG", "Initialized GL resources for output %u", output->id);
|
|
||||||
return CHROMA_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create or update texture from image data
|
|
||||||
static int update_texture_from_image(chroma_output_t *output,
|
|
||||||
chroma_image_t *image) {
|
|
||||||
if (!output || !image || !image->loaded) {
|
|
||||||
return CHROMA_ERROR_INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If image data was already freed after previous GPU upload, we can't upload
|
|
||||||
// again
|
|
||||||
if (!image->data) {
|
|
||||||
chroma_log("ERROR",
|
|
||||||
"Cannot create texture: image data already freed for %s",
|
|
||||||
image->path);
|
|
||||||
return CHROMA_ERROR_IMAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete existing texture if it exists
|
|
||||||
if (output->texture_id != 0) {
|
|
||||||
glDeleteTextures(1, &output->texture_id);
|
|
||||||
output->texture_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new texture
|
|
||||||
glGenTextures(1, &output->texture_id);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, output->texture_id);
|
|
||||||
|
|
||||||
// Set texture parameters
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
// Upload texture data (always RGBA now)
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->width, image->height, 0,
|
|
||||||
GL_RGBA, GL_UNSIGNED_BYTE, image->data);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
// Mark this output as having uploaded its texture
|
|
||||||
output->texture_uploaded = true;
|
|
||||||
|
|
||||||
// Free system RAM copy only when ALL outputs using this image have uploaded
|
|
||||||
// to GPU
|
|
||||||
if (image->data) {
|
|
||||||
// Count total outputs using this image and how many have uploaded
|
|
||||||
int total_using = 0;
|
|
||||||
int uploaded_count = 0;
|
|
||||||
|
|
||||||
chroma_state_t *state = output->state;
|
|
||||||
for (int i = 0; i < state->output_count; i++) {
|
|
||||||
if (state->outputs[i].active && state->outputs[i].image == image) {
|
|
||||||
total_using++;
|
|
||||||
if (state->outputs[i].texture_uploaded) {
|
|
||||||
uploaded_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only free image data when ALL outputs using it have uploaded
|
|
||||||
if (total_using > 0 && uploaded_count >= total_using) {
|
|
||||||
size_t freed_bytes =
|
|
||||||
(size_t)image->width * image->height * image->channels;
|
|
||||||
stbi_image_free(image->data);
|
|
||||||
image->data = NULL;
|
|
||||||
chroma_log("INFO",
|
|
||||||
"Freed %.2f MB of image data after all %d outputs uploaded to "
|
|
||||||
"GPU: %s",
|
|
||||||
(double)freed_bytes / (1024.0 * 1024.0), total_using,
|
|
||||||
image->path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chroma_log("DEBUG", "Updated texture for output %u (%dx%d)", output->id,
|
|
||||||
image->width, image->height);
|
|
||||||
return CHROMA_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup OpenGL resources for output
|
|
||||||
static void cleanup_gl_resources(chroma_output_t *output) {
|
|
||||||
if (!output || !output->gl_resources_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output->texture_id != 0) {
|
|
||||||
glDeleteTextures(1, &output->texture_id);
|
|
||||||
output->texture_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output->shader_program != 0) {
|
|
||||||
glDeleteProgram(output->shader_program);
|
|
||||||
output->shader_program = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output->vbo != 0) {
|
|
||||||
glDeleteBuffers(1, &output->vbo);
|
|
||||||
output->vbo = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output->ebo != 0) {
|
|
||||||
glDeleteBuffers(1, &output->ebo);
|
|
||||||
output->ebo = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
output->gl_resources_initialized = false;
|
|
||||||
chroma_log("DEBUG", "Cleaned up GL resources for output %u", output->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// EGL configuration selection
|
// EGL configuration selection
|
||||||
static int choose_egl_config(EGLDisplay display, EGLConfig *config) {
|
static int choose_egl_config(EGLDisplay display, EGLConfig *config) {
|
||||||
EGLint attributes[] = {EGL_SURFACE_TYPE,
|
EGLint attributes[] = {EGL_SURFACE_TYPE,
|
||||||
|
@ -429,9 +292,6 @@ void chroma_surface_destroy(chroma_output_t *output) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up OpenGL resources first
|
|
||||||
cleanup_gl_resources(output);
|
|
||||||
|
|
||||||
if (output->egl_surface != EGL_NO_SURFACE) {
|
if (output->egl_surface != EGL_NO_SURFACE) {
|
||||||
eglDestroySurface(eglGetCurrentDisplay(), output->egl_surface);
|
eglDestroySurface(eglGetCurrentDisplay(), output->egl_surface);
|
||||||
output->egl_surface = EGL_NO_SURFACE;
|
output->egl_surface = EGL_NO_SURFACE;
|
||||||
|
@ -455,7 +315,33 @@ void chroma_surface_destroy(chroma_output_t *output) {
|
||||||
chroma_log("DEBUG", "Destroyed surface for output %u", output->id);
|
chroma_log("DEBUG", "Destroyed surface for output %u", output->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render wallpaper to output using cached resources
|
// Create texture from image data
|
||||||
|
static GLuint create_texture_from_image(chroma_image_t *image) {
|
||||||
|
if (!image || !image->loaded || !image->data) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
// Set texture parameters
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
// Upload texture data
|
||||||
|
GLenum format = (image->channels == 4) ? GL_RGBA : GL_RGB;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, format, image->width, image->height, 0, format,
|
||||||
|
GL_UNSIGNED_BYTE, image->data);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render wallpaper to output
|
||||||
int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) {
|
int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) {
|
||||||
if (!state || !output || !output->image || !output->image->loaded) {
|
if (!state || !output || !output->image || !output->image->loaded) {
|
||||||
return CHROMA_ERROR_INIT;
|
return CHROMA_ERROR_INIT;
|
||||||
|
@ -469,17 +355,6 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) {
|
||||||
return CHROMA_ERROR_EGL;
|
return CHROMA_ERROR_EGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_gl_resources(output) != CHROMA_OK) {
|
|
||||||
return CHROMA_ERROR_EGL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output->texture_id == 0) {
|
|
||||||
if (update_texture_from_image(output, output->image) != CHROMA_OK) {
|
|
||||||
chroma_log("ERROR", "Failed to update texture for output %u", output->id);
|
|
||||||
return CHROMA_ERROR_EGL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set viewport
|
// Set viewport
|
||||||
glViewport(0, 0, output->width, output->height);
|
glViewport(0, 0, output->width, output->height);
|
||||||
|
|
||||||
|
@ -487,21 +362,42 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) {
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// Use cached shader program
|
// Create shader program (should be cached in real implementation)
|
||||||
glUseProgram(output->shader_program);
|
GLuint program = create_shader_program();
|
||||||
|
if (!program) {
|
||||||
|
return CHROMA_ERROR_EGL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use shader program
|
||||||
|
glUseProgram(program);
|
||||||
|
|
||||||
|
// Create and bind texture
|
||||||
|
GLuint texture = create_texture_from_image(output->image);
|
||||||
|
if (!texture) {
|
||||||
|
chroma_log("ERROR", "Failed to create texture for output %u", output->id);
|
||||||
|
glDeleteProgram(program);
|
||||||
|
return CHROMA_ERROR_EGL;
|
||||||
|
}
|
||||||
|
|
||||||
// Bind cached texture
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, output->texture_id);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
glUniform1i(glGetUniformLocation(output->shader_program, "texture"), 0);
|
glUniform1i(glGetUniformLocation(program, "texture"), 0);
|
||||||
|
|
||||||
// Use cached VBO/EBO
|
// Create vertex buffer objects (should be cached in real implementation)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, output->vbo);
|
GLuint vbo, ebo;
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, output->ebo);
|
glGenBuffers(1, &vbo);
|
||||||
|
glGenBuffers(1, &ebo);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
|
||||||
// Set vertex attributes
|
// Set vertex attributes
|
||||||
GLint position_attr = glGetAttribLocation(output->shader_program, "position");
|
GLint position_attr = glGetAttribLocation(program, "position");
|
||||||
GLint texcoord_attr = glGetAttribLocation(output->shader_program, "texcoord");
|
GLint texcoord_attr = glGetAttribLocation(program, "texcoord");
|
||||||
|
|
||||||
glEnableVertexAttribArray(position_attr);
|
glEnableVertexAttribArray(position_attr);
|
||||||
glVertexAttribPointer(position_attr, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float),
|
glVertexAttribPointer(position_attr, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float),
|
||||||
|
@ -514,11 +410,11 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) {
|
||||||
// Draw
|
// Draw
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
// Unbind resources
|
// Cleanup
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glDeleteBuffers(1, &vbo);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glDeleteBuffers(1, &ebo);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glDeleteTextures(1, &texture);
|
||||||
glUseProgram(0);
|
glDeleteProgram(program);
|
||||||
|
|
||||||
// Swap buffers
|
// Swap buffers
|
||||||
if (!eglSwapBuffers(state->egl_display, output->egl_surface)) {
|
if (!eglSwapBuffers(state->egl_display, output->egl_surface)) {
|
||||||
|
@ -530,21 +426,6 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) {
|
||||||
// Commit surface
|
// Commit surface
|
||||||
wl_surface_commit(output->surface);
|
wl_surface_commit(output->surface);
|
||||||
|
|
||||||
chroma_log("DEBUG", "Rendered wallpaper to output %u (cached resources)",
|
chroma_log("DEBUG", "Rendered wallpaper to output %u", output->id);
|
||||||
output->id);
|
|
||||||
return CHROMA_OK;
|
return CHROMA_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate texture cache for output
|
|
||||||
void chroma_output_invalidate_texture(chroma_output_t *output) {
|
|
||||||
if (!output || !output->gl_resources_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output->texture_id != 0) {
|
|
||||||
glDeleteTextures(1, &output->texture_id);
|
|
||||||
output->texture_id = 0;
|
|
||||||
output->texture_uploaded = false; // reset upload flag
|
|
||||||
chroma_log("DEBUG", "Invalidated texture cache for output %u", output->id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Chroma Wallpaper Daemon
|
|
||||||
After=graphical-session.target
|
|
||||||
Wants=graphical-session.target
|
|
||||||
PartOf=graphical-session.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=chroma
|
|
||||||
ExecReload=kill -HUP $MAINPID
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=1
|
|
||||||
KillMode=mixed
|
|
||||||
TimeoutStopSec=5
|
|
||||||
|
|
||||||
# Security
|
|
||||||
NoNewPrivileges=true
|
|
||||||
PrivateDevices=true
|
|
||||||
ProtectSystem=strict
|
|
||||||
ProtectHome=read-only
|
|
||||||
ReadWritePaths=%h/.config/chroma
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-useer.target
|
|
Loading…
Add table
Add a link
Reference in a new issue