Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mk/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ CPPFLAGS += -Iinclude -Isrc \
CFLAGS += -std=c99 -Wall -Wextra -Wno-unused-parameter \
-Wno-typedef-redefinition -fPIC

# Per-function/-data sections so the shared-library link can --gc-sections away
# code no exported symbol reaches once mk/library.mk pins the export surface.
# ELF-only leverage; clang on Mach-O ignores these and dead-strips by symbol.
CFLAGS += -ffunction-sections -fdata-sections

# Release optimization default for first-party objects: libX11-compat core, the
# staged upstream libX11 sources, the compat toolkit libraries (libXt/Xpm/Xaw/
# Xmu/Xext/Xinerama/ICE/SM/Xft-compat), tests, and bundled examples. Debug CI
Expand Down
21 changes: 20 additions & 1 deletion mk/install.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@
PREFIX ?= /usr/local
DESTDIR ?=

# Strip local symbols from the installed libraries: the export surface (dynamic
# symbols) is untouched, so only the internal names in .symtab go, shaving ~6%
# off each .so. The in-tree build/ copies keep their local symbols so crash
# backtraces stay symbolic during development; only the deployed artifact slims.
# Override STRIP (e.g. STRIP=: for a packager that strips its own way, or a
# cross strip) to change or disable it.
STRIP ?= strip

# strip -x rewrites the Mach-O, which invalidates the ad-hoc signature ld64 puts
# on arm64 binaries. Apple's own strip re-signs, but lld or an older toolchain
# does not, and dyld then refuses the installed dylib ("code signature invalid").
# Re-sign explicitly on Darwin so the default install is safe on any toolchain;
# elsewhere CODESIGN_RESIGN is the no-op colon builtin that just swallows the path.
CODESIGN_RESIGN := $(if $(filter Darwin,$(UNAME_S)),codesign --force --sign - ,:)

# Libraries a downstream links by their standard X11 SONAME (each gets a
# libNAME.so -> libNAME-compat.so alias).
XCOMPAT_INSTALL_ALIASED := X11 Xft Xext Xt Xmu Xaw Xpm Xinerama ICE SM
Expand All @@ -34,10 +49,14 @@ install: $(XCOMPAT_INSTALL_LIB_FILES) $(UPSTREAM_HEADERS_STAMP)
$(Q)mkdir -p "$(DESTDIR)$(PREFIX)/lib" "$(DESTDIR)$(PREFIX)/include"
$(Q)for l in $(XCOMPAT_INSTALL_ALIASED); do \
cp "$(OUT)/lib$$l-compat.so" "$(DESTDIR)$(PREFIX)/lib/" && \
$(STRIP) -x "$(DESTDIR)$(PREFIX)/lib/lib$$l-compat.so" && \
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
$(CODESIGN_RESIGN) "$(DESTDIR)$(PREFIX)/lib/lib$$l-compat.so" && \
ln -sf "lib$$l-compat.so" "$(DESTDIR)$(PREFIX)/lib/lib$$l.so" || exit 1; \
done
$(Q)for w in $(XCOMPAT_INSTALL_WRAPPERS); do \
cp "$(OUT)/lib$$w.so" "$(DESTDIR)$(PREFIX)/lib/"; \
cp "$(OUT)/lib$$w.so" "$(DESTDIR)$(PREFIX)/lib/" && \
$(STRIP) -x "$(DESTDIR)$(PREFIX)/lib/lib$$w.so" && \
$(CODESIGN_RESIGN) "$(DESTDIR)$(PREFIX)/lib/lib$$w.so" || exit 1; \
done
$(Q)cp -R "$(UPSTREAM_HEADERS_DIR)/." "$(DESTDIR)$(PREFIX)/include/"
$(Q)for d in $(XCOMPAT_INSTALL_HEADER_DIRS); do \
Expand Down
97 changes: 87 additions & 10 deletions mk/library.mk
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,98 @@ all: $(TARGET)
# segfaults at offset 0x50. -Bsymbolic (not just -Bsymbolic-functions)
# binds *both* function and data references to the local library at
# link time. Mach-O ld on macOS does not accept the flag, so gate it
# on Linux only.
LDFLAGS_LIB :=
# on Linux only. The version script below now hides those same lock
# globals outright (they are in no manifest, so local: keeps them out
# of the dynamic table entirely), which is strictly stronger than
# -Bsymbolic; the flag stays as belt-and-suspenders for the exported
# symbols' own intra-library references.

# Pin the exported surface to the intended public API. The library defaults to
# exporting every non-static symbol, which leaks ~400 internal helpers into the
# dynamic table; restricting the export set to the enforced manifests also lets
# the link garbage-collect code no exported symbol reaches (e.g. the Xft/Fc copy
# that only libXft-compat consumes). See scripts/gen-export-list.sh.
X11_EXPORT_MANIFESTS := tests/api-symbols.txt tests/shim-symbols.txt \
tests/private-symbols.txt tests/whitebox-symbols.txt

# GLX (and the export FORMAT) toggle the exported surface, so a GLX=0->1 flip
# without make clean must not reuse a map that hid glX* as local. That identity
# is tracked once by X11_LINK_CONFIG below: the defined-syms, the export list,
# and the linked libraries all take it as a prerequisite, so a change to GLX or
# FORMAT regenerates the map and relinks. The artifact names stay unversioned.
# The core link splits in two: LDFLAGS_LIB_COMMON is the binding every core .so
# needs (notably -Bsymbolic on Linux), LDFLAGS_LIB_PIN is the export-surface
# restriction only the shipped library wants. The whitebox test twin below
# reuses COMMON but drops PIN, so it keeps -Bsymbolic (without which the system
# libX11.so.6 that SDL2 loads on Linux interposes our lock/event globals) while
# exporting every internal the tests reach. The @loader_path rpath and the
# @rpath install_name / $ORIGIN rpath come from shared_lib_rpath_ldflags, keyed
# on $@ so each library carries its own soname.
LDFLAGS_LIB_COMMON :=
X11_RPATH_FLAGS = $(call shared_lib_rpath_ldflags,$(notdir $@))
ifeq ($(UNAME_S),Linux)
LDFLAGS_LIB += -Wl,-Bsymbolic $(call shared_lib_rpath_ldflags,$(notdir $(TARGET)))
X11_EXPORT_LIST := $(OUT)/libX11-compat.map
X11_EXPORT_FORMAT := elf
LDFLAGS_LIB_COMMON += -Wl,-Bsymbolic
LDFLAGS_LIB_PIN := -Wl,--version-script=$(X11_EXPORT_LIST) -Wl,--gc-sections
endif
ifeq ($(UNAME_S),Darwin)
# @loader_path lets the dylib find sibling compat shared libraries
# (libXt-compat, libXpm-compat, etc.) at the same directory level
# without requiring the consumer to bake in an absolute rpath.
LDFLAGS_LIB += -Wl,-install_name,@rpath/$(notdir $(TARGET)) \
-Wl,-rpath,@loader_path
X11_EXPORT_LIST := $(OUT)/libX11-compat.exports
X11_EXPORT_FORMAT := macho
LDFLAGS_LIB_PIN := -Wl,-exported_symbols_list,$(X11_EXPORT_LIST) -Wl,-dead_strip
endif

$(TARGET): $(OBJS) $(SDL_WRAPPER_TARGETS) | $(OUT)
X11_LINK_CONFIG := $(OUT)/libX11-compat.link-config
.PHONY: FORCE
$(X11_LINK_CONFIG): FORCE | $(OUT)
$(Q){ printf 'GLX=%s\n' '$(GLX)'; \
printf 'FORMAT=%s\n' '$(X11_EXPORT_FORMAT)'; } > $@.tmp
$(Q)if test -r $@ && cmp -s $@.tmp $@; then \
rm -f $@.tmp; \
else \
mv $@.tmp $@; \
fi

# The symbols the core objects actually define, so the export list can be
# intersected against them (see scripts/gen-export-list.sh for why). Darwin nm
# spells C symbols with a leading underscore; strip it so names match the
# manifests. Undefined entries (type U) are dropped.
X11_EXPORT_DEFINED := $(OUT)/libX11-compat.defined-syms
$(X11_EXPORT_DEFINED): $(OBJS) $(X11_LINK_CONFIG) | $(OUT)
@echo " GEN $@"
$(Q)nm -g $(OBJS) 2>/dev/null \
| awk '$$1 ~ /^[0-9a-fA-F]+$$/ { print $$NF }' \
| $(if $(filter Darwin,$(UNAME_S)),sed 's/^_//',cat) \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: On macOS the underscore ABI is silently dropped from the exported set. The defined-syms step strips the leading underscore from every nm symbol (sed 's/^_//' on Darwin), then gen-export-list.sh detects the underscore ABI with grep -E '^_X' on that same (stripped) file, so _Xdebug/_XGetHostname/... become Xdebug/... and never match. Since Mach-O uses -exported_symbols_list (everything not listed is hidden), the underscore ABI the PR intends to export for legacy direct-linkers ends up hidden on macOS, unlike the ELF build where the same globals are exported. Consider keeping the pre-strip names (or detecting the ABI before stripping) so both platforms export the underscore surface consistently.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At mk/library.mk, line 86:

<comment>On macOS the underscore ABI is silently dropped from the exported set. The defined-syms step strips the leading underscore from every nm symbol (`sed 's/^_//'` on Darwin), then gen-export-list.sh detects the underscore ABI with `grep -E '^_X'` on that same (stripped) file, so `_Xdebug`/`_XGetHostname`/... become `Xdebug`/... and never match. Since Mach-O uses `-exported_symbols_list` (everything not listed is hidden), the underscore ABI the PR intends to export for legacy direct-linkers ends up hidden on macOS, unlike the ELF build where the same globals are exported. Consider keeping the pre-strip names (or detecting the ABI before stripping) so both platforms export the underscore surface consistently.</comment>

<file context>
@@ -22,21 +22,98 @@ all: $(TARGET)
+	@echo "  GEN     $@"
+	$(Q)nm -g $(OBJS) 2>/dev/null \
+	    | awk '$$1 ~ /^[0-9a-fA-F]+$$/ { print $$NF }' \
+	    | $(if $(filter Darwin,$(UNAME_S)),sed 's/^_//',cat) \
+	    | LC_ALL=C sort -u > $@
+	$(Q)test -s $@ || { echo "  ERROR   $@ empty (nm found no defined symbols)" >&2; exit 1; }
</file context>

| LC_ALL=C sort -u > $@
$(Q)test -s $@ || { echo " ERROR $@ empty (nm found no defined symbols)" >&2; exit 1; }

# X11_EXPORT_FORMAT and GLX are quoted because a make GLX= override leaves GLX
# empty; unquoted it would vanish from the argv and shift every later positional,
# so the script would read the defined-syms path as the glx flag. Matching only
# lines whose first nm field is a hex address above keeps undefined-weak (type
# w/v) references out of the defined set, not just type U.
$(X11_EXPORT_LIST): $(X11_EXPORT_MANIFESTS) $(X11_EXPORT_DEFINED) \
scripts/gen-export-list.sh $(X11_LINK_CONFIG) | $(OUT)
@echo " GEN $@"
$(Q)scripts/gen-export-list.sh "$(X11_EXPORT_FORMAT)" "$(GLX)" \
$(X11_EXPORT_DEFINED) $(X11_EXPORT_MANIFESTS) > $@

$(TARGET): $(OBJS) $(SDL_WRAPPER_TARGETS) $(X11_EXPORT_LIST) \
$(X11_LINK_CONFIG) | $(OUT)
@echo " LD $@"
$(Q)$(CC) $(LDFLAGS) $(LDFLAGS_LIB_COMMON) $(X11_RPATH_FLAGS) \
$(LDFLAGS_LIB_PIN) -shared -o $@ $(OBJS) $(LDLIBS)

# Fat, unpinned twin of the core library for the whitebox tests (see mk/tests.mk
# for why they cannot link the pinned .so or the bare objects). Same objects and
# the same COMMON binding as $(TARGET), so -Bsymbolic still shields our globals
# from the system libX11.so.6, but with no export list every internal stays
# reachable. Built only as a prerequisite of the whitebox test binaries, never
# by all and never installed.
X11_TEST_LIB := $(OUT)/libX11-compat-test.so

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The whitebox test twin is hardcoded to libX11-compat-test.so even though on macOS shared libraries in this tree are .dylib and the extension is normally derived from the target. As long as whitebox tests are Linux-only this is benign, but it is a latent cross-platform inconsistency: building on Darwin produces a Mach-O file with a .so name. Consider gating the test-twin rule to the ELF platform or deriving the suffix from the platform so the name can't silently diverge if the whitebox suite is ever run on macOS.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At mk/library.mk, line 113:

<comment>The whitebox test twin is hardcoded to `libX11-compat-test.so` even though on macOS shared libraries in this tree are `.dylib` and the extension is normally derived from the target. As long as whitebox tests are Linux-only this is benign, but it is a latent cross-platform inconsistency: building on Darwin produces a Mach-O file with a `.so` name. Consider gating the test-twin rule to the ELF platform or deriving the suffix from the platform so the name can't silently diverge if the whitebox suite is ever run on macOS.</comment>

<file context>
@@ -22,21 +22,98 @@ all: $(TARGET)
+# from the system libX11.so.6, but with no export list every internal stays
+# reachable. Built only as a prerequisite of the whitebox test binaries, never
+# by all and never installed.
+X11_TEST_LIB := $(OUT)/libX11-compat-test.so
+$(X11_TEST_LIB): $(OBJS) $(SDL_WRAPPER_TARGETS) $(X11_LINK_CONFIG) | $(OUT)
 	@echo "  LD      $@"
</file context>

$(X11_TEST_LIB): $(OBJS) $(SDL_WRAPPER_TARGETS) $(X11_LINK_CONFIG) | $(OUT)
@echo " LD $@"
$(Q)$(CC) $(LDFLAGS) $(LDFLAGS_LIB) -shared -o $@ $(OBJS) $(LDLIBS)
$(Q)$(CC) $(LDFLAGS) $(LDFLAGS_LIB_COMMON) $(X11_RPATH_FLAGS) \
-shared -o $@ $(OBJS) $(LDLIBS)

endif # native .so build
20 changes: 20 additions & 0 deletions mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ CHECK_BINS := $(OUT)/tests/check $(OUT)/tests/symbol-coverage \
$(OUT)/tests/test-xinerama-link \
$(OUT)/tests/test-libxpm-link \
$(OUT)/tests/test-xft-link \
$(OUT)/tests/test-xlibint-link \
$(OUT)/tests/test-xtest
# The GLX tests only exist when the optional GLX layer is built (GLX=1).
# test-glx-link covers the no-provider degrade path; test-glx-provider drives the
Expand Down Expand Up @@ -238,6 +239,25 @@ $(OUT)/tests/test-glx-init-fail: tests/test-glx-init-fail.c $(TARGET) $(FAKE_EGL
$(Q)$(CC) $(CPPFLAGS) -DFAKE_EGL_PATH=\"$(abspath $(FAKE_EGL_LIB))\" \
$(FP_CFLAGS) $(CFLAGS_EXTRA) $< $(TARGET) $(LDLIBS) $(TEST_LDFLAGS) -o $@

# check and test-xtest are whitebox tests: they call core internals directly.
# Linking them against the fat test twin (libX11-compat-test.so) instead of the
# pinned .so keeps those ~50 internals out of the shipped library's export list.
# The twin, not the bare objects, because on Linux the whitebox binary shares a
# process with the system libX11.so.6 that SDL2 loads; only a -Bsymbolic shared
# library (which an executable cannot be) keeps our lock/event globals from being
# interposed by it. Everything else links the pinned .so via the rule below.
#
# The twin only exists on the native .so build; under WASM=1 X11_TEST_LIB is
# empty, so fall back to $(TARGET), which is the full-symbol static archive
# there (no export pinning, no system libX11 to interpose) exactly as the
# generic rule linked these before this change.
X11_WHITEBOX_LIB := $(if $(X11_TEST_LIB),$(X11_TEST_LIB),$(TARGET))
$(OUT)/tests/check $(OUT)/tests/test-xtest: $(OUT)/tests/%: tests/%.c $(X11_WHITEBOX_LIB)
@mkdir -p $(dir $@)
@echo " CC $<"
$(Q)$(CC) $(CPPFLAGS) $(FP_CFLAGS) $(CFLAGS_EXTRA) $< $(X11_WHITEBOX_LIB) \
$(LDLIBS) $(TEST_LDFLAGS) -o $@

$(OUT)/tests/%: tests/%.c $(TARGET)
@mkdir -p $(dir $@)
@echo " CC $<"
Expand Down
14 changes: 13 additions & 1 deletion mk/xcompat-libs.mk
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,21 @@ $(SM_COMPAT_TARGET): $(OUT)/sm-compat.o $(ICE_COMPAT_TARGET) | $(OUT)
$(Q)$(CC) $(LDFLAGS) $(SM_COMPAT_LDFLAGS) -shared -o $@ $< \
-L$(OUT) -lICE-compat

# -Wl,--no-undefined makes a missing core helper (one src/xft.c calls but that is
# absent from tests/private-symbols.txt) fail this link loudly on Linux, matching
# the macOS two-level namespace which already rejects it. Every symbol xft-compat.o
# references resolves from -lX11-compat + $(LDLIBS) (SDL, SDL_ttf, pixman, libc),
# so this only tightens error reporting, it does not change what links. macOS ld64
# spells the same guard -Wl,-undefined,error, which is already its default.
#
# Dropped under a sanitizer build: -fsanitize leaves the __asan_*/__ubsan_*
# runtime symbols undefined in the .so (resolved from the executable at load
# time), which --no-undefined would reject, breaking the ASan/UBSan/TSan jobs.
XFT_SANITIZED := $(findstring -fsanitize,$(CFLAGS_EXTRA) $(LDFLAGS))
XFT_COMPAT_NO_UNDEF := $(if $(filter Linux,$(UNAME_S)),$(if $(XFT_SANITIZED),,-Wl$(comma)--no-undefined))
$(XFT_COMPAT_TARGET): $(OUT)/xft-compat.o $(TARGET) | $(OUT)
@echo " LD $@"
$(Q)$(CC) $(LDFLAGS) $(XFT_COMPAT_LDFLAGS) -shared -o $@ $< \
$(Q)$(CC) $(LDFLAGS) $(XFT_COMPAT_LDFLAGS) $(XFT_COMPAT_NO_UNDEF) -shared -o $@ $< \
-L$(OUT) -lX11-compat $(LDLIBS)

.PHONY: xext xmu xinerama ice sm xft
Expand Down
77 changes: 77 additions & 0 deletions scripts/gen-export-list.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/bin/sh

# Emit the linker export list that pins libX11-compat's exported surface to its
# intended API. Everything else (internal helpers, the duplicated Xft/Fc copy)
# is hidden, which also lets the linker dead-strip code no exported symbol
# reaches. The symbol set is the union of the manifests already enforced by
# tests/check-api-symbols.py plus tests/private-symbols.txt (the core->libXft
# private contract) and tests/whitebox-symbols.txt (the whitebox test surface),
# so the manifests stay the single source of truth.
#
# The union is intersected with <defined-syms>, the symbols the core objects
# actually define, so the list never names a symbol absent from this build. That
# matters because a manifest carries symbols that only exist on one platform or
# feature build (the libx11Compat* shims are macOS-only; glX* drop when GLX=0):
# a stray name is a hard error under ld64 and under lld's --no-undefined-version
# default, and a silent no-op only under GNU ld. Pinning to the defined set
# keeps every linker happy without per-platform manifests.
#
# Usage: gen-export-list.sh <elf|macho> <glx:0|1> <defined-syms> <manifest>...
set -eu

# comm below needs both inputs collated identically to the sort that produced
# them; pin C collation everywhere so the intersection is deterministic
# regardless of the caller's LC_* (a UTF-8 locale orders _/case differently).
export LC_ALL=C

format=$1
glx=$2
defined=$3
shift 3

# Read every manifest in one checked step: a missing or unreadable file must
# abort the build, not silently yield an empty (API-omitting) map. A sed failure
# propagates through this assignment under set -e; the later grep -v / sort only
# exit non-zero on the harmless all-blank case.
manifest_lines=$(sed -e 's/#.*//' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' "$@")
syms=$(printf '%s\n' "$manifest_lines" | grep -v '^$' | sort -u)

# grep here reads a pipe, so it can only exit non-zero by matching nothing (a
# legal empty filter, e.g. GLX=0 against a glX-only set): tolerate that.
if [ "$glx" != "1" ]; then
syms=$(printf '%s\n' "$syms" | grep -v '^glX' || true)
fi

# Keep only symbols this build actually defines. comm reads $defined, so a read
# error there is real and must fail the build; comm already returns 0 for an
# empty intersection, so no explicit fallback is needed for the legitimate empty
# case.
syms=$(printf '%s\n' "$syms" | comm -12 - "$defined")

# Always export the libX11 underscore ABI the core defines (_Xdebug,
# _XrmInternalStringToQuark, ...). Real libX11 exports these _X* globals, and
# legacy clients link against them directly (violawww's libIMG references
# _Xdebug); the manifests only enumerate the X[A-Z]* public names, so without
# this the underscore ABI would be hidden and those clients fail to link. Drawn
# from $defined, so every entry is guaranteed present in this build.
abi=$(grep -E '^_X' "$defined" || true)
syms=$(printf '%s\n%s\n' "$syms" "$abi" | grep -v '^$' | sort -u)

case "$format" in
macho)

# Mach-O -exported_symbols_list: one C symbol per line, leading
# underscore.
printf '%s\n' "$syms" | grep -v '^$' | sed 's/^/_/'
;;
elf)
# ELF version script: named globals, everything else local (hidden).
printf '{\n global:\n'
printf '%s\n' "$syms" | grep -v '^$' | sed 's/^/ /; s/$/;/'
printf ' local:\n *;\n};\n'
;;
*)
echo "gen-export-list.sh: unknown format '$format'" >&2
exit 2
;;
esac
9 changes: 6 additions & 3 deletions src/atoms.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ static Bool predefinedAtomMatchesName(const char *predefinedName,
{
if (strcmp(predefinedName, name) == 0)
return True;

/* The predefined list stores the C identifier (e.g. "XA_PRIMARY"); the X11
* atom name strips the "XA_" prefix.
*/
return strncmp(predefinedName, "XA_", 3) == 0 &&
strcmp(&predefinedName[3], name) == 0;
}

AtomStruct *getAtomStruct(Atom atom)
static AtomStruct *getAtomStruct(Atom atom)
{
AtomStruct *atomStruct = atomStorageStart;
while (atomStruct) {
Expand All @@ -35,7 +36,7 @@ AtomStruct *getAtomStruct(Atom atom)
return NULL;
}

AtomStruct *getAtomStructByName(const char *name)
static AtomStruct *getAtomStructByName(const char *name)
{
size_t i;
for (i = 0; i < PREDEFINED_ATOM_LIST_SIZE; i++) {
Expand Down Expand Up @@ -117,7 +118,9 @@ Status XGetAtomNames(Display *dpy, Atom *atoms, int count, char **names_return)
return returned_names == count ? 1 : 0;
}

Atom _internAtom(const char *atomName, Bool only_if_exists, Bool *outOfMemory)
static Atom _internAtom(const char *atomName,
Bool only_if_exists,
Bool *outOfMemory)
{
if (outOfMemory)
*outOfMemory = False;
Expand Down
14 changes: 3 additions & 11 deletions src/colors.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,6 @@ SDL_Color uLongToColor(XcPixelFormat pixelFormat, unsigned long color)
return res;
}

SDL_Color uLongToColorFromVisual(Visual *visual, unsigned long color)
{
SDL_Color res;
res.r = (visual->red_mask & color) >> 24;
res.g = (visual->green_mask & color) >> 16;
res.b = (visual->blue_mask & color) >> 8;
res.a =
(~(visual->red_mask | visual->green_mask | visual->blue_mask)) & color;
return res;
}

int XFreeColormap(Display *display, Colormap colormap)
{
// https://tronche.com/gui/x/xlib/color/XFreeColormap.html
Expand Down Expand Up @@ -258,6 +247,7 @@ static Bool parseRgbComponent(const char **cursor, unsigned short *value)
unsigned int raw = 0;
for (int i = 0; i < digits; i++)
raw = (raw << 4) | (unsigned int) hexValue(start[i]);

/* X11 rgb: components scale a k-digit value to 16 bits by bit replication,
* so rgb:f/f/f is full intensity (0xffff), not 0xf000.
*/
Expand Down Expand Up @@ -351,6 +341,7 @@ int XFreeColors(Display *display,
// https://tronche.com/gui/x/xlib/color/XFreeColors.html
SET_X_SERVER_REQUEST(display, X_FreeColors);
TYPE_CHECK(colormap, COLORMAP, display, 0);

/* Direct-color visual: pixels are not allocated entries, so nothing to
* release.
*/
Expand All @@ -367,6 +358,7 @@ Status XAllocColor(Display *display, Colormap colormap, XColor *screen_in_out)
TYPE_CHECK(colormap, COLORMAP, display, 0);
if (!screen_in_out)
return 0;

/* Spec: on success, .pixel is filled with the allocated index and the
* .red/.green/.blue fields with the actually rendered values (which may
* differ from the requested ones on indexed visuals). The compat layer's
Expand Down
Loading
Loading