diff --git a/Makefile b/Makefile index 4289eb4d..fedd6ec3 100644 --- a/Makefile +++ b/Makefile @@ -18,18 +18,21 @@ else UNUSED:=$(shell $(MAKE) loglevels.h) endif -SUBDIRS=i3-msg i3-input i3-nagbar i3-config-wizard i3bar +SUBDIRS:=i3-msg i3-input i3-nagbar i3-config-wizard i3bar # Depend on the specific file (.c for each .o) and on all headers src/%.o: src/%.c ${HEADERS} - echo "CC $<" + echo "[i3] CC $<" $(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="((uint64_t)1 << $(shell awk '/$(shell basename $< .c)/ { print NR; exit 0; }' loglevels.tmp))" -c -o $@ $< 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 \ @@ -39,7 +42,7 @@ subdirs: done loglevels.h: - echo "LOGLEVELS" + echo "[i3] LOGLEVELS" for file in $$(ls src/*.c src/*.y src/*.l | grep -v 'cfgparse.\(tab\|yy\).c'); \ do \ echo $$(basename $$file .c); \ @@ -51,29 +54,29 @@ loglevels.h: echo "};") > include/loglevels.h; src/cfgparse.yy.o: src/cfgparse.l src/cfgparse.y.o ${HEADERS} - echo "LEX $<" + echo "[i3] LEX $<" flex -i -o$(@:.o=.c) $< $(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="(1 << $(shell awk '/cfgparse.l/ { print NR }' loglevels.tmp))" -c -o $@ $(@:.o=.c) src/cmdparse.yy.o: src/cmdparse.l src/cmdparse.y.o ${HEADERS} - echo "LEX $<" + echo "[i3] LEX $<" flex -Pcmdyy -i -o$(@:.o=.c) $< $(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="(1 << $(shell awk '/cmdparse.l/ { print NR }' loglevels.tmp))" -c -o $@ $(@:.o=.c) src/cfgparse.y.o: src/cfgparse.y ${HEADERS} - echo "YACC $<" + echo "[i3] YACC $<" bison --debug --verbose -b $(basename $< .y) -d $< $(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="(1 << $(shell awk '/cfgparse.y/ { print NR }' loglevels.tmp))" -c -o $@ $(<:.y=.tab.c) src/cmdparse.y.o: src/cmdparse.y ${HEADERS} - echo "YACC $<" + echo "[i3] YACC $<" bison -p cmdyy --debug --verbose -b $(basename $< .y) -d $< $(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="(1 << $(shell awk '/cmdparse.y/ { print NR }' loglevels.tmp))" -c -o $@ $(<:.y=.tab.c) install: all - echo "INSTALL" + echo "[i3] INSTALL" $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin $(INSTALL) -d -m 0755 $(DESTDIR)$(SYSCONFDIR)/i3 $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/include/i3 @@ -120,6 +123,7 @@ dist: distclean 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 \ diff --git a/common.mk b/common.mk index b8ceea3b..53094fb3 100644 --- a/common.mk +++ b/common.mk @@ -58,6 +58,7 @@ CPPFLAGS += -DPCRE_HAS_UCP=1 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) diff --git a/i3-config-wizard/Makefile b/i3-config-wizard/Makefile index 43c3a1ff..1a9638ec 100644 --- a/i3-config-wizard/Makefile +++ b/i3-config-wizard/Makefile @@ -10,28 +10,28 @@ HEADERS:=$(wildcard *.h) # Depend on the specific file (.c for each .o) and on all headers %.o: %.c ${HEADERS} - echo "CC $<" + echo "[i3-config-wizard] CC $<" $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< all: i3-config-wizard i3-config-wizard: cfgparse.y.o cfgparse.yy.o ${FILES} - echo "LINK i3-config-wizard" + echo "[i3-config-wizard] LINK i3-config-wizard" $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) cfgparse.yy.o: cfgparse.l cfgparse.y.o ${HEADERS} - echo "LEX $<" + echo "[i3-config-wizard] LEX $<" flex -i -o$(@:.o=.c) $< $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(@:.o=.c) cfgparse.y.o: cfgparse.y ${HEADERS} - echo "YACC $<" + echo "[i3-config-wizard] YACC $<" bison --debug --verbose -b $(basename $< .y) -d $< $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(<:.y=.tab.c) install: all - echo "INSTALL" + echo "[i3-config-wizard] INSTALL" $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin $(INSTALL) -m 0755 i3-config-wizard $(DESTDIR)$(PREFIX)/bin/ diff --git a/i3-input/Makefile b/i3-input/Makefile index 45653dad..5929b4c4 100644 --- a/i3-input/Makefile +++ b/i3-input/Makefile @@ -9,17 +9,17 @@ HEADERS=$(wildcard *.h) # Depend on the specific file (.c for each .o) and on all headers %.o: %.c ${HEADERS} - echo "CC $<" + echo "[i3-input] CC $<" $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< all: i3-input i3-input: ${FILES} - echo "LINK i3-input" + echo "[i3-input] LINK i3-input" $(CC) $(LDFLAGS) -o $@ ${FILES} $(LIBS) install: all - echo "INSTALL" + echo "[i3-input] INSTALL" $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin $(INSTALL) -m 0755 i3-input $(DESTDIR)$(PREFIX)/bin/ diff --git a/i3-msg/Makefile b/i3-msg/Makefile index 1b7c1c04..617df932 100644 --- a/i3-msg/Makefile +++ b/i3-msg/Makefile @@ -11,17 +11,17 @@ HEADERS=$(wildcard *.h) # Depend on the specific file (.c for each .o) and on all headers %.o: %.c ${HEADERS} - echo "CC $<" + echo "[i3-msg] CC $<" $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< all: i3-msg i3-msg: ${FILES} - echo "LINK i3-msg" + echo "[i3-msg] LINK i3-msg" $(CC) $(LDFLAGS) -o i3-msg ${FILES} $(LIBS) install: all - echo "INSTALL" + echo "[i3-msg] INSTALL" $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin $(INSTALL) -m 0755 i3-msg $(DESTDIR)$(PREFIX)/bin/ diff --git a/i3-msg/main.c b/i3-msg/main.c index 2d7cef0e..124663d6 100644 --- a/i3-msg/main.c +++ b/i3-msg/main.c @@ -32,46 +32,11 @@ #include #include +#include "libi3.h" #include static char *socket_path; -/* - * Try to get the socket path from X11 and return NULL if it doesn’t work. - * As i3-msg is a short-running tool, we don’t bother with cleaning up the - * connection and leave it up to the operating system on exit. - * - */ -static char *socket_path_from_x11() { - xcb_connection_t *conn; - int screen; - if ((conn = xcb_connect(NULL, &screen)) == NULL || - xcb_connection_has_error(conn)) - return NULL; - xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screen); - xcb_window_t root = root_screen->root; - - xcb_intern_atom_cookie_t atom_cookie; - xcb_intern_atom_reply_t *atom_reply; - - atom_cookie = xcb_intern_atom(conn, 0, strlen("I3_SOCKET_PATH"), "I3_SOCKET_PATH"); - 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; - return socket_path; -} - /* * Formats a message (payload) of the given size and type and sends it to i3 via * the given socket file descriptor. diff --git a/i3-nagbar/Makefile b/i3-nagbar/Makefile index 933ae76c..fed223db 100644 --- a/i3-nagbar/Makefile +++ b/i3-nagbar/Makefile @@ -9,17 +9,17 @@ HEADERS=$(wildcard *.h) # Depend on the specific file (.c for each .o) and on all headers %.o: %.c ${HEADERS} - echo "CC $<" + echo "[i3-nagbar] CC $<" $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< all: i3-nagbar i3-nagbar: ${FILES} - echo "LINK i3-nagbar" + echo "[i3-nagbar] LINK i3-nagbar" $(CC) $(LDFLAGS) -o $@ ${FILES} $(LIBS) install: all - echo "INSTALL" + echo "[i3-nagbar] INSTALL" $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin $(INSTALL) -m 0755 i3-nagbar $(DESTDIR)$(PREFIX)/bin/ diff --git a/include/all.h b/include/all.h index 9c08ebef..38cda89c 100644 --- a/include/all.h +++ b/include/all.h @@ -65,5 +65,6 @@ #include "ewmh.h" #include "assignments.h" #include "regex.h" +#include "libi3.h" #endif diff --git a/libi3/Makefile b/libi3/Makefile new file mode 100644 index 00000000..e9efcf7b --- /dev/null +++ b/libi3/Makefile @@ -0,0 +1,26 @@ +# 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 diff --git a/libi3/README b/libi3/README new file mode 100644 index 00000000..740ef22e --- /dev/null +++ b/libi3/README @@ -0,0 +1,16 @@ +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. diff --git a/libi3/get_socket_path.c b/libi3/get_socket_path.c new file mode 100644 index 00000000..9e02ec51 --- /dev/null +++ b/libi3/get_socket_path.c @@ -0,0 +1,59 @@ +/* + * 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 +#include +#include +#include + +#include +#include + +/* + * 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; +} + diff --git a/src/main.c b/src/main.c index cc60d69c..19c45681 100644 --- a/src/main.c +++ b/src/main.c @@ -172,7 +172,6 @@ static void i3_exit() { } int main(int argc, char *argv[]) { - //parse_cmd("[ foo ] attach, attach ; focus"); int screens; char *override_configpath = NULL; bool autostart = true; @@ -190,6 +189,7 @@ int main(int argc, char *argv[]) { {"restart", required_argument, 0, 0}, {"force-xinerama", no_argument, 0, 0}, {"disable-signalhandler", no_argument, 0, 0}, + {"get-socketpath", no_argument, 0, 0}, {0, 0, 0, 0} }; int option_index = 0, opt; @@ -248,6 +248,14 @@ int main(int argc, char *argv[]) { } else if (strcmp(long_options[option_index].name, "disable-signalhandler") == 0) { disable_signalhandler = true; break; + } else if (strcmp(long_options[option_index].name, "get-socketpath") == 0) { + char *socket_path = socket_path_from_x11(); + if (socket_path) { + printf("%s\n", socket_path); + return 0; + } + + return 1; } else if (strcmp(long_options[option_index].name, "restart") == 0) { FREE(layout_path); layout_path = sstrdup(optarg);