all: i3 subdirs
-i3: src/cfgparse.y.o src/cfgparse.yy.o src/cmdparse.y.o src/cmdparse.yy.o ${FILES}
- echo "LINK i3"
- $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+i3: libi3/libi3.a src/cfgparse.y.o src/cfgparse.yy.o src/cmdparse.y.o src/cmdparse.yy.o ${FILES}
+ echo "[i3] LINK i3"
+ $(CC) $(LDFLAGS) -o $@ $(filter-out libi3/libi3.a,$^) $(LIBS)
+
+libi3/%.a:
+ $(MAKE) -C libi3
subdirs:
for dir in $(SUBDIRS); do \
clean:
rm -f src/*.o src/*.gcno src/cfgparse.tab.{c,h} src/cfgparse.yy.c src/cfgparse.{output,dot} src/cmdparse.tab.{c,h} src/cmdparse.yy.c src/cmdparse.{output,dot} loglevels.tmp include/loglevels.h
(which lcov >/dev/null 2>&1 && lcov -d . --zerocounters) || true
+ $(MAKE) -C libi3 clean
$(MAKE) -C docs clean
$(MAKE) -C man clean
for dir in $(SUBDIRS); do \
endif
LIBS += -lm
+LIBS += -L $(TOPDIR)/libi3 -li3
LIBS += $(call ldflags_for_lib, xcb-event, xcb-event)
LIBS += $(call ldflags_for_lib, xcb-keysyms, xcb-keysyms)
ifeq ($(shell pkg-config --exists xcb-util || echo 1),1)
--- /dev/null
+# Default value so one can compile i3-msg standalone
+TOPDIR=..
+
+include $(TOPDIR)/common.mk
+
+CFLAGS += -I$(TOPDIR)/include
+
+# Depend on the object files of all source-files in src/*.c and on all header files
+FILES=$(patsubst %.c,%.o,$(wildcard *.c))
+HEADERS=$(wildcard *.h)
+
+# Depend on the specific file (.c for each .o) and on all headers
+%.o: %.c ${HEADERS}
+ echo "[libi3] CC $<"
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+all: libi3.a
+
+libi3.a: ${FILES}
+ echo "[libi3] AR libi3.a"
+ ar rcs libi3.a ${FILES}
+
+clean:
+ rm -f *.o libi3.a
+
+distclean: clean
--- /dev/null
+Introduction
+============
+
+libi3 is an *INTERNAL* library which contains functions that i3 and related
+tools (i3-msg, i3-input, i3-nagbar, i3-config-wizard, i3bar) use.
+
+It is NOT to be used by other programs.
+
+Structure
+=========
+
+Every function gets its own .c file, which in turn gets compiled into an .o
+object file. Afterwards, all .o files are archived into one static library
+(libi3.a). This library will be linked into all i3 binaries. The linker is able
+to eliminate unused .o files when linking, so only the functions which you
+actually use will be included in the corresponding binary.
--- /dev/null
+/*
+ * vim:ts=4:sw=4:expandtab
+ *
+ * i3 - an improved dynamic tiling window manager
+ *
+ * © 2009-2011 Michael Stapelberg and contributors
+ *
+ * See file LICENSE for license information.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <limits.h>
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+/*
+ * Try to get the socket path from X11 and return NULL if it doesn’t work.
+ *
+ * The memory for the socket path is dynamically allocated and has to be
+ * free()d by the caller.
+ *
+ */
+char *socket_path_from_x11() {
+ xcb_connection_t *conn;
+ xcb_intern_atom_cookie_t atom_cookie;
+ xcb_intern_atom_reply_t *atom_reply;
+ int screen;
+ char *socket_path;
+
+ if ((conn = xcb_connect(NULL, &screen)) == NULL ||
+ xcb_connection_has_error(conn))
+ return NULL;
+
+ atom_cookie = xcb_intern_atom(conn, 0, strlen("I3_SOCKET_PATH"), "I3_SOCKET_PATH");
+
+ xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screen);
+ xcb_window_t root = root_screen->root;
+
+ atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL);
+ if (atom_reply == NULL)
+ return NULL;
+
+ xcb_get_property_cookie_t prop_cookie;
+ xcb_get_property_reply_t *prop_reply;
+ prop_cookie = xcb_get_property_unchecked(conn, false, root, atom_reply->atom,
+ XCB_GET_PROPERTY_TYPE_ANY, 0, PATH_MAX);
+ prop_reply = xcb_get_property_reply(conn, prop_cookie, NULL);
+ if (prop_reply == NULL || xcb_get_property_value_length(prop_reply) == 0)
+ return NULL;
+ if (asprintf(&socket_path, "%.*s", xcb_get_property_value_length(prop_reply),
+ (char*)xcb_get_property_value(prop_reply)) == -1)
+ return NULL;
+ xcb_disconnect(conn);
+ return socket_path;
+}
+