├── .gitignore ├── images ├── tree.png ├── fullscreen.png ├── gprof_1hr.png ├── gprof_short.png ├── theme-ryan.png ├── theme-default.png ├── theme-islands.png ├── theme-minimal.png ├── theme-pastels.png ├── theme-xstatbar.png └── theme-islands-colorful.png ├── gui ├── Makefile.in ├── chart.t.cc ├── chart.d.c ├── Makefile ├── xdraw.d.c ├── gui.h ├── chart.c ├── chart.h ├── xcore.h ├── xdraw.h ├── gui.c ├── xcore.d.c ├── xcore.t.cc └── xdraw.c ├── widgets ├── Makefile.in ├── Makefile ├── cpushort.h ├── cpuslong.h ├── wifi.h ├── nprocs.h ├── time.h ├── bright.h ├── volume.h ├── util.h ├── battery.h ├── nprocs.c ├── wifi.c ├── time.c ├── cpushort.c ├── bright.c ├── memory.h ├── net.h ├── cpus.h ├── battery.c ├── util.c ├── volume.c ├── cpuslong.c ├── memory.c ├── net.c └── cpus.c ├── stats ├── Makefile.in ├── Makefile ├── util.h ├── volume.h ├── nprocs.h ├── wifi.h ├── brightness.h ├── battery.h ├── memory.h ├── nprocs.d.c ├── brightness.d.c ├── nprocs.c ├── wifi.d.c ├── net.h ├── volume.d.c ├── stats.h ├── cpu.h ├── battery.d.c ├── net.d.c ├── memory.d.c ├── cpu.d.c ├── stats.c ├── README.md ├── util.c ├── battery.c ├── wifi.c ├── memory.c ├── cpu.c ├── volume.c ├── brightness.c └── net.c ├── man └── Makefile ├── TODO ├── LICENSE ├── widgets.h ├── settings.h ├── testruns.sh ├── screenshots.sh ├── CONTRIBUTING.md ├── Makefile ├── README.md ├── oxbar.c ├── sample.oxbar.conf ├── loc └── widgets.c /.gitignore: -------------------------------------------------------------------------------- 1 | oxbar 2 | *.d 3 | *.t 4 | *.o 5 | *.swp 6 | gmon.out 7 | gprof.analysis 8 | -------------------------------------------------------------------------------- /images/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/tree.png -------------------------------------------------------------------------------- /images/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/fullscreen.png -------------------------------------------------------------------------------- /images/gprof_1hr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/gprof_1hr.png -------------------------------------------------------------------------------- /images/gprof_short.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/gprof_short.png -------------------------------------------------------------------------------- /images/theme-ryan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/theme-ryan.png -------------------------------------------------------------------------------- /images/theme-default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/theme-default.png -------------------------------------------------------------------------------- /images/theme-islands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/theme-islands.png -------------------------------------------------------------------------------- /images/theme-minimal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/theme-minimal.png -------------------------------------------------------------------------------- /images/theme-pastels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/theme-pastels.png -------------------------------------------------------------------------------- /images/theme-xstatbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/theme-xstatbar.png -------------------------------------------------------------------------------- /images/theme-islands-colorful.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanflannery/oxbar/HEAD/images/theme-islands-colorful.png -------------------------------------------------------------------------------- /gui/Makefile.in: -------------------------------------------------------------------------------- 1 | # all object files local to this subdir 2 | GUI_OBJS = \ 3 | chart.o \ 4 | gui.o \ 5 | xdraw.o \ 6 | xcore.o 7 | 8 | # all test drivers local to this subdir 9 | GUI_DRIVERS = \ 10 | chart.d \ 11 | xdraw.d \ 12 | xcore.d 13 | -------------------------------------------------------------------------------- /widgets/Makefile.in: -------------------------------------------------------------------------------- 1 | # all object files local to this subdir 2 | WIDGET_OBJS = \ 3 | battery.o \ 4 | bright.o \ 5 | cpus.o \ 6 | cpuslong.o \ 7 | cpushort.o \ 8 | net.o \ 9 | nprocs.o \ 10 | memory.o \ 11 | time.o \ 12 | util.o \ 13 | volume.o \ 14 | wifi.o 15 | -------------------------------------------------------------------------------- /stats/Makefile.in: -------------------------------------------------------------------------------- 1 | # all object files local to this subdir 2 | STATS_OBJS = \ 3 | battery.o \ 4 | brightness.o \ 5 | cpu.o \ 6 | memory.o \ 7 | net.o \ 8 | nprocs.o \ 9 | volume.o \ 10 | wifi.o \ 11 | util.o \ 12 | stats.o 13 | 14 | # all test drivers local to this subdir 15 | STATS_DRIVERS = \ 16 | battery.d \ 17 | brightness.d \ 18 | cpu.d \ 19 | memory.d \ 20 | net.d \ 21 | nprocs.d \ 22 | volume.d \ 23 | wifi.d 24 | -------------------------------------------------------------------------------- /man/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | MANDIR ?= $(PREFIX)/man/man1 3 | 4 | MAN_PAGES = oxbar.1 5 | 6 | .PHONY: lint test 7 | 8 | .DEFAULT: 9 | @echo Nothing to do here 10 | 11 | all: oxbar.html 12 | 13 | oxbar.html: oxbar.1 14 | mandoc -T html -O toc oxbar.1 > $@ 15 | 16 | lint: 17 | mandoc -Tlint $(MAN_PAGES) 18 | 19 | test: 20 | mandoc oxbar.1 | less 21 | 22 | install: 23 | install -m 0444 $(MAN_PAGES) $(MANDIR) 24 | 25 | uninstall: 26 | cd $(MANDIR) 27 | rm -f $(MAN_PAGES) 28 | -------------------------------------------------------------------------------- /widgets/Makefile: -------------------------------------------------------------------------------- 1 | # build flags 2 | CFLAGS += -c -std=c89 -Wall -Wextra -Werror -O2 3 | CFLAGS += `pkg-config --cflags pangocairo` 4 | LDFLAGS += -L/usr/X11R6/lib -lxcb -lxcb-icccm 5 | LDFLAGS += `pkg-config --libs pangocairo` 6 | 7 | # all inputs defined here 8 | .include "Makefile.in" 9 | 10 | .PHONY: all clean objects 11 | .DEFAULT: all 12 | 13 | all: $(WIDGET_OBJS) 14 | objects: $(WIDGET_OBJS) 15 | 16 | .c.o: 17 | $(CC) $(CFLAGS) $< 18 | 19 | clean: 20 | rm -f $(WIDGET_OBJS) 21 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | gui/xcore.c:232: * TODO cleanup & separate wm hints ... and dragons 2 | gui/xdraw.h:40: * TODO This abstraction should also permit vertical rendering (for a vertical 3 | gui/xcore.t.cc:9:/* TODO either fix googletest's [ASSERT|EXPECT]_EXIT* on openbsd or switch */ 4 | oxbar.c:19: * TODO allow configuration of interfaces used by net & wifi collectors 5 | oxbar.c:20: * TODO polish error messages (err/errx calls) 6 | oxbar.c:21: * TODO make window FLOAT & ALWAYS-ON-TOP properties set-able 7 | settings.c:330: * TODO Create a settings_free() (or refactor to make easier) 8 | stats/net.c:83: * TODO Refactor network bytes logic below 9 | -------------------------------------------------------------------------------- /stats/Makefile: -------------------------------------------------------------------------------- 1 | # build flags 2 | CFLAGS += -c -std=c89 -Wall -Wextra -Werror -O2 -I/usr/X11R6/include 3 | LDFLAGS += -lm -L/usr/X11R6/lib -lxcb -lxcb-randr 4 | 5 | # all objects + drivers defined here 6 | .include "Makefile.in" 7 | 8 | .PHONY: all clean objects drivers 9 | .DEFAULT: all 10 | 11 | all: $(STATS_OBJS) $(STATS_DRIVERS) 12 | objects: $(STATS_OBJS) 13 | drivers: $(STATS_DRIVERS) 14 | 15 | .c.o: 16 | $(CC) $(CFLAGS) $< 17 | 18 | .for driv in $(STATS_DRIVERS) 19 | ${driv}: ${driv}.o ${driv:R}.o 20 | $(CC) -o $@ $(LDFLAGS) ${driv}.o ${driv:R}.o util.o 21 | .endfor 22 | 23 | clean: 24 | rm -f $(STATS_OBJS) 25 | rm -f $(STATS_DRIVERS) 26 | rm -f *.d.o 27 | rm -f *.core 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Ryan Flannery 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /stats/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef STATS_UTIL_H 18 | #define STATS_UTIL_H 19 | 20 | char* get_egress(); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /gui/chart.t.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | extern "C" { 6 | #include "chart.h" 7 | }; 8 | 9 | 10 | TEST(chart, InitZeroSeries_ShouldFail) 11 | { 12 | ASSERT_EXIT(chart_init(0, 20, true, "", (const char*[]){ (const char*)"" }), 13 | ::testing::ExitedWithCode(1), ""); 14 | } 15 | 16 | TEST(chart, InitZeroSamples_ShouldFail) 17 | { 18 | ASSERT_EXIT(chart_init(20, 0, true, "", (const char*[]){ (const char*)"" }), 19 | ::testing::ExitedWithCode(1), ""); 20 | } 21 | 22 | TEST(chart, InitWithNullBgcolor_ShouldFail) 23 | { 24 | ASSERT_EXIT(chart_init(1, 10, true, NULL, (const char*[]){ (const char*)"" }), 25 | ::testing::ExitedWithCode(1), ""); 26 | } 27 | 28 | TEST(chart, InitWithNullColorArray_ShouldFail) 29 | { 30 | ASSERT_EXIT(chart_init(1, 10, true, "", NULL), 31 | ::testing::ExitedWithCode(1), ""); 32 | } 33 | 34 | TEST(chart, InitFree_ShouldSucceed) 35 | { 36 | struct chart *c = chart_init(10, 1, true, "#444", 37 | (const char *[]){ (const char*)"#f00" }); 38 | chart_free(c); 39 | } 40 | -------------------------------------------------------------------------------- /widgets/cpushort.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WCPUSHORT_H 18 | #define WCPUSHORT_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | bool wcpushort_enabled(void *wstate); 26 | void wcpushort_draw(void *wstate, struct xctx*); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /widgets/cpuslong.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WCPUSLONG_H 18 | #define WCPUSLONG_H 19 | 20 | #include 21 | 22 | #include "cpus.h" 23 | #include "../gui/xdraw.h" 24 | #include "../stats/stats.h" 25 | 26 | bool wcpulong_enabled(void *wstate); 27 | void wcpulong_draw(void *wstate, struct xctx*); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /stats/volume.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef VOLUME_H 18 | #define VOLUME_H 19 | 20 | #include 21 | 22 | struct volume_stats { 23 | bool is_setup; 24 | bool muted; 25 | float left, right; 26 | }; 27 | 28 | void volume_init(struct volume_stats*); 29 | void volume_update(struct volume_stats*); 30 | void volume_close(struct volume_stats*); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /stats/nprocs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef NPROCS_H 18 | #define NPROCS_H 19 | 20 | #include 21 | 22 | struct nprocs_stats { 23 | bool is_setup; 24 | int nprocs; /* total # of processes */ 25 | }; 26 | 27 | void nprocs_init(struct nprocs_stats*); 28 | void nprocs_update(struct nprocs_stats*); 29 | void nprocs_close(struct nprocs_stats*); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /widgets/wifi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WWIFI_H 18 | #define WWIFI_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | struct widget_wifi_settings { 26 | char *hdcolor; 27 | char *bgcolor; 28 | char *fgcolor; 29 | }; 30 | 31 | bool wwifi_enabled(void *wstate); 32 | void wwifi_draw(void *wstate, struct xctx*); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /widgets/nprocs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WNPROCS_H 18 | #define WNPROCS_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | struct widget_nprocs_settings { 26 | char *hdcolor; 27 | char *bgcolor; 28 | char *fgcolor; 29 | }; 30 | 31 | bool wnprocs_enabled(void *wstate); 32 | void wnprocs_draw(void *wstate, struct xctx*); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /widgets/time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WTIME_H 18 | #define WTIME_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | struct widget_time_settings { 26 | char *hdcolor; 27 | char *bgcolor; 28 | char *fgcolor; 29 | char *format; 30 | }; 31 | 32 | bool wtime_enabled(void *wstate); 33 | void wtime_draw(void *wstate, struct xctx*); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /stats/wifi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WIFI_H 18 | #define WIFI_H 19 | 20 | #include 21 | 22 | struct wifi_stats { 23 | bool is_setup; 24 | char *iface; /* network interface used */ 25 | float signal_strength; /* signal strength [0,100] */ 26 | }; 27 | 28 | void wifi_init(struct wifi_stats*); 29 | void wifi_update(struct wifi_stats*); 30 | void wifi_close(struct wifi_stats*); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /stats/brightness.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef BRIGHTNESS_H 18 | #define BRIGHTNESS_H 19 | 20 | #include 21 | 22 | struct brightness_stats { 23 | bool is_setup; 24 | float brightness; /* % brightness of the display from Xrandr(3) */ 25 | }; 26 | 27 | void brightness_init(struct brightness_stats*); 28 | void brightness_update(struct brightness_stats*); 29 | void brightness_close(struct brightness_stats*); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /widgets.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WIDGETS_H 18 | #define WIDGETS_H 19 | 20 | #include "settings.h" 21 | #include "gui/gui.h" 22 | #include "stats/stats.h" 23 | 24 | void widgets_init(struct gui *, struct settings *, struct oxstats *); 25 | void widgets_free(); 26 | 27 | void widget_set_hdcolor(const char * const, char **); 28 | void widget_set_bgcolor(const char * const, char **); 29 | void widget_set_fgcolor(const char * const, char **); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /widgets/bright.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WBRIGHT_H 18 | #define WBRIGHT_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | struct widget_bright_settings { 26 | char *hdcolor; 27 | char *bgcolor; 28 | char *fgcolor; 29 | int chart_width; 30 | char *chart_bgcolor; 31 | char *chart_pgcolor; 32 | }; 33 | 34 | bool wbright_enabled(void *wstate); 35 | void wbright_draw(void *wstate, struct xctx*); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /widgets/volume.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WVOLUME_H 18 | #define WVOLUME_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | struct widget_volume_settings { 26 | char *hdcolor; 27 | char *bgcolor; 28 | char *fgcolor; 29 | int chart_width; 30 | char *chart_bgcolor; 31 | char *chart_pgcolor; 32 | }; 33 | 34 | bool wvolume_enabled(void *wstate); 35 | void wvolume_draw(void *wstate, struct xctx*); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /widgets/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WUTIL_H 18 | #define WUTIL_H 19 | 20 | #include "../stats/stats.h" 21 | 22 | /* for widgets that have no local state (other than stats & settings hooks) */ 23 | struct generic_wstate { 24 | struct oxstats *stats; 25 | void *settings; 26 | }; 27 | void* generic_init(struct oxstats*, void *settings); 28 | void generic_free(void *wstate); 29 | 30 | /* a method to format memtory into a string */ 31 | const char *fmt_memory(const char*, int); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /widgets/battery.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WBATTERY_H 18 | #define WBATTERY_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | struct widget_battery_settings { 26 | char *hdcolor; 27 | char *bgcolor; 28 | char *fgcolor; 29 | char *fgcolor_unplugged; 30 | int chart_width; 31 | char *chart_bgcolor; 32 | char *chart_pgcolor; 33 | }; 34 | 35 | bool wbattery_enabled(void *wstate); 36 | void wbattery_draw(void *wstate, struct xctx*); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /widgets/nprocs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "util.h" 20 | #include "nprocs.h" 21 | 22 | bool 23 | wnprocs_enabled(void *wstate) 24 | { 25 | struct generic_wstate *w = wstate; 26 | return w->stats->nprocs.is_setup; 27 | } 28 | 29 | void 30 | wnprocs_draw(void *wstate, struct xctx *ctx) 31 | { 32 | struct generic_wstate *w = wstate; 33 | struct widget_nprocs_settings *settings = w->settings; 34 | 35 | xdraw_printf(ctx, settings->fgcolor, "#Procs: %d", 36 | w->stats->nprocs.nprocs); 37 | } 38 | -------------------------------------------------------------------------------- /widgets/wifi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "util.h" 20 | #include "wifi.h" 21 | 22 | bool 23 | wwifi_enabled(void *wstate) 24 | { 25 | struct generic_wstate *w = wstate; 26 | return w->stats->wifi.is_setup; 27 | } 28 | 29 | void 30 | wwifi_draw(void *wstate, struct xctx *ctx) 31 | { 32 | struct generic_wstate *w = wstate; 33 | struct widget_wifi_settings *settings = w->settings; 34 | xdraw_printf(ctx, 35 | settings->fgcolor, 36 | "Wifi:% 3.0f%%", 37 | w->stats->wifi.signal_strength); 38 | } 39 | -------------------------------------------------------------------------------- /stats/battery.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef BATTERY_H 18 | #define BATTERY_H 19 | 20 | #include 21 | 22 | struct battery_stats { 23 | bool is_setup; 24 | bool plugged_in; /* true: plugged in, false: using battery */ 25 | float charge_pct; /* percent battery charged */ 26 | int minutes_remaining; /* minutes remaining on battery charge */ 27 | }; 28 | 29 | void battery_init(struct battery_stats*); 30 | void battery_update(struct battery_stats*); 31 | void battery_close(struct battery_stats*); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /stats/memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef MEMORY_H 18 | #define MEMORY_H 19 | 20 | #include 21 | 22 | struct memory_stats { 23 | bool is_setup; 24 | 25 | /* raw values in kilobytes */ 26 | int active, total, free; /* "total" means same as in top(1) here */ 27 | int swap_used, swap_total; 28 | 29 | /* percentage values */ 30 | float active_pct, free_pct, total_pct; 31 | float swap_used_pct; 32 | }; 33 | 34 | void memory_init(struct memory_stats*); 35 | void memory_update(struct memory_stats*); 36 | void memory_close(struct memory_stats*); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /stats/nprocs.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "nprocs.h" 23 | 24 | volatile sig_atomic_t sig_stop = 0; 25 | void stop(int __attribute__((unused)) sig) { sig_stop = 1; } 26 | 27 | int 28 | main() 29 | { 30 | struct nprocs_stats s; 31 | signal(SIGINT, stop); 32 | 33 | nprocs_init(&s); 34 | if (!s.is_setup) 35 | errx(1, "failed to setup core!"); 36 | 37 | printf("%8s\n", "procs"); 38 | 39 | while (!sig_stop) { 40 | nprocs_update(&s); 41 | printf("%8d\n", s.nprocs); 42 | sleep(1); 43 | } 44 | 45 | nprocs_close(&s); 46 | } 47 | -------------------------------------------------------------------------------- /widgets/time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "util.h" 21 | #include "time.h" 22 | 23 | bool 24 | wtime_enabled(__attribute__((unused)) void *wstate) 25 | { 26 | return true; 27 | } 28 | 29 | void 30 | wtime_draw(void *wstate, struct xctx *ctx) 31 | { 32 | struct generic_wstate *w = wstate; 33 | struct widget_time_settings *settings = w->settings; 34 | #define GUI_TIME_MAXLEN 100 35 | static char buffer[GUI_TIME_MAXLEN]; 36 | 37 | time_t now = time(NULL); 38 | strftime(buffer, GUI_TIME_MAXLEN, settings->format, localtime(&now)); 39 | xdraw_printf(ctx, settings->fgcolor, buffer); 40 | } 41 | -------------------------------------------------------------------------------- /stats/brightness.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "brightness.h" 23 | 24 | volatile sig_atomic_t sig_stop = 0; 25 | void stop(int __attribute__((unused)) sig) { sig_stop = 1; } 26 | 27 | int 28 | main() 29 | { 30 | struct brightness_stats s; 31 | signal(SIGINT, stop); 32 | 33 | brightness_init(&s); 34 | if (!s.is_setup) 35 | errx(1, "failed to setup brightness!"); 36 | 37 | printf("bright%%\n"); 38 | 39 | while (!sig_stop) { 40 | brightness_update(&s); 41 | printf("%5.1f\n", s.brightness); 42 | sleep(1); 43 | } 44 | 45 | brightness_close(&s); 46 | } 47 | -------------------------------------------------------------------------------- /stats/nprocs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "nprocs.h" 24 | 25 | void 26 | nprocs_init(struct nprocs_stats *stats) 27 | { 28 | stats->is_setup = true; 29 | } 30 | 31 | void 32 | nprocs_update(struct nprocs_stats *stats) 33 | { 34 | static int mib[] = { CTL_KERN, KERN_NPROCS }; 35 | static size_t size = sizeof(stats->nprocs); 36 | 37 | if (-1 == sysctl(mib, 2, &stats->nprocs, &size, NULL, 0)) 38 | err(1, "KERN.NPROCS"); 39 | } 40 | 41 | void 42 | nprocs_close(__attribute__((unused)) struct nprocs_stats *stats) 43 | { 44 | /* nothing to do */ 45 | } 46 | -------------------------------------------------------------------------------- /stats/wifi.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "wifi.h" 23 | 24 | volatile sig_atomic_t sig_stop = 0; 25 | void stop(int __attribute__((unused)) sig) { sig_stop = 1; } 26 | 27 | int 28 | main() 29 | { 30 | struct wifi_stats s; 31 | signal(SIGINT, stop); 32 | 33 | wifi_init(&s); 34 | if (!s.is_setup) 35 | errx(1, "failed to setup wifi!"); 36 | 37 | printf("iface: '%s'\n\n", s.iface); 38 | printf("strength%%\n"); 39 | 40 | while (!sig_stop) { 41 | wifi_update(&s); 42 | printf("%4.1f%%\n", s.signal_strength); 43 | sleep(1); 44 | } 45 | 46 | wifi_close(&s); 47 | } 48 | -------------------------------------------------------------------------------- /stats/net.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef NET_H 18 | #define NET_H 19 | 20 | #include 21 | 22 | #include 23 | 24 | struct net_stats { 25 | bool is_setup; 26 | 27 | /* iface name (first in the 'egress' group) */ 28 | char *iface; 29 | 30 | /* raw packet & byte counters (these can rollover) */ 31 | u_long packets_in, packets_out; 32 | uint64_t bytes_in, bytes_out; 33 | 34 | /* diff since last update (handles rollover) */ 35 | u_long packets_in_new, packets_out_new; 36 | uint64_t bytes_in_new, bytes_out_new; 37 | }; 38 | 39 | void net_init(struct net_stats*); 40 | void net_update(struct net_stats*); 41 | void net_close(struct net_stats*); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /widgets/cpushort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "cpus.h" 20 | #include "cpushort.h" 21 | 22 | bool 23 | wcpushort_enabled(void *wstate) 24 | { 25 | struct widget_cpu_state *w = wstate; 26 | return w->stats->cpus.is_setup; 27 | } 28 | 29 | void 30 | wcpushort_draw(void *wstate, struct xctx *ctx) 31 | { 32 | struct widget_cpu_state *w = wstate; 33 | struct oxstats *stats = w->stats; 34 | int cpu; 35 | for (cpu = 0; cpu < stats->cpus.ncpu; cpu++) { 36 | xdraw_printf(ctx, 37 | w->settings->fgcolor, 38 | "CPU%d:% 3.0f%%", 39 | cpu, 40 | (100 - stats->cpus.cpus[cpu].percentages[CP_IDLE])); 41 | 42 | if (cpu != stats->cpus.ncpu - 1) 43 | xdraw_printf(ctx, "000000", " "); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /stats/volume.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "volume.h" 23 | 24 | volatile sig_atomic_t sig_stop = 0; 25 | void stop(int __attribute__((unused)) sig) { sig_stop = 1; } 26 | 27 | int 28 | main() 29 | { 30 | struct volume_stats s; 31 | signal(SIGINT, stop); 32 | 33 | volume_init(&s); 34 | if (!s.is_setup) 35 | errx(1, "failed to setup volume!"); 36 | 37 | printf("%8s\t%8s\t%8s\n", "mute?", "left", "right"); 38 | 39 | while (!sig_stop) { 40 | volume_update(&s); 41 | printf("%8s\t%8.1f\t%8.1f\n", 42 | s.muted ? "TRUE" : "false", 43 | s.left, 44 | s.right); 45 | sleep(1); 46 | } 47 | 48 | volume_close(&s); 49 | } 50 | -------------------------------------------------------------------------------- /stats/stats.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef STATS_H 18 | #define STATS_H 19 | 20 | #include "battery.h" 21 | #include "brightness.h" 22 | #include "cpu.h" 23 | #include "memory.h" 24 | #include "net.h" 25 | #include "nprocs.h" 26 | #include "volume.h" 27 | #include "wifi.h" 28 | 29 | struct oxstats { 30 | struct battery_stats battery; 31 | struct brightness_stats brightness; 32 | struct cpu_stats cpus; 33 | struct memory_stats memory; 34 | struct net_stats network; 35 | struct nprocs_stats nprocs; 36 | struct volume_stats volume; 37 | struct wifi_stats wifi; 38 | }; 39 | 40 | extern struct oxstats OXSTATS; 41 | 42 | void stats_init(); 43 | void stats_update(); 44 | void stats_close(); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /widgets/bright.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "util.h" 20 | #include "bright.h" 21 | 22 | bool 23 | wbright_enabled(void *wstate) 24 | { 25 | struct generic_wstate *w = wstate; 26 | return w->stats->brightness.is_setup; 27 | } 28 | 29 | void 30 | wbright_draw(void *wstate, struct xctx *ctx) 31 | { 32 | struct generic_wstate *w = wstate; 33 | struct widget_bright_settings *settings = w->settings; 34 | 35 | xdraw_printf(ctx, settings->fgcolor, "Bright:"); 36 | 37 | xdraw_progress_bar(ctx, 38 | settings->chart_bgcolor, 39 | settings->chart_pgcolor, 40 | settings->chart_width, 41 | w->stats->brightness.brightness); 42 | 43 | xdraw_printf(ctx, settings->fgcolor, 44 | "% 3.0f%%", w->stats->brightness.brightness); 45 | } 46 | -------------------------------------------------------------------------------- /stats/cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef CORE_H 18 | #define CORE_H 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | /* XXX see sys/sched.h for definition of CPUSTATES */ 26 | struct cpu_states { 27 | u_int64_t raw[CPUSTATES]; /* raw tick counters for each */ 28 | float percentages[CPUSTATES]; /* percent time spent in each */ 29 | }; 30 | 31 | struct cpu_stats { 32 | bool is_setup; 33 | int ncpu; /* number of CPUs available */ 34 | struct cpu_states *cpus; /* array of cpu states, one for each cpu */ 35 | }; 36 | 37 | void cpu_init(struct cpu_stats*); 38 | void cpu_update(struct cpu_stats*); 39 | void cpu_close(struct cpu_stats*); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /gui/chart.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /* 18 | * Test driver (system test) for chart.* component 19 | * Run by just: 20 | * ./chart.d 21 | */ 22 | #include 23 | #include 24 | #include 25 | #include "chart.h" 26 | 27 | int 28 | main() 29 | { 30 | const char *colors[] = { 31 | "#ff0000", 32 | "#00ff00", 33 | "#0000ff" 34 | }; 35 | 36 | struct chart *c; 37 | 38 | c = chart_init( 39 | 10, 3, /* 10 samples of 3 different series */ 40 | false, /* raw values (not percentages) */ 41 | "#555555", 42 | colors); 43 | 44 | double i = 1; 45 | while (1) { 46 | chart_update(c, (double[]){ i, i + 1, i + 2 }); 47 | i++; 48 | chart_print(c); 49 | sleep(1); 50 | } 51 | 52 | chart_free(c); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /stats/battery.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "battery.h" 23 | 24 | volatile sig_atomic_t sig_stop = 0; 25 | void stop(int __attribute__((unused)) sig) { sig_stop = 1; } 26 | 27 | int 28 | main() 29 | { 30 | struct battery_stats s; 31 | signal(SIGINT, stop); 32 | 33 | battery_init(&s); 34 | if (!s.is_setup) 35 | errx(1, "failed to setup battery!"); 36 | 37 | printf("%8s\t%8s\t%8s\n", "plugged?", "%", "minutes"); 38 | 39 | while (!sig_stop) { 40 | battery_update(&s); 41 | printf("%8s\t%8.1f\t%8d\n", 42 | s.plugged_in ? "TRUE" : "false", 43 | s.charge_pct, 44 | s.minutes_remaining); 45 | sleep(1); 46 | } 47 | 48 | battery_close(&s); 49 | } 50 | -------------------------------------------------------------------------------- /gui/Makefile: -------------------------------------------------------------------------------- 1 | # build & link flags (XXX remember to tweak CXX versions below) 2 | CFLAGS += -c -std=c89 -Wall -Wextra -Werror -O2 3 | CFLAGS += `pkg-config --cflags pangocairo` 4 | LDFLAGS += -lm -L/usr/X11R6/lib -lxcb -lxcb-icccm 5 | LDFLAGS += `pkg-config --libs pangocairo` 6 | 7 | # all objects + drivers defined here 8 | .include "Makefile.in" 9 | 10 | .PHONY: clean objects tests drivers 11 | .DEFAULT: all 12 | 13 | all: $(GUI_OBJS) $(GUI_DRIVERS) 14 | objects: $(GUI_OBJS) 15 | drivers: $(GUI_DRIVERS) 16 | 17 | .c.o: 18 | $(CC) $(CFLAGS) $< 19 | 20 | # drivers (system tests) 21 | xcore.d: xcore.o xcore.d.o 22 | $(CC) -o $@ $(LDFLAGS) xcore.o xcore.d.o 23 | 24 | chart.d: chart.o chart.d.o 25 | $(CC) -o $@ $(LDFLAGS) chart.o chart.d.o 26 | 27 | xdraw.d: xcore.o chart.o xdraw.o xdraw.d.o 28 | $(CC) -o $@ $(LDFLAGS) xcore.o xdraw.o chart.o xdraw.d.o 29 | 30 | 31 | # unit tests (using gtest, so c++) 32 | CXX ?= clang++ 33 | CXXFLAGS += -c -Wall -Wextra -Werror -O2 34 | CXXFLAGS += `pkg-config --cflags pangocairo` 35 | LXXDFLAGS += -lm -L/usr/X11R6/lib -lxcb -lxcb-icccm 36 | LXXDFLAGS += -L/usr/local/lib -lgtest -lgtest_main -lpthread 37 | LXXDFLAGS += `pkg-config --libs pangocairo` 38 | 39 | TESTS = xcore.t chart.t 40 | TOBJS = xcore.t.o chart.t.o 41 | 42 | tests: $(TESTS) 43 | gtester $(TESTS) 44 | 45 | .cc.o: 46 | $(CXX) $(CXXFLAGS) $< 47 | 48 | xcore.t: xcore.t.o xcore.o 49 | $(CXX) -o $@ $(LXXDFLAGS) xcore.o xcore.t.o 50 | 51 | chart.t: chart.t.o chart.o 52 | $(CXX) -o $@ $(LXXDFLAGS) chart.o chart.t.o 53 | 54 | clean: 55 | rm -f $(GUI_OBJS) 56 | rm -f $(GUI_DRIVERS) 57 | rm -f $(TOBJS) 58 | rm -f $(TESTS) 59 | -------------------------------------------------------------------------------- /widgets/memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WMEMORY_H 18 | #define WMEMORY_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | struct widget_memory_settings { 26 | char *hdcolor; 27 | char *bgcolor; 28 | char *fgcolor; 29 | char *chart_bgcolor; 30 | char *chart_color_free; 31 | char *chart_color_total; 32 | char *chart_color_active; 33 | }; 34 | 35 | struct widget_memory_state { 36 | /* pointers to stuff */ 37 | struct oxstats *stats; 38 | struct widget_memory_settings *settings; 39 | /* local state */ 40 | struct chart *chart; 41 | }; 42 | 43 | void *wmemory_init(struct oxstats*, void *settings); 44 | void wmemory_free(void *wstate); 45 | bool wmemory_enabled(void *wstate); 46 | void wmemory_draw(void *wstate, struct xctx*); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /widgets/net.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WNET_H 18 | #define WNET_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | struct widget_net_settings { 26 | char *hdcolor; 27 | char *bgcolor; 28 | char *fgcolor; 29 | char *inbound_chart_color_bgcolor; 30 | char *inbound_chart_color_pgcolor; 31 | char *inbound_text_fgcolor; 32 | char *outbound_chart_color_bgcolor; 33 | char *outbound_chart_color_pgcolor; 34 | char *outbound_text_fgcolor; 35 | }; 36 | 37 | struct widget_net_state { 38 | /* pointers to stuff */ 39 | struct oxstats *stats; 40 | struct widget_net_settings *settings; 41 | /* local state */ 42 | struct chart *inbound; 43 | struct chart *outbound; 44 | }; 45 | 46 | void *wnet_init(struct oxstats*, void *settings); 47 | void wnet_free(void *wstate); 48 | bool wnet_enabled(void *wstate); 49 | void wnet_draw(void *wstate, struct xctx*); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /stats/net.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "net.h" 25 | 26 | volatile sig_atomic_t sig_stop = 0; 27 | void stop(int __attribute__((unused)) sig) { sig_stop = 1; } 28 | 29 | int 30 | main() 31 | { 32 | struct net_stats s; 33 | signal(SIGINT, stop); 34 | 35 | net_init(&s); 36 | if (!s.is_setup) 37 | errx(1, "failed to setup core!"); 38 | 39 | printf("iface: '%s'\n\n", s.iface); 40 | printf("%10s %10s %10s %10s %10s %10s %10s %10s\n", 41 | "#p in", "#p out", "#new in", "#new out", 42 | "#b in", "#b out", "#b new in", "#b new out"); 43 | 44 | while (!sig_stop) { 45 | net_update(&s); 46 | printf("%10lu %10lu %10lu %10lu %10llu %10llu %10llu %10llu\n", 47 | s.packets_in, s.packets_out, 48 | s.packets_in_new, s.packets_in_new, 49 | s.bytes_in, s.bytes_out, 50 | s.bytes_in_new, s.bytes_out_new); 51 | sleep(1); 52 | } 53 | 54 | net_close(&s); 55 | } 56 | -------------------------------------------------------------------------------- /stats/memory.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "memory.h" 23 | 24 | volatile sig_atomic_t sig_stop = 0; 25 | void stop(int __attribute__((unused)) sig) { sig_stop = 1; } 26 | 27 | int 28 | main() 29 | { 30 | struct memory_stats s; 31 | signal(SIGINT, stop); 32 | 33 | memory_init(&s); 34 | if (!s.is_setup) 35 | errx(1, "failed to setup memory!"); 36 | 37 | printf("%8s %7s ", "Act kb", "%"); 38 | printf("%8s %7s ", "Tot kb", "%"); 39 | printf("%8s %7s ", "Free kb", "%"); 40 | printf("%8s %7s ", "Swap U", "%"); 41 | printf("%8s\n", "Swap T"); 42 | 43 | while (!sig_stop) { 44 | memory_update(&s); 45 | printf("%8d %7.1f ", s.active, s.active_pct); 46 | printf("%8d %7.1f ", s.total, s.total_pct); 47 | printf("%8d %7.1f ", s.free, s.free_pct); 48 | printf("%8d %7.1f ", s.swap_used, s.swap_used_pct); 49 | printf("%8d\n", s.swap_total); 50 | sleep(1); 51 | } 52 | 53 | memory_close(&s); 54 | } 55 | -------------------------------------------------------------------------------- /widgets/cpus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef WCPUS_H 18 | #define WCPUS_H 19 | 20 | #include 21 | 22 | #include "../gui/xdraw.h" 23 | #include "../stats/stats.h" 24 | 25 | /* 26 | * settings for a cpus widget (public so settings.* component can pick them 27 | * up and set them via cli or config file) 28 | */ 29 | struct widget_cpu_settings { 30 | char *hdcolor; 31 | char *bgcolor; 32 | char *fgcolor; 33 | char *chart_bgcolor; 34 | char *chart_color_system; 35 | char *chart_color_interrupt; 36 | char *chart_color_user; 37 | char *chart_color_nice; 38 | char *chart_color_spin; 39 | char *chart_color_idle; 40 | }; 41 | 42 | struct widget_cpu_state { 43 | /* pointers to stuff */ 44 | struct oxstats *stats; 45 | struct widget_cpu_settings *settings; 46 | /* local state */ 47 | size_t ncpus; 48 | struct chart **cpu_charts; 49 | }; 50 | 51 | void *wcpu_init(struct oxstats*, void *settings); 52 | void wcpu_free(void *wstate); 53 | bool wcpu_enabled(void *wstate); 54 | void wcpu_draw(void *wstate, struct xctx*); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /stats/cpu.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "cpu.h" 23 | 24 | volatile sig_atomic_t sig_stop = 0; 25 | void stop(int __attribute__((unused)) sig) { sig_stop = 1; } 26 | 27 | int 28 | main() 29 | { 30 | struct cpu_stats s; 31 | int i; 32 | signal(SIGINT, stop); 33 | 34 | cpu_init(&s); 35 | if (!s.is_setup) 36 | errx(1, "failed to setup cpus!"); 37 | 38 | printf("#cpus: %d\n\n", s.ncpu); 39 | printf("%4s: %7s %7s %7s %7s %7s %7s", 40 | "cpuX", "user", "nice", "system", "spin", "intrpt", "idle\n"); 41 | 42 | while (!sig_stop) { 43 | cpu_update(&s); 44 | for (i = 0; i < s.ncpu; i++) { 45 | printf("cpu%02d: %6.1f%% %6.1f%% %6.1f%% " 46 | " %6.1f%% %6.1f%% %6.1f%%\n", 47 | i, 48 | s.cpus[i].percentages[CP_USER], 49 | s.cpus[i].percentages[CP_NICE], 50 | s.cpus[i].percentages[CP_SYS], 51 | s.cpus[i].percentages[CP_SPIN], 52 | s.cpus[i].percentages[CP_INTR], 53 | s.cpus[i].percentages[CP_IDLE]); 54 | } 55 | sleep(1); 56 | } 57 | 58 | cpu_close(&s); 59 | } 60 | -------------------------------------------------------------------------------- /widgets/battery.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "util.h" 20 | #include "battery.h" 21 | 22 | bool 23 | wbattery_enabled(void *wstate) 24 | { 25 | struct generic_wstate *w = wstate; 26 | return w->stats->battery.is_setup; 27 | } 28 | 29 | void 30 | wbattery_draw(void *wstate, struct xctx *ctx) 31 | { 32 | struct generic_wstate *w = wstate; 33 | struct widget_battery_settings *settings = w->settings; 34 | 35 | xdraw_printf(ctx, 36 | w->stats->battery.plugged_in ? 37 | settings->fgcolor : 38 | settings->fgcolor_unplugged , 39 | w->stats->battery.plugged_in ? "AC:" : "BAT:"); 40 | 41 | xdraw_progress_bar(ctx, 42 | settings->chart_bgcolor, 43 | settings->chart_pgcolor, 44 | settings->chart_width, 45 | w->stats->battery.charge_pct); 46 | 47 | xdraw_printf(ctx, 48 | settings->fgcolor, 49 | "% 3.0f%%", w->stats->battery.charge_pct); 50 | 51 | if (-1 != w->stats->battery.minutes_remaining) { 52 | xdraw_printf(ctx, 53 | settings->fgcolor, 54 | " %dh %dm", 55 | w->stats->battery.minutes_remaining / 60, 56 | w->stats->battery.minutes_remaining % 60); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /stats/stats.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include "stats.h" 18 | 19 | struct oxstats OXSTATS; 20 | 21 | void 22 | stats_init() 23 | { 24 | battery_init(&OXSTATS.battery); 25 | brightness_init(&OXSTATS.brightness); 26 | cpu_init(&OXSTATS.cpus); 27 | memory_init(&OXSTATS.memory); 28 | net_init(&OXSTATS.network); 29 | nprocs_init(&OXSTATS.nprocs); 30 | volume_init(&OXSTATS.volume); 31 | wifi_init(&OXSTATS.wifi); 32 | 33 | /* do first update to initialize everything */ 34 | stats_update(); 35 | } 36 | 37 | void 38 | stats_update() 39 | { 40 | battery_update(&OXSTATS.battery); 41 | brightness_update(&OXSTATS.brightness); 42 | cpu_update(&OXSTATS.cpus); 43 | memory_update(&OXSTATS.memory); 44 | net_update(&OXSTATS.network); 45 | nprocs_update(&OXSTATS.nprocs); 46 | volume_update(&OXSTATS.volume); 47 | wifi_update(&OXSTATS.wifi); 48 | } 49 | 50 | void 51 | stats_close() 52 | { 53 | battery_close(&OXSTATS.battery); 54 | brightness_close(&OXSTATS.brightness); 55 | cpu_close(&OXSTATS.cpus); 56 | memory_close(&OXSTATS.memory); 57 | net_close(&OXSTATS.network); 58 | nprocs_close(&OXSTATS.nprocs); 59 | volume_close(&OXSTATS.volume); 60 | wifi_close(&OXSTATS.wifi); 61 | } 62 | -------------------------------------------------------------------------------- /gui/xdraw.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include "xdraw.h" 19 | 20 | void 21 | pause() 22 | { 23 | printf("press ENTER to continue"); 24 | getchar(); 25 | } 26 | 27 | int 28 | main() 29 | { 30 | struct xdisp *x = xdisp_init(); 31 | struct xfont *f; 32 | 33 | printf("display: %x x %x (pixels)\n", x->display_width, x->display_height); 34 | 35 | struct xfont_settings fonts = { 36 | .desc = "serif italic 20", 37 | .fgcolor = "ff0000" 38 | }; 39 | f = xfont_init(&fonts); 40 | 41 | struct xwin_settings wins = { 42 | .bgcolor = "#ff0000", 43 | .wname = "xcore.d :: xwin test", 44 | .x = 500, .y = 500, 45 | .w = 500, .h = 500 46 | }; 47 | struct padding padding = { 48 | .top = 10, 49 | .right = 10, 50 | .bottom = 10, 51 | .left = 10 52 | }; 53 | struct xwin *w = xwin_init(x, &wins); 54 | struct xctx *root = xctx_init_root(f, w, L2R, &padding); 55 | 56 | xwin_push(w); 57 | 58 | xdraw_colorfill(root, "#ffffff"); 59 | xdraw_printf(root, "#ff0000", "Hello world!"); 60 | 61 | xwin_pop(w); 62 | 63 | pause(); 64 | 65 | xwin_push(w); 66 | 67 | xdraw_colorfill(root, "#ffffff"); 68 | xdraw_printf(root, "#00ff00", "Hello world!"); 69 | 70 | xwin_pop(w); 71 | 72 | pause(); 73 | 74 | printf("bye\n"); 75 | xctx_free(root); 76 | xwin_free(w); 77 | xdisp_free(x); 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /stats/README.md: -------------------------------------------------------------------------------- 1 | # oxbar stats collectors 2 | 3 | This directory contains all the stats collectors used by oxbar. 4 | They each follow a pattern, that should be followed as much as possible, 5 | described here. 6 | 7 | ## pattern to follow for all stat collectors 8 | * Each collector of a type of stats, like cpu stats, lives in `cpu.h` and 9 | `cpu.c`, with full test driver in `cpu.d.c` 10 | * Each collector declares a type like `struct cpu_stats` containing the 11 | display-ready versions of the stats it collects 12 | * Any other local state the collector needs are static private locals in `cpu.c` 13 | * The collectors themselves don't have to worry about malloc()/free()'ing 14 | their `struct foo_stats` types - that's done by `stats.h`/`stats.c` 15 | * Each collector has an init, update, and free method taking a pointer to 16 | their respective stats object. E.g. 17 | * `void cpu_init(struct cpu_stats*)` 18 | * `void cpu_update(struct cpu_stats*)` 19 | * `void cpu_close(struct cpu_stats*)` 20 | * `stats.h`/`stats.c` handle allocating and loading the stats object for every 21 | collector, and wrap the init, update, and close methods for all collectors 22 | 23 | ## patterns within each collector 24 | * Each collector's stat type has a boolean member `is_setup` 25 | * The `_init(...)` method sets that appropriately 26 | * The `_update(...)` method checks that, and ignores updates if not setup 27 | * The `_cleanup(...)` method can use it to aid cleanup 28 | * For some collectors, that enablement can change over time 29 | 30 | ## expectations by oxbar on the stats components 31 | * All stats are wrapped into the global `OXBAR` instance of `struct oxstats` 32 | defined in `stats.h` 33 | * That object represents a global, read-only dump of all stats available 34 | * History is *NOT* tracked in the collectors - widgets do that if they want 35 | * Stats should be grouped logically by what, and how, they access data. There 36 | should be no relation between stats collectors and widgets. E.g. it's fine 37 | for a widget to use stats from multiple collectors. That's why the `OXSTATS` 38 | abstraction exists: to present all stats to every widget. 39 | -------------------------------------------------------------------------------- /stats/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "util.h" 27 | 28 | char* 29 | get_egress() 30 | { 31 | struct ifgroupreq ifgr; 32 | struct ifg_req *ifg; 33 | unsigned int len; 34 | int ioctlfd; 35 | char *name; 36 | 37 | memset(&ifgr, 0, sizeof(ifgr)); 38 | strlcpy(ifgr.ifgr_name, "egress", sizeof(ifgr.ifgr_name)); 39 | 40 | if ((ioctlfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 41 | err(1, "egress lookup: socket(AF_INET, SOCK_DGRAM)"); 42 | 43 | if (ioctl(ioctlfd, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 44 | err(1, "egress lookup: ioctl(SIOCGIFGMEMB)"); 45 | 46 | len = ifgr.ifgr_len; 47 | if (NULL == (ifgr.ifgr_groups = calloc(1, len))) 48 | err(1, "egress lookup: calloc w/ len = %d", len); 49 | 50 | if (ioctl(ioctlfd, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 51 | err(1, "egress lookup: ioctl(SIOCGIFGMEMB)"); 52 | 53 | name = NULL; 54 | for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) { 55 | len -= sizeof(*ifg); 56 | if (NULL != name) 57 | continue; /* just use first egress interface */ 58 | if (NULL == (name = strdup(ifg->ifgrq_member))) 59 | errx(1, "egress: strdup '%s'", ifg->ifgrq_member); 60 | } 61 | 62 | free(ifgr.ifgr_groups); 63 | return name; 64 | } 65 | -------------------------------------------------------------------------------- /widgets/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "util.h" 22 | 23 | void* 24 | generic_init(struct oxstats *stats, void *settings) 25 | { 26 | struct generic_wstate *w; 27 | if (NULL == (w = malloc(sizeof(struct generic_wstate)))) 28 | err(1, "malloc() failed for generic widget state"); 29 | 30 | w->settings = settings; 31 | w->stats = stats; 32 | return w; 33 | } 34 | 35 | void 36 | generic_free(void *wstate) 37 | { 38 | free(wstate); 39 | } 40 | 41 | const char * 42 | fmt_memory(const char *fmt, int kbytes) 43 | { 44 | #define GUI_FMT_MEMORY_BUFFER_MAXLEN 100 45 | static char buffer[GUI_FMT_MEMORY_BUFFER_MAXLEN]; 46 | static const char *suffixes[] = { "k", "M", "G", "T", "P" }; 47 | static const size_t snum = sizeof(suffixes) / sizeof(suffixes[0]); 48 | 49 | double dbytes = (double) kbytes; 50 | size_t step = 0; 51 | int ret; 52 | 53 | if (1024 < kbytes) 54 | for (step = 0; (kbytes / 1024) > 0 && step < snum; step++, kbytes /= 1024) 55 | dbytes = kbytes / 1024.0; 56 | 57 | ret = snprintf(buffer, GUI_FMT_MEMORY_BUFFER_MAXLEN, fmt, dbytes); 58 | if (0 > ret) 59 | err(1, "%s: snprintf failed for %d", __FUNCTION__, kbytes); 60 | 61 | ret = snprintf(buffer + ret, GUI_FMT_MEMORY_BUFFER_MAXLEN- ret, "%s", 62 | suffixes[step]); 63 | if (0 > ret) 64 | err(1, "%s: snprintf failed for %s", __FUNCTION__, suffixes[step]); 65 | 66 | return buffer; 67 | } 68 | -------------------------------------------------------------------------------- /widgets/volume.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "util.h" 20 | #include "volume.h" 21 | 22 | bool 23 | wvolume_enabled(void *wstate) 24 | { 25 | struct generic_wstate *w = wstate; 26 | return w->stats->volume.is_setup; 27 | } 28 | 29 | void 30 | wvolume_draw(void *wstate, struct xctx *ctx) 31 | { 32 | struct generic_wstate *w = wstate; 33 | struct widget_volume_settings *settings = w->settings; 34 | struct oxstats *stats = w->stats; 35 | 36 | xdraw_printf(ctx, settings->fgcolor, "Vol:"); 37 | 38 | if (stats->volume.muted) 39 | xdraw_printf(ctx, "#f00", " MUTE "); 40 | 41 | if (stats->volume.left == stats->volume.right) { 42 | xdraw_progress_bar(ctx, 43 | settings->chart_bgcolor, 44 | settings->chart_pgcolor, 45 | settings->chart_width, 46 | stats->volume.left); 47 | xdraw_printf(ctx, settings->fgcolor, "% 3.0f%%", stats->volume.left); 48 | } else { 49 | xdraw_printf(ctx, settings->fgcolor, "%3.0f%% ", stats->volume.left); 50 | 51 | xdraw_progress_bar(ctx, 52 | settings->chart_bgcolor, 53 | settings->chart_pgcolor, 54 | settings->chart_width / 2 + 1, 55 | stats->volume.left); 56 | 57 | xctx_advance(ctx, AFTER_RENDER, 2, 0); /* 2-pixel space between sides */ 58 | 59 | xdraw_progress_bar(ctx, 60 | settings->chart_bgcolor, 61 | settings->chart_pgcolor, 62 | settings->chart_width / 2 + 1, 63 | stats->volume.right); 64 | 65 | xdraw_printf(ctx, settings->fgcolor, "% 3.0f%%", stats->volume.right); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /settings.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef SETTINGS_H 18 | #define SETTINGS_H 19 | 20 | #include "gui/gui.h" 21 | #include "gui/xdraw.h" 22 | #include "gui/xcore.h" 23 | 24 | #include "widgets/battery.h" 25 | #include "widgets/bright.h" 26 | #include "widgets/cpus.h" 27 | #include "widgets/memory.h" 28 | #include "widgets/net.h" 29 | #include "widgets/nprocs.h" 30 | #include "widgets/time.h" 31 | #include "widgets/volume.h" 32 | #include "widgets/wifi.h" 33 | 34 | struct settings { 35 | /* these aren't directly 'set-able' settings - more meta-settings */ 36 | char *config_file; /* file to read settings from */ 37 | char *theme; /* theme name specified on command line (if any) */ 38 | 39 | /* this is setable but doesn't belong to any proper component below */ 40 | char *widgets; /* widget list with formatting */ 41 | 42 | /* core display settings */ 43 | struct xfont_settings font; 44 | struct xwin_settings window; 45 | struct gui_settings gui; 46 | 47 | /* per-widget settings */ 48 | struct widget_battery_settings battery; 49 | struct widget_bright_settings bright; 50 | struct widget_volume_settings volume; 51 | struct widget_nprocs_settings nprocs; 52 | struct widget_memory_settings memory; 53 | struct widget_cpu_settings cpus; 54 | struct widget_net_settings net; 55 | struct widget_time_settings time; 56 | struct widget_wifi_settings wifi; 57 | }; 58 | 59 | void settings_init(struct settings *s, int argc, char *argv[]); 60 | void settings_reload_config(struct settings *s); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /stats/battery.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "battery.h" 26 | 27 | static struct apm_power_info apm_info; 28 | static int apm_dev_fd; 29 | 30 | void 31 | battery_init(struct battery_stats *stats) 32 | { 33 | stats->is_setup = false; 34 | 35 | apm_dev_fd = open("/dev/apm", O_RDONLY); 36 | if (apm_dev_fd < 0) 37 | return; 38 | 39 | if (ioctl(apm_dev_fd, APM_IOC_GETPOWER, &(apm_info)) < 0) 40 | errx(1, "APM_IOC_GETPOWER"); 41 | 42 | /* if not on a battery (desktop) don't enable this widget */ 43 | if (APM_AC_OFF != apm_info.ac_state 44 | && APM_AC_ON != apm_info.ac_state) 45 | return; 46 | 47 | stats->is_setup = true; 48 | } 49 | 50 | void 51 | battery_update(struct battery_stats *stats) 52 | { 53 | if (!stats->is_setup) 54 | return; 55 | 56 | if (ioctl(apm_dev_fd, APM_IOC_GETPOWER, &(apm_info)) < 0) 57 | errx(1, "APM_IOC_GETPOWER"); 58 | 59 | switch (apm_info.ac_state) { 60 | case APM_AC_OFF: 61 | stats->plugged_in = false; 62 | break; 63 | case APM_AC_ON: 64 | stats->plugged_in = true; 65 | break; 66 | case APM_AC_BACKUP: 67 | case APM_AC_UNKNOWN: 68 | /* likely a desktop machine - see catch in init */ 69 | break; 70 | default: 71 | warnx("battery: failed to decode APM status"); 72 | } 73 | 74 | stats->charge_pct = apm_info.battery_life; 75 | stats->minutes_remaining = apm_info.minutes_left; 76 | } 77 | 78 | void 79 | battery_close(struct battery_stats *stats) 80 | { 81 | if (stats->is_setup) 82 | close(apm_dev_fd); 83 | } 84 | -------------------------------------------------------------------------------- /widgets/cpuslong.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "cpuslong.h" 20 | 21 | bool 22 | wcpulong_enabled(void *wstate) 23 | { 24 | return wcpu_enabled(wstate); 25 | } 26 | 27 | void 28 | wcpulong_draw(void *wstate, struct xctx *ctx) 29 | { 30 | struct widget_cpu_state *w = wstate; 31 | struct oxstats *stats = w->stats; 32 | struct widget_cpu_settings *settings = w->settings; 33 | char *fgcolor = w->settings->fgcolor; 34 | 35 | xdraw_printf(ctx, fgcolor, "CPUs: "); 36 | size_t cpu; 37 | for (cpu = 0; cpu < w->ncpus; cpu++) { 38 | chart_update(w->cpu_charts[cpu], (double[]) { 39 | stats->cpus.cpus[cpu].percentages[CP_SYS], 40 | stats->cpus.cpus[cpu].percentages[CP_INTR], 41 | stats->cpus.cpus[cpu].percentages[CP_USER], 42 | stats->cpus.cpus[cpu].percentages[CP_NICE], 43 | stats->cpus.cpus[cpu].percentages[CP_SPIN], 44 | stats->cpus.cpus[cpu].percentages[CP_IDLE] 45 | }); 46 | 47 | xdraw_chart(ctx, w->cpu_charts[cpu]); 48 | xdraw_printf(ctx, settings->chart_color_system, "%3.0f%%", 49 | stats->cpus.cpus[cpu].percentages[CP_SYS]); 50 | xdraw_printf(ctx, settings->chart_color_interrupt, "%3.0f%%", 51 | stats->cpus.cpus[cpu].percentages[CP_INTR]); 52 | xdraw_printf(ctx, settings->chart_color_user, "%3.0f%%", 53 | stats->cpus.cpus[cpu].percentages[CP_USER]); 54 | xdraw_printf(ctx, settings->chart_color_nice, "%3.0f%%", 55 | stats->cpus.cpus[cpu].percentages[CP_NICE]); 56 | xdraw_printf(ctx, settings->chart_color_spin, "%3.0f%%", 57 | stats->cpus.cpus[cpu].percentages[CP_SPIN]); 58 | xdraw_printf(ctx, settings->chart_color_idle, "%3.0f%%", 59 | stats->cpus.cpus[cpu].percentages[CP_IDLE]); 60 | 61 | if (cpu != w->ncpus - 1) xdraw_printf(ctx, "000000", " "); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /stats/wifi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "wifi.h" 32 | #include "util.h" 33 | 34 | static int wifi_socket; 35 | static struct ieee80211_bssid bssid; 36 | 37 | void 38 | wifi_init(struct wifi_stats *stats) 39 | { 40 | int ibssid; 41 | stats->is_setup = false; 42 | 43 | if (NULL == (stats->iface = get_egress())) 44 | return; 45 | 46 | if (-1 == (wifi_socket = socket(AF_INET, SOCK_DGRAM, 0))) { 47 | free(stats->iface); 48 | return; 49 | } 50 | 51 | memset(&bssid, 0, sizeof(bssid)); 52 | strlcpy(bssid.i_name, stats->iface, sizeof(bssid.i_name)); 53 | 54 | ibssid = ioctl(wifi_socket, SIOCG80211BSSID, &bssid); 55 | if (0 == ibssid) 56 | stats->is_setup = true; /* egress is a 802.11, we're good */ 57 | else { 58 | stats->is_setup = false; /* that's not the case - bail */ 59 | free(stats->iface); 60 | } 61 | } 62 | 63 | void 64 | wifi_update(struct wifi_stats *stats) 65 | { 66 | if (!stats->is_setup) 67 | return; 68 | 69 | struct ieee80211_nodereq req; 70 | bzero(&req, sizeof(req)); 71 | 72 | bcopy(bssid.i_bssid, &req.nr_macaddr, sizeof(req.nr_macaddr)); 73 | strlcpy(req.nr_ifname, stats->iface, sizeof(req.nr_ifname)); 74 | if (0 == ioctl(wifi_socket, SIOCG80211NODE, &req) && req.nr_rssi) 75 | stats->signal_strength = (float) IEEE80211_NODEREQ_RSSI(&req); 76 | } 77 | 78 | void 79 | wifi_close(struct wifi_stats *stats) 80 | { 81 | if (stats->is_setup) { 82 | free(stats->iface); 83 | close(wifi_socket); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /testruns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | # This should be run via `make testruns` 3 | # It's a list of sample configurations to run-throug/test oxbar with. 4 | 5 | trap "" INT TERM 6 | 7 | # easy bg colors for testing layouts 8 | GSIZE="-x 100 -y 100 -w 1000" 9 | GCOLORS="-S window.bgcolor=ff0000 -S gui.widget_bgcolor=ffffff -c none" 10 | GWIDGETS="nprocs nprocs | nprocs nprocs > nprocs nprocs" 11 | 12 | # test SIGHUP reloading config 13 | ./oxbar -F sample.oxbar.conf & 14 | pid=$! 15 | /bin/sleep 1 && kill -HUP $pid 16 | /bin/sleep 1 && kill -HUP $pid 17 | /bin/sleep 1 && kill -HUP $pid 18 | /bin/sleep 1 && kill -HUP $pid 19 | kill $pid 20 | 21 | # test padding/margins 22 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p 10 -m 20 23 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p 10 -m 0 24 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p 10 -m "0 0 0 0" 25 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p 10 -m "0 20 20 0" 26 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p 0 -m 10 27 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p "0 0 0 0" -m 20 28 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p "40 0 20 5" -m 20 29 | 30 | # test widget spacing 31 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p 10 -m 10 -s 0 32 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p 10 -m 10 -s 10 33 | ./oxbar $GSIZE $GCOLORS -W "$GWIDGETS" -p 10 -m 10 -s 20 34 | 35 | # test setting colored headers 36 | ./oxbar $GCOLORS -y 100 -p 20 -m 20 -c none 37 | ./oxbar $GCOLORS -y 100 -p 20 -m 20 -c above 38 | ./oxbar $GCOLORS -y 100 -p 20 -m 20 -c below 39 | 40 | # test y/w/h morphing 41 | ./oxbar $GCOLORS -y 0 -w 400 -h 50 -W "time" 42 | ./oxbar $GCOLORS -y 0 -w 400 -h -1 -W "time" 43 | ./oxbar $GCOLORS -y 0 -w -1 -h 50 -W "time" 44 | ./oxbar $GCOLORS -y 0 -w -1 -h -1 -W "time" 45 | ./oxbar $GCOLORS -y -1 -w 400 -h 50 -W "time" 46 | ./oxbar $GCOLORS -y -1 -w 400 -h -1 -W "time" 47 | ./oxbar $GCOLORS -y -1 -w -1 -h 50 -W "time" 48 | ./oxbar $GCOLORS -y -1 -w -1 -h -1 -W "time" 49 | 50 | # test display ordering 51 | ./oxbar -y 0 -W "time time" 52 | ./oxbar -y 0 -W "< time time" 53 | ./oxbar -y 0 -W "| time time" 54 | ./oxbar -y 0 -W "> time time" 55 | ./oxbar -y 0 -W "time | time > time" 56 | ./oxbar -y 0 -W "< | > time" 57 | ./oxbar -y 0 -W "< time time | time time > time time" 58 | 59 | # test config file & themes 60 | ./oxbar -F sample.oxbar.conf 61 | ./oxbar -F sample.oxbar.conf FooBar # should fail 62 | ./oxbar -F sample.oxbar.conf top 63 | ./oxbar -F sample.oxbar.conf bottom 64 | ./oxbar -F sample.oxbar.conf islands 65 | ./oxbar -F sample.oxbar.conf islands-colorful 66 | ./oxbar -F sample.oxbar.conf minimal 67 | ./oxbar -F sample.oxbar.conf ryan 68 | ./oxbar -F sample.oxbar.conf pastels 69 | ./oxbar -F sample.oxbar.conf xstatbar 70 | -------------------------------------------------------------------------------- /widgets/memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "memory.h" 20 | #include "util.h" 21 | 22 | void * 23 | wmemory_init(struct oxstats *stats, void *settings) 24 | { 25 | struct widget_memory_state *w; 26 | if (NULL == (w = malloc(sizeof(struct widget_memory_state)))) 27 | err(1, "failed to allocate widget_memory_state"); 28 | 29 | w->settings = settings; 30 | w->stats = stats; 31 | 32 | const char *colors[] = { 33 | w->settings->chart_color_active, 34 | w->settings->chart_color_total, 35 | w->settings->chart_color_free 36 | }; 37 | 38 | w->chart = chart_init(60, 3, true, w->settings->chart_bgcolor, colors); 39 | return w; 40 | } 41 | 42 | void 43 | wmemory_free(void *wstate) 44 | { 45 | struct widget_memory_state *w = wstate; 46 | chart_free(w->chart); 47 | free(w); 48 | } 49 | 50 | bool 51 | wmemory_enabled(void *wstate) 52 | { 53 | struct widget_memory_state *w = wstate; 54 | return w->stats->memory.is_setup; 55 | } 56 | 57 | void 58 | wmemory_draw(void *wstate, struct xctx *ctx) 59 | { 60 | struct widget_memory_state *w = wstate; 61 | struct widget_memory_settings *settings = w->settings; 62 | struct oxstats *stats = w->stats; 63 | 64 | chart_update(w->chart, (double[]) { 65 | stats->memory.active_pct, 66 | stats->memory.total_pct, 67 | stats->memory.free_pct 68 | }); 69 | 70 | xdraw_printf(ctx, w->settings->fgcolor, "Mem: "); 71 | xdraw_chart(ctx, w->chart); 72 | xdraw_printf(ctx, settings->chart_color_active, " %s", 73 | fmt_memory("%.1lf", stats->memory.active)); 74 | xdraw_printf(ctx, w->settings->fgcolor, " act "); 75 | xdraw_printf(ctx, settings->chart_color_total, "%s", 76 | fmt_memory("%.1lf", stats->memory.total)); 77 | xdraw_printf(ctx, w->settings->fgcolor, " tot "); 78 | xdraw_printf(ctx, settings->chart_color_free, 79 | fmt_memory("%.1lf", stats->memory.free)); 80 | xdraw_printf(ctx, w->settings->fgcolor, " free"); 81 | } 82 | -------------------------------------------------------------------------------- /widgets/net.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "net.h" 20 | #include "util.h" 21 | 22 | void * 23 | wnet_init(struct oxstats *stats, void *settings) 24 | { 25 | struct widget_net_state *w; 26 | if (NULL == (w = malloc(sizeof(struct widget_net_state)))) 27 | err(1, "failed to allocate widget_net_state"); 28 | 29 | w->settings = settings; 30 | w->stats = stats; 31 | 32 | const char *colors_in[] = { 33 | w->settings->inbound_chart_color_pgcolor 34 | }; 35 | const char *colors_out[] = { 36 | w->settings->outbound_chart_color_pgcolor 37 | }; 38 | char *bgcolor_in = w->settings->inbound_chart_color_bgcolor; 39 | char *bgcolor_out = w->settings->outbound_chart_color_bgcolor; 40 | 41 | w->inbound = chart_init(60, 1, false, bgcolor_in, colors_in); 42 | w->outbound = chart_init(60, 1, false, bgcolor_out, colors_out); 43 | return w; 44 | } 45 | 46 | void 47 | wnet_free(void *wstate) 48 | { 49 | struct widget_net_state *w = wstate; 50 | chart_free(w->inbound); 51 | chart_free(w->outbound); 52 | free(w); 53 | } 54 | 55 | bool 56 | wnet_enabled(void *wstate) 57 | { 58 | struct widget_net_state *w = wstate; 59 | return w->stats->network.is_setup; 60 | } 61 | 62 | void 63 | wnet_draw(void *wstate, struct xctx *ctx) 64 | { 65 | struct widget_net_state *w = wstate; 66 | struct oxstats *stats = w->stats; 67 | struct chart *chart_in = w->inbound; 68 | struct chart *chart_out = w->outbound; 69 | 70 | chart_update(chart_in, (double[]){ stats->network.bytes_in_new }); 71 | chart_update(chart_out, (double[]){ stats->network.bytes_out_new }); 72 | 73 | xdraw_printf(ctx, w->settings->fgcolor, "Net: "); 74 | xdraw_chart(ctx, chart_in); 75 | xdraw_printf(ctx, w->settings->inbound_text_fgcolor, "% 4s ", 76 | fmt_memory("% 4.0f", stats->network.bytes_in_new / 1000)); 77 | xdraw_chart(ctx, chart_out); 78 | xdraw_printf(ctx, w->settings->outbound_text_fgcolor, "% 4s", 79 | fmt_memory("% 4.0f", stats->network.bytes_out_new / 1000)); 80 | } 81 | -------------------------------------------------------------------------------- /gui/gui.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef GUI_H 18 | #define GUI_H 19 | 20 | #include 21 | 22 | #include "xcore.h" 23 | #include "xdraw.h" 24 | 25 | /* 26 | * A widget, as understood by the gui. It has: 27 | * name: A string name, used solely for debugging. 28 | * hdcolor: A color used optionally to draw a bar above/below the widget. 29 | * enabled: A method to determine if the widget is enabled or not. Widgets 30 | * can appear/disappear based on stats/state. 31 | * draw: A method to render the widget onto a x context. 32 | */ 33 | struct widget { 34 | const char *name; /* only used for debugging */ 35 | char **hdcolor; /* header color */ 36 | char **bgcolor; /* backround color */ 37 | char **fgcolor; /* backround color */ 38 | bool (*enabled)(void *); /* is this widget enabled? */ 39 | void (*draw)(void *, struct xctx*); /* draw it to a context! */ 40 | void *state; /* internal state to the widget */ 41 | }; 42 | 43 | /* pad that wraps all user-customizable settings for a gui */ 44 | struct gui_settings { 45 | char *widget_bgcolor; 46 | int spacing; 47 | struct padding padding; 48 | struct padding margin; 49 | header_style_t header_style; 50 | }; 51 | 52 | struct widget_list_entry { 53 | TAILQ_ENTRY(widget_list_entry) widget_entry; 54 | struct widget *widget; 55 | }; 56 | 57 | /* a gui just contains & orchestrates the drawing of widgets */ 58 | struct gui { 59 | struct gui_settings *s; 60 | struct xfont *xfont; 61 | struct xwin *xwin; 62 | 63 | /* list of widgets in the left, center, and right lists */ 64 | TAILQ_HEAD(widget_list, widget_list_entry) left, center, right; 65 | }; 66 | 67 | struct gui* gui_init(struct xfont *, struct xwin *, struct gui_settings *); 68 | void gui_free(struct gui *); 69 | void gui_add_widget(struct gui *, xctx_direction_t, struct widget *); 70 | void gui_draw(struct gui *); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /screenshots.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # NOTE: This references some images in my personal directory that are used 4 | # as background images for some of the screenshots. They are not included 5 | # with the git repository as they are not mine and I don't have permission 6 | # to redistribute. 7 | 8 | # oxbar -F sample.oxbar.conf -w 1700 [theme] & # run oxbar 9 | # feh --bg-fill /home/ryan/images/ice-mountain-lake.jpg # set background 10 | # import -window root foo.png # grab whole screen 11 | # import -window oxbar foo.png # grab just oxbar 12 | # feh foo.png # to view / best way 13 | 14 | function generate_load 15 | { 16 | gitrepo="https://github.com/openbsd/src" 17 | cwd=`pwd` 18 | 19 | # start w/ some quiet time 20 | sleep 5 21 | 22 | # start some cpu & network activity 23 | ubench -c > /dev/null 2> /dev/null & 24 | tmp=`mktemp -d` 25 | cd $tmp && git clone $gitrepo > /dev/null 2> /dev/null & 26 | sleep 20 27 | 28 | # start some memory activity 29 | ubench -m > /dev/null 2> /dev/null & 30 | sleep 25 31 | 32 | # 50 seconds in - kill cpu & memory tests 33 | pkill ubench 34 | # kill network test 35 | pkill git 36 | 37 | # 5 seconds of quiet 38 | sleep 5 39 | 40 | # remove git temp dir & return to old directory 41 | rm -rf $tmp 42 | cd $cwd 43 | } 44 | 45 | # kill all running instances 46 | pkill oxbar 47 | WOPTS="-w 2200 -S window.wname=oxshort" 48 | WBG="-S window.bgcolor=fff" 49 | 50 | # default 51 | feh --bg-fill ~/images/spiff.jpg 52 | ./oxbar ${WOPTS} & 53 | generate_load 54 | import -screen -window oxshort images/theme-default.png 55 | pkill oxbar 56 | 57 | # islands 58 | feh --bg-fill ~/images/ice-mountain-lake.jpg 59 | ./oxbar ${WOPTS} ${WBG} -F sample.oxbar.conf islands & 60 | generate_load 61 | import -screen -window oxshort images/theme-islands.png 62 | pkill oxbar 63 | 64 | # islands-colorful 65 | feh --bg-fill ~/images/ice-mountain-lake.jpg 66 | ./oxbar ${WOPTS} ${WBG} -F sample.oxbar.conf islands-colorful & 67 | generate_load 68 | import -screen -window oxshort images/theme-islands-colorful.png 69 | pkill oxbar 70 | 71 | # minimal 72 | feh --bg-fill ~/images/ice-mountain-lake.jpg 73 | ./oxbar ${WOPTS} ${WBG} -F sample.oxbar.conf minimal & 74 | generate_load 75 | import -screen -window oxshort images/theme-minimal.png 76 | pkill oxbar 77 | 78 | # pastels 79 | feh --bg-fill ~/images/ice-mountain-lake.jpg 80 | ./oxbar ${WOPTS} ${WBG} -F sample.oxbar.conf pastels & 81 | generate_load 82 | import -screen -window oxshort images/theme-pastels.png 83 | pkill oxbar 84 | 85 | # ryan 86 | feh --bg-fill ~/images/spiff.jpg 87 | ./oxbar ${WOPTS} -w 2500 -F sample.oxbar.conf ryan & 88 | generate_load 89 | import -screen -window oxshort images/theme-ryan.png 90 | pkill oxbar 91 | 92 | # xstatbar 93 | feh --bg-fill ~/images/ice-mountain-lake.jpg 94 | ./oxbar ${WOPTS} -F sample.oxbar.conf xstatbar & 95 | generate_load 96 | import -screen -window oxshort images/theme-xstatbar.png 97 | pkill oxbar 98 | -------------------------------------------------------------------------------- /widgets/cpus.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "cpus.h" 20 | 21 | void * 22 | wcpu_init(struct oxstats *stats, void *settings) 23 | { 24 | struct widget_cpu_state *w; 25 | if (NULL == (w = malloc(sizeof(struct widget_cpu_state)))) 26 | err(1, "failed to allocate widget_cpu_state"); 27 | 28 | w->settings = settings; 29 | w->stats = stats; 30 | w->ncpus = stats->cpus.ncpu; /* XXX this can change at run-time! */ 31 | 32 | const char *colors[] = { 33 | w->settings->chart_color_system, 34 | w->settings->chart_color_interrupt, 35 | w->settings->chart_color_user, 36 | w->settings->chart_color_nice, 37 | w->settings->chart_color_spin, 38 | w->settings->chart_color_idle 39 | }; 40 | 41 | if (NULL == (w->cpu_charts = calloc(w->ncpus, sizeof(struct chart*)))) 42 | err(1, "failed to allocate charts array for cpus"); 43 | 44 | size_t cpu; 45 | for (cpu = 0; cpu < w->ncpus; cpu++) { 46 | w->cpu_charts[cpu] = chart_init(60, CPUSTATES, true, 47 | w->settings->chart_bgcolor, colors); 48 | } 49 | 50 | return w; 51 | } 52 | 53 | void 54 | wcpu_free(void *wstate) 55 | { 56 | struct widget_cpu_state *w = wstate; 57 | size_t cpu; 58 | for (cpu = 0; cpu < w->ncpus; cpu++) 59 | chart_free(w->cpu_charts[cpu]); 60 | 61 | free(w); 62 | } 63 | 64 | bool 65 | wcpu_enabled(void *wstate) 66 | { 67 | struct widget_cpu_state *w = wstate; 68 | return w->stats->cpus.is_setup; 69 | } 70 | 71 | void 72 | wcpu_draw(void *wstate, struct xctx *ctx) 73 | { 74 | struct widget_cpu_state *w = wstate; 75 | char *fgcolor = w->settings->fgcolor; 76 | xdraw_printf(ctx, fgcolor, "CPUs: "); 77 | 78 | size_t cpu; 79 | for (cpu = 0; cpu < w->ncpus; cpu++) { 80 | chart_update(w->cpu_charts[cpu], (double[]) { 81 | w->stats->cpus.cpus[cpu].percentages[CP_SYS], 82 | w->stats->cpus.cpus[cpu].percentages[CP_INTR], 83 | w->stats->cpus.cpus[cpu].percentages[CP_USER], 84 | w->stats->cpus.cpus[cpu].percentages[CP_NICE], 85 | w->stats->cpus.cpus[cpu].percentages[CP_SPIN], 86 | w->stats->cpus.cpus[cpu].percentages[CP_IDLE] 87 | }); 88 | 89 | xdraw_chart(ctx, w->cpu_charts[cpu]); 90 | xdraw_printf(ctx, fgcolor, "%3.0f%%", 91 | w->stats->cpus.cpus[cpu].percentages[CP_IDLE]); 92 | 93 | if (cpu != w->ncpus - 1) 94 | xdraw_printf(ctx, "000000", " "); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /stats/memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "memory.h" 29 | 30 | static int sys_pageshift; 31 | 32 | void 33 | memory_init(struct memory_stats *stats) 34 | { 35 | int pgsize; 36 | 37 | /* determine page-shift, needed to accurately interpret vminfo values */ 38 | pgsize = getpagesize(); 39 | sys_pageshift = 0; 40 | while (pgsize > 1) { 41 | sys_pageshift++; 42 | pgsize >>= 1; 43 | } 44 | sys_pageshift -= 10; 45 | 46 | stats->is_setup = true; 47 | } 48 | 49 | void 50 | memory_update(struct memory_stats *stats) 51 | { 52 | struct vmtotal vminfo; 53 | struct swapent *swapdev; 54 | static int mib[] = { CTL_VM, VM_METER }; 55 | size_t size; 56 | int nswaps, total_mem; 57 | 58 | /* update mem usage */ 59 | size = sizeof(vminfo); 60 | if (sysctl(mib, 2, &vminfo, &size, NULL, 0) < 0) 61 | err(1, "sysinfo update: VM.METER failed"); 62 | 63 | stats->active = vminfo.t_arm << sys_pageshift; 64 | stats->free = vminfo.t_free << sys_pageshift; 65 | stats->total = vminfo.t_rm << sys_pageshift; 66 | total_mem = stats->active + stats->free + stats->total; 67 | 68 | /* update mem percents */ 69 | stats->active_pct = (float)stats->active / (float)total_mem * 100.0; 70 | stats->free_pct = (float)stats->free / (float)total_mem * 100.0; 71 | stats->total_pct = (float)stats->total / (float)total_mem * 100.0; 72 | 73 | /* update swap usage */ 74 | if (0 != (nswaps = swapctl(SWAP_NSWAP, 0, 0))) { 75 | if ((swapdev = calloc(nswaps, sizeof(*swapdev))) == NULL) 76 | err(1, "swapdev calloc failed (%d)", nswaps); 77 | 78 | if (swapctl(SWAP_STATS, swapdev, nswaps) == -1) 79 | err(1, "swapctl(SWAP_STATS)"); 80 | 81 | int isize = 0; 82 | for (isize = 0; isize < nswaps; isize++) { 83 | if (swapdev[isize].se_flags & SWF_ENABLE) { 84 | stats->swap_used = swapdev[isize].se_inuse 85 | / (1024 / DEV_BSIZE); 86 | stats->swap_total = swapdev[isize].se_nblks 87 | / (1024 / DEV_BSIZE); 88 | } 89 | } 90 | free(swapdev); 91 | } 92 | 93 | /* update swap percents and strings */ 94 | stats->swap_used_pct = (float)stats->swap_used 95 | / (float)stats->swap_total 96 | * 100.0; 97 | } 98 | 99 | void 100 | memory_close(__attribute__((unused)) struct memory_stats *stats) 101 | { 102 | /* nothing to do here */ 103 | } 104 | -------------------------------------------------------------------------------- /stats/cpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "cpu.h" 26 | 27 | static u_int64_t calc_diffs(u_int64_t*, u_int64_t*, u_int64_t*); 28 | static void calc_percents(float*, u_int64_t*, u_int64_t); 29 | 30 | void 31 | cpu_init(struct cpu_stats *stats) 32 | { 33 | size_t size; 34 | int mib[] = { CTL_HW, HW_NCPUONLINE }; 35 | 36 | /* get number of cpu's */ 37 | size = sizeof(stats->ncpu); 38 | if (sysctl(mib, 2, &(stats->ncpu), &size, NULL, 0) == -1) 39 | err(1, "HW.NCPU"); 40 | 41 | /* allocate array of cpu states */ 42 | stats->cpus = calloc(stats->ncpu, sizeof(struct cpu_states)); 43 | if (NULL == stats->cpus) 44 | err(1, "calloc failed for %d cpus", stats->ncpu); 45 | 46 | stats->is_setup = true; 47 | cpu_update(stats); /* to set initial counters */ 48 | } 49 | 50 | static u_int64_t 51 | calc_diffs(u_int64_t *new, u_int64_t *old, u_int64_t *diff) 52 | { 53 | u_int64_t nticks = 0; 54 | size_t state; 55 | 56 | for (state = 0; state < CPUSTATES; state++) { 57 | if (new[state] < old[state]) 58 | diff[state] = INT64_MAX - old[state] + new[state]; 59 | else 60 | diff[state] = new[state] - old[state]; 61 | 62 | nticks += diff[state]; 63 | } 64 | 65 | return nticks; 66 | } 67 | 68 | static void 69 | calc_percents(float *percents, u_int64_t *diffs, u_int64_t total) 70 | { 71 | size_t state; 72 | 73 | if (0 == total) /* guard divde-by-zero */ 74 | total = 1; 75 | 76 | for (state = 0; state < CPUSTATES; state++) { 77 | percents[state] = (((float)diffs[state] * 1000.0 78 | + ((float)total / 2.0)) 79 | / (float)total) / 10.0; 80 | } 81 | } 82 | 83 | void 84 | cpu_update(struct cpu_stats *stats) 85 | { 86 | static int mib[] = { CTL_KERN, KERN_CPTIME2, 0 }; 87 | int cpu, state; 88 | u_int64_t current[CPUSTATES]; /* current cpu tick counters */ 89 | u_int64_t diffs[CPUSTATES]; /* diffs from previous counters */ 90 | size_t size = sizeof(current); 91 | 92 | for (cpu = 0; cpu < stats->ncpu; cpu++) { 93 | /* update curreent cpu counters */ 94 | mib[2] = cpu; 95 | if (sysctl(mib, 3, current, &size, NULL, 0) < 0) 96 | err(1, "KERN.CPTIME2[%d]", cpu); 97 | 98 | u_int64_t nticks; /* total ticks per cpu */ 99 | nticks = calc_diffs(current, stats->cpus[cpu].raw, diffs); 100 | calc_percents(stats->cpus[cpu].percentages, diffs, nticks); 101 | 102 | /* copy current back into CPUS state */ 103 | for (state = 0; state < CPUSTATES; state++) 104 | stats->cpus[cpu].raw[state] = current[state]; 105 | } 106 | } 107 | 108 | void 109 | cpu_close(struct cpu_stats *stats) 110 | { 111 | free(stats->cpus); 112 | } 113 | -------------------------------------------------------------------------------- /stats/volume.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "volume.h" 30 | 31 | static int mixer_fd; 32 | static int outputs_class = -1; 33 | static int outputs_master_idx = -1; 34 | static int outputs_mute_idx = -1; 35 | 36 | void 37 | volume_init(struct volume_stats *stats) 38 | { 39 | mixer_devinfo_t devinfo; 40 | stats->is_setup = false; 41 | 42 | /* determine mixer device & open it */ 43 | char *device = getenv("MIXERDEVICE"); 44 | if (NULL == device) 45 | device = "/dev/mixer"; 46 | 47 | if (0 >= (mixer_fd = open(device, O_RDWR))) 48 | return; 49 | 50 | /* find outputs.master volume and mute devices */ 51 | devinfo.index = 0; 52 | while (-1 != ioctl(mixer_fd, AUDIO_MIXER_DEVINFO, &devinfo)) { 53 | if (0 == strncmp(devinfo.label.name, AudioCoutputs, MAX_AUDIO_DEV_LEN)) 54 | outputs_class = devinfo.mixer_class; 55 | 56 | if (0 == strncmp(devinfo.label.name, AudioNmaster, MAX_AUDIO_DEV_LEN) 57 | && devinfo.mixer_class == outputs_class) 58 | outputs_master_idx = devinfo.index; 59 | 60 | if (0 == strncmp(devinfo.label.name, AudioNmute, MAX_AUDIO_DEV_LEN) 61 | && devinfo.mixer_class == outputs_class) 62 | outputs_mute_idx = devinfo.index; 63 | 64 | devinfo.index++; 65 | } 66 | 67 | /* did we find them? */ 68 | if (-1 == outputs_class 69 | || -1 == outputs_master_idx 70 | || -1 == outputs_mute_idx) { 71 | close(mixer_fd); 72 | stats->is_setup = false; 73 | return; 74 | } 75 | 76 | /* reopen mixer device readonly */ 77 | close(mixer_fd); 78 | if (0 >= (mixer_fd = open(device, O_RDONLY))) 79 | err(1, "failed to re-open %s readonly", device); 80 | 81 | stats->is_setup = true; 82 | } 83 | 84 | void 85 | volume_update(struct volume_stats *stats) 86 | { 87 | mixer_ctrl_t vinfo; 88 | 89 | if (!stats->is_setup) 90 | return; 91 | 92 | /* update volume */ 93 | vinfo.dev = outputs_master_idx; 94 | vinfo.type = AUDIO_MIXER_VALUE; 95 | 96 | if (-1 == ioctl(mixer_fd, AUDIO_MIXER_READ, &vinfo)) 97 | err(1, "AUDIO_MIXER_READ failed (volume)"); 98 | 99 | stats->left = (float)vinfo.un.value.level[AUDIO_MIXER_LEVEL_LEFT] 100 | / (float)AUDIO_MAX_GAIN * 100.0; 101 | stats->right = (float)vinfo.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] 102 | / (float)AUDIO_MAX_GAIN * 100.0; 103 | 104 | /* update mute */ 105 | vinfo.dev = outputs_mute_idx; 106 | vinfo.type = AUDIO_MIXER_ENUM; 107 | 108 | if (-1 == ioctl(mixer_fd, AUDIO_MIXER_READ, &vinfo)) 109 | err(1, "AUDIO_MIXER_READ failed (mute)"); 110 | 111 | stats->muted = vinfo.un.ord == 1; 112 | } 113 | 114 | void 115 | volume_close(struct volume_stats *stats) 116 | { 117 | if (stats->is_setup) 118 | close(mixer_fd); 119 | } 120 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # guidelines for contributing 2 | 3 | Pull requests can be made to master. 4 | All code should follow the existing style: 5 | 6 | 1. strict c89 that's `-Wall -Wextra -Werror` clean 7 | 2. nothing found by clang analyzer (`make scan-build`) or cppcheck 8 | (`make cppcheck`) 9 | 3. it's ok if it's not perfect -- works-in-progress welcome 10 | 4. but it should be stable 11 | 5. and any planned/known TODOs should be document (and update `make TODO`) 12 | 6. if it introduces knobs, those should be documented 13 | 7. HAH! just kidding on that last one - there is no usage documentation (yet) 14 | 15 | # a note about overall architecture 16 | 17 | These are the following components 18 | 19 | ## oxbar 20 | 21 | The `main()`, which does little more than orchestrate the various threads and 22 | signal handlers. There are 3 threads: 23 | 1. The main timer loop - sleeps for a second, wakes up, collects stats, and 24 | redraws the screen 25 | 2. The signal handler - just listens to signals and sets flags -- could 26 | possibly merge into another thread 27 | 3. The gui loop handler - just handles xcb events (expose only currently, so 28 | the gui can redraw whenever it's exposed, and not wait up to 1 second) 29 | 30 | In the main, it basically init's the other components (stats, gui, widgets), 31 | the above threads, and then runs. After exit, it cleans everything up. 32 | 33 | ## settings 34 | 35 | The settings component is really just a pad of all client knobs and ways to 36 | set them (via cli flags, and eventually a config file). This is used heavily 37 | by the widgets components as this is where all their display settings live. 38 | 39 | ## stats (subdirectory) 40 | 41 | This is where all the stats collectors live. One module for one stats source. 42 | E.g. `stats/cpu.*` collects all cpu information. There is a "wrapper" module 43 | in `stats/stats.*` that wraps all the other collectors into a single 44 | `struct` and interface, used extensively by the widget components to retrieve 45 | the stats they display. 46 | 47 | **NOTE:** There is currently a one-to-one relationship between stats collectors 48 | and widgets. That is **not** a design enforcement - widgets are free to pull 49 | from any and all stats components (e.g. you could have a widget that renders 50 | memory and cpu information more compactly). 51 | 52 | ## gui (subdirectory) 53 | 54 | This is where all the UI rendering logic lives. Each module has a well defined 55 | purpose and that should be maintained. They are: 56 | 57 | 1. `gui/xcore.*` All xcb/cairo/pango setup and teardown logic lives here. It 58 | simply creates a window, sets the various window properties (there are 59 | many) and then tears it down. 60 | 2. `gui/xdraw.*` This defines a "drawing context" type called `xctx_t` that 61 | all drawing takes place on. It also provides a number of primitive drawing 62 | routines used by the widgets, such as `xdraw_printf()`, 63 | `xdraw_progressbar()`, `xdraw_chart()`, etc. The goal of this interface is 64 | to wrap all the common/usual drawing routines by the widgets and make them 65 | as streamlined as possible. 66 | 3. `gui/chart.*` This component holds the chart object used to hold and render 67 | historical data. 68 | 4. `gui/gui.*` This is an "orchestrator of widgets" .. it is responsible for 69 | containing widgets, mapped to "regions" of the display (left, center, and 70 | right-aligned stacks), and then rendering them in order. That is all. 71 | Ideally it maintains and manages no state. 72 | 73 | ## widgets (module + subdirectory) 74 | 75 | This `widgets.*` component in the root directory defines an interface used by 76 | the individual widgets defined in the `widgets/` subdirectory. This is a 77 | polymorphic design. The `widgets.*` component itself defines that interface 78 | and the routines to create all widgets, from recipes, add them to a gui, and 79 | track them for teardown on exit. 80 | 81 | TBD - document this widget piece more once it settles. 82 | -------------------------------------------------------------------------------- /gui/chart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "chart.h" 23 | 24 | struct chart* 25 | chart_init( 26 | size_t nsamples, 27 | size_t nseries, 28 | bool is_percents, 29 | const char *bgcolor, 30 | const char **colors) 31 | { 32 | struct chart *c; 33 | size_t i, j; 34 | 35 | if (0 == nseries || 0 == nsamples || NULL == bgcolor || NULL == colors) 36 | errx(1, "invalid chart parameters %zu %zu", nseries, nsamples); 37 | 38 | if (NULL == (c = malloc(sizeof(struct chart)))) 39 | err(1, "failed to malloc chart"); 40 | 41 | c->nseries = nseries; 42 | c->nsamples = nsamples; 43 | c->percents = is_percents; 44 | c->current = nsamples - 1; /* first update will be at 0 */ 45 | 46 | if (NULL == (c->values = calloc(nsamples, sizeof(double*)))) 47 | err(1, "chart calloc failed"); 48 | 49 | for (i = 0; i < nsamples; i++) 50 | if (NULL == (c->values[i] = calloc(nseries, sizeof(double)))) 51 | err(1, "charrt calloc failed (2)"); 52 | 53 | for (i = 0; i < nsamples; i++) 54 | for (j = 0; j < nseries; j++) 55 | c->values[i][j] = 0.0; 56 | 57 | if (NULL == (c->bgcolor = strdup(bgcolor))) 58 | err(1, "chart strdup failed"); 59 | 60 | if (NULL == (c->colors = calloc(nsamples, sizeof(char*)))) 61 | err(1, "chart colors calloc failed"); 62 | 63 | for (j = 0; j < nseries; j++) { 64 | if (NULL == (c->colors[j] = strdup(colors[j]))) 65 | err(1, "chart colors strdup failed(2)"); 66 | } 67 | 68 | return c; 69 | } 70 | 71 | void 72 | chart_free(struct chart *c) 73 | { 74 | size_t i; 75 | for (i = 0; i < c->nsamples; i++) 76 | free(c->values[i]); 77 | 78 | free(c->values); 79 | free(c->bgcolor); 80 | free(c); 81 | } 82 | 83 | void 84 | chart_update(struct chart *c, double data[]) 85 | { 86 | size_t cur = (c->current + 1) % c->nsamples; 87 | size_t i; 88 | 89 | for (i = 0; i < c->nseries; i++) { 90 | if (0 > data[i]) 91 | errx(1, "charts don't support negative values\n"); 92 | 93 | c->values[cur][i] = data[i]; 94 | } 95 | 96 | c->current = cur; 97 | } 98 | 99 | void 100 | chart_get_minmax(struct chart *c, double *min, double *max) 101 | { 102 | size_t i, j; 103 | *min = *max = c->values[0][0]; 104 | for (i = 0; i < c->nsamples; i++) { 105 | for (j = 0; j < c->nseries; j++) { 106 | if (c->values[i][j] > *max) 107 | *max = c->values[i][j]; 108 | 109 | if (c->values[i][j] < *min) 110 | *min = c->values[i][j]; 111 | } 112 | } 113 | } 114 | 115 | void 116 | chart_print(struct chart *c) 117 | { 118 | size_t i, j; 119 | 120 | printf("nseries: %zu\t\tnsamples: %zu\n", c->nseries, c->nsamples); 121 | printf("current: %zu\t\tpercents? %s\n", c->current, 122 | c->percents ? "YES" : "NO"); 123 | printf("bgcolor: '%s'\n", c->bgcolor); 124 | 125 | for (i = 0; i < c->nseries; i++) 126 | printf(" color[%zu] = '%s'\n", i, c->colors[i]); 127 | 128 | for (i = 0; i < c->nseries; i++) { 129 | for (j = 0; j < c->nsamples; j++) 130 | printf("%3.1f ", c->values[j][i]); 131 | 132 | printf("\n"); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # install locations 2 | PREFIX ?= /usr/local 3 | BINDIR ?= $(PREFIX)/bin 4 | MANDIR ?= $(PREFIX)/man/man1 5 | SHAREDIR ?= $(PREFIX)/share/oxbar 6 | 7 | # build & link flags 8 | CFLAGS += -c -std=c89 -Wall -Wextra -Werror -O2 9 | CFLAGS += `pkg-config --cflags pangocairo` 10 | LDFLAGS += -L/usr/X11R6/lib -lxcb -lxcb-icccm -lxcb-randr -lutil -lpthread -lm 11 | LDFLAGS += `pkg-config --libs pangocairo` 12 | 13 | # objects (OBJS = this dir, SOBJS = stats/*, GOBJS = giu/*, WOBJS = widgets/*) 14 | OBJS = settings.o widgets.o oxbar.o 15 | GOBJS = gui/chart.o gui/xcore.o gui/xdraw.o gui/gui.o 16 | SOBJS = stats/battery.o stats/brightness.o stats/cpu.o stats/memory.o \ 17 | stats/net.o stats/nprocs.o stats/stats.o stats/util.o \ 18 | stats/volume.o stats/wifi.o 19 | WOBJS = widgets/battery.o widgets/bright.o widgets/cpus.o widgets/cpushort.o \ 20 | widgets/cpuslong.o widgets/net.o widgets/nprocs.o widgets/memory.o \ 21 | widgets/time.o widgets/util.o widgets/volume.o widgets/wifi.o 22 | 23 | .PHONY: clean install testruns cppcheck scan-build iwyu gprof loc gource 24 | 25 | oxbar: $(OBJS) $(GOBJS) $(SOBJS) $(WOBJS) 26 | $(CC) -o $@ $(LDFLAGS) $(OBJS) $(GOBJS) $(SOBJS) $(WOBJS) 27 | 28 | $(GOBJS): 29 | $(MAKE) -C gui $(MFLAGS) objects 30 | 31 | $(SOBJS): 32 | $(MAKE) -C stats $(MFLAGS) objects 33 | 34 | $(WOBJS): 35 | $(MAKE) -C widgets $(MFLAGS) objects 36 | 37 | .c.o: 38 | $(CC) $(CFLAGS) $< 39 | 40 | all: oxbar 41 | $(MAKE) -C gui $(MFLAGS) $@ 42 | $(MAKE) -C stats $(MFLAGS) $@ 43 | $(MAKE) -C widgets $(MFLAGS) $@ 44 | 45 | clean: 46 | $(MAKE) -C gui $(MFLAGS) $@ 47 | $(MAKE) -C stats $(MFLAGS) $@ 48 | $(MAKE) -C widgets $(MFLAGS) $@ 49 | @echo make clean \(local\) 50 | rm -f $(OBJS) 51 | rm -f oxbar 52 | rm -f oxbar.core 53 | 54 | install: 55 | $(MAKE) -C man $(MFLAGS) $@ 56 | install oxbar $(BINDIR) 57 | install -d $(SHAREDIR) 58 | install -m 644 sample.oxbar.conf $(SHAREDIR) 59 | 60 | # some simple test runs that work the gui/widget logic 61 | testruns: 62 | @echo just sigint / ctrl-c these 63 | ./testruns.sh 64 | @echo all done 65 | 66 | # clang-analyzer (should ALWAYS be clean) 67 | cppcheck: 68 | cppcheck --quiet --std=c89 -I/usr/include --enable=all --force . 69 | 70 | # cppcheck (should ALWAYS be clean) 71 | scan-build: clean 72 | scan-build --status-bugs make 73 | 74 | # run include-what-you-use (identify includes that are missing/extra) 75 | iwyu: 76 | make -k CC=include-what-you-use 77 | 78 | # gprof / memory profiler run and visualize output 79 | gprof: clean 80 | CC=gcc CFLAGS="-g -pg -fno-pie -fPIC" LDFLAGS="-g -pg -fno-pie -lc" $(MAKE) 81 | @echo Kill this oxbar with control-c and then view gprof.[analysis|png]. 82 | @echo NOTE: longer runs produce tighter results / smaller chart. 83 | ./oxbar 84 | gprof oxbar gmon.out > gprof.analysis 85 | gprof2dot gprof.analysis | dot -Tpng -o gprof.png 86 | 87 | # rebuild todo file based on all "TODO" comments in code 88 | TODO:: 89 | grep -nr TODO * \ 90 | | grep -v '^TODO' \ 91 | | grep -v '^README.md' \ 92 | | grep -v '^CONTRIBUTING.md' \ 93 | | grep -v '^Makefile' > $@ 94 | 95 | # report # of lines per flie 96 | loc:: 97 | cloc . > loc 98 | cloc --by-file . >> loc 99 | @echo >> loc 100 | @echo >> loc 101 | @echo Lines in core oxbar >> loc 102 | wc -l `find . -name "*.c" -a ! -name "*.d.c"` >> loc 103 | @echo Lines in tests and drivers >> loc 104 | wc -l `find . -name "*.d.c" -o -name "*.t.cc"` >> loc 105 | @echo Lines in build setup >> loc 106 | wc -l `find . -name "Makefile" \ 107 | -o -name "testruns.sh" \ 108 | -o -name "*.conf"` >> loc 109 | cat loc 110 | 111 | # rebuild the architecture image showing #include dependencies 112 | tree.png:: 113 | cinclude2dot --paths --merge module --exclude '.t.c|.d.c' > source.dot 114 | dot -Tpng -Grankdir=LR -Gratio=fill source.dot > $@ 115 | rm source.dot 116 | 117 | # run gource on the repo / a visualization of activity over time 118 | gource: 119 | gource -f -c 4 -a 1 120 | -------------------------------------------------------------------------------- /gui/chart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef CHART_H 18 | #define CHART_H 19 | 20 | #include 21 | #include 22 | 23 | /* 24 | * A chart is a set of N sampls of M distinct series, where all sampled values 25 | * are doubles representing either percentages or raw values. If values are 26 | * percentages, they are on the scale of 0-100, not 0-1, and the values for 27 | * all series for a given sample should sum to 100 (or reasonably close). 28 | * 29 | * The chart also contains a background color (for the whole chart) as well 30 | * as a color for each series. 31 | * 32 | * Example: 33 | * If you sample the 3 memory stats (% active/total/free) for 60 seconds, 34 | * you would want a chart with nseries = 3, nsamples = 60, and percents = true. 35 | */ 36 | 37 | struct chart { 38 | size_t nseries; /* how many distinct series are in the chart */ 39 | size_t nsamples; /* how many samples of each series there are */ 40 | size_t current; /* index of current SAMPLE */ 41 | bool percents; /* true = all values are percents, false = raw */ 42 | double **values; /* the nseries x nsamples array of percents */ 43 | char *bgcolor; /* background color of the chart */ 44 | char **colors; /* array of nsamples - colors for each sample */ 45 | }; 46 | 47 | /* 48 | * Initialize a new chart object. The parameters are: 49 | * nsamples the number of distinct SAMPLES of each SERIES 50 | * nseries the number of each THINGS being tracked 51 | * is_percents are the values percentages (0-1.0) or raw (any value)? 52 | * bgcolor string color (hex2rgba) for the background of the chart 53 | * colors array of colors for each series of the charts. There should 54 | * be exactly NSERIES colors in this array. 55 | * 56 | * Example: to track the memory usage of a system for 10 seconds, we would do 57 | * the following... 58 | * nseries => 3 (we track total, active, and free memory) 59 | * nsamples => 10 (assuming we track 1 sample per second) 60 | * is_percents => false (we track raw values as doubles, and let the chart 61 | * scale it. CPU usage is an example where you natively get 62 | * percentages) 63 | * bgcolor => "#444" (a nice gray background) 64 | * colors => [ "#f00", "#ff0", "#0f0" ] / an array of red/yellow/blue 65 | * to color the total/active/free memory. 66 | * XXX note that the color order sets the order of which 67 | * series should be added when updating. 68 | */ 69 | struct chart* 70 | chart_init( 71 | size_t nsamples, 72 | size_t nseries, 73 | bool is_percents, 74 | const char *bgcolor, 75 | const char **colors); 76 | 77 | /* Free all allocated memory with a chart */ 78 | void chart_free(struct chart *c); 79 | 80 | /* Update a chart with an array of data, where size of data == c->nseries */ 81 | void chart_update(struct chart *c, double data[]); 82 | 83 | /* Determine the min & max values in a chart's history (for scaling displays) */ 84 | void chart_get_minmax(struct chart *c, double *min, double *max); 85 | 86 | /* Debug utility: print all data in a chart */ 87 | void chart_print(struct chart *c); 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /gui/xcore.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef XINFO_H 18 | #define XINFO_H 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | /* pango font wrapper struct & setup/teardown methods */ 27 | 28 | struct xfont_settings { /* user provided settings for xfont */ 29 | char *desc; /* free-form font description string */ 30 | char *fgcolor; /* default foreground color for text */ 31 | }; 32 | 33 | struct xfont { /* core xfont struct (read-only) */ 34 | struct xfont_settings *settings; 35 | PangoFontDescription *pfont; /* pango font loaded from that string */ 36 | int height;/* derived font height (in pixels) */ 37 | }; 38 | 39 | struct xfont *xfont_init(struct xfont_settings *settings); 40 | void xfont_free(struct xfont *xf); 41 | 42 | /* xcb / display-info struct & setup/teardown methods */ 43 | struct xdisp { 44 | uint16_t display_width; 45 | uint16_t display_height; 46 | xcb_connection_t *con; 47 | xcb_screen_t *root_screen; 48 | xcb_visualtype_t *root_visual; 49 | }; 50 | 51 | struct xdisp *xdisp_init(); 52 | void xdisp_free(struct xdisp *x); 53 | 54 | /* xcb / window & cairo wrapper struct & setup/teardown methods */ 55 | 56 | struct xwin_settings { /* user provided settings */ 57 | char *bgcolor; /* default background color for whole window */ 58 | char *wname; /* name of window for window manager */ 59 | int x, y; /* (x,y) pixel coordinates of top-left corner */ 60 | int w, h; /* (width,height) pixel dimensions of window */ 61 | }; 62 | 63 | struct xwin { /* core xwin struct (read-only) */ 64 | struct xwin_settings *settings; 65 | struct xdisp *xdisp; /* x display server */ 66 | xcb_drawable_t window; /* oxbar xwindow */ 67 | cairo_surface_t *surface;/* core cairo surface mapped to X */ 68 | cairo_t *cairo; /* core cairo object for rendering */ 69 | }; 70 | 71 | struct xwin *xwin_init(struct xdisp *xdisp, struct xwin_settings *settings); 72 | void xwin_free(struct xwin *w); 73 | 74 | /* 75 | * Double buffering API for an xwin. When starting the main draw loop, 76 | * call xwin_push() to create a new buffer and clear it with the background 77 | * color. Once the main draw loop is done, call xwin_pop() to render that 78 | * buffer to the screen and flush it to the display. 79 | */ 80 | void xwin_push(struct xwin *w); /* double buffer: push buffer & clear it */ 81 | void xwin_pop(struct xwin *w); /* double buffer: pop buffer & render it */ 82 | 83 | /* 84 | * A universal method to translate colors to r/g/b/a components. 85 | * The input string is a hex color like "#ff0000" (red). The leading '#' is 86 | * optional. The color spec can have 3 or 4 components, where the 4th is an 87 | * alpha component, so "#ff000088" is ~50% transparent red (it will blend with 88 | * what's behind it). 89 | * Each component can be on a 256 scale (like "#ff0000" where each component 90 | * takes two hexits), or a 16 scale (like "#f00", also red, where each 91 | * component takes a single hexit). 92 | */ 93 | void hex2rgba(const char *s, double *r, double *g, double *b, double *a); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /gui/xdraw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef XDRAW_H 18 | #define XDRAW_H 19 | 20 | #include 21 | #include 22 | 23 | #include "chart.h" 24 | #include "xcore.h" 25 | 26 | /* 27 | * struct xctx: A stateful context for rendering widgets sequentially. 28 | * All drawing in the gui and widgets is done ONTO a xctx context. 29 | * Specifically, all the drawing primitives below draw onto such a context, 30 | * and the context tracts advancing the "pen" when drawing. E.g. when drawing 31 | * left-to-right (L2R), it advances the x-offset after each drawing primitive 32 | * below, so that the next primitive knows where to start. This encapsulation 33 | * greatly simplifies the calling code, eliminating much boilerplate code. 34 | * 35 | * Note that a "root" context is one that's *actually* rendered to the screen. 36 | * As such, a typical pipeline will create a temporary context, render a bunch 37 | * of primitives to it, and then draw that context onto a "root" context 38 | * using xdraw_context(root, source). 39 | * 40 | * TODO This abstraction should also permit vertical rendering (for a vertical 41 | * bar) rather easily, but that hasn't been a priority yet. 42 | */ 43 | 44 | typedef enum { 45 | L2R, 46 | R2L, 47 | CENTERED, 48 | } xctx_direction_t; 49 | 50 | typedef enum { 51 | BEFORE_RENDER, 52 | AFTER_RENDER 53 | } xctx_state_t; 54 | 55 | struct padding { 56 | double top, bottom, left, right; 57 | }; 58 | 59 | struct xctx { 60 | bool is_root; 61 | xctx_direction_t direction; 62 | struct xfont *xfont; 63 | cairo_t *cairo; 64 | cairo_surface_t *surface; 65 | int h, w; 66 | struct padding *padding; 67 | double xoffset; 68 | double yoffset; 69 | }; 70 | 71 | struct xctx *xctx_init_root(struct xfont *font, struct xwin *win, 72 | xctx_direction_t direction, struct padding *padding); 73 | struct xctx *xctx_init_scratchpad(struct xfont *font, struct xwin *win, 74 | xctx_direction_t direction, struct padding *padding); 75 | 76 | void xctx_free(struct xctx *ctx); 77 | void xctx_reset(struct xctx *ctx); 78 | void xctx_complete(struct xctx *ctx); 79 | void xctx_advance(struct xctx *ctx, xctx_state_t state, double xplus, double yplus); 80 | 81 | /* 82 | * Drawing Primitives 83 | * All widget rendering is done using these simple primitives (so far) 84 | */ 85 | 86 | /* draw one context onto another */ 87 | void 88 | xdraw_context( 89 | struct xctx *dest, 90 | struct xctx *source); 91 | 92 | /* draw a color over an entire context */ 93 | void 94 | xdraw_colorfill( 95 | struct xctx *ctx, 96 | const char *const color); 97 | 98 | /* draw a colored headerline on a widget */ 99 | 100 | typedef enum { 101 | NONE, /* don't show them at all */ 102 | ABOVE, /* show the headers above the widget in the padding region */ 103 | BELOW /* show the headers below the widget in the padding region */ 104 | } header_style_t; 105 | 106 | void 107 | xdraw_headerline( 108 | struct xctx *ctx, 109 | header_style_t style, 110 | const char *color); 111 | 112 | /* draw some colored text (printf(3) style) */ 113 | void 114 | xdraw_printf( 115 | struct xctx *ctx, 116 | const char *color, 117 | const char *fmt, 118 | ...); 119 | 120 | /* draw simple progress bar showing some % completion */ 121 | void 122 | xdraw_progress_bar( 123 | struct xctx *ctx, 124 | const char *bgcolor, 125 | const char *pgcolor, 126 | double width, 127 | double pct); 128 | 129 | /* draw a historical bar chart */ 130 | void 131 | xdraw_chart( 132 | struct xctx *ctx, 133 | struct chart *chart); 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # oxbar 2 | oxbar is a X11 status bar for OpenBSD showing various system stats. 3 | It has a configurable display and works out-of-the-box on most modern window 4 | managers in an intuitive fashion. 5 | oxbar supports FreeType font rendering and styling, true transparency & alpha 6 | blending on all UI components (including the root window), and a simple 7 | configuration format that can concisely support multiple themes. 8 | 9 | It's motivated by the frequent complaints/threats I get about 10 | my old xstatbar and its many hacks. Shaming works 'yo. 11 | 12 | oxbar is released under an 13 | [ISC license](https://github.com/ryanflannery/oxbar/blob/master/LICENSE) 14 | 15 | ![screenshot](images/fullscreen.png?raw=true) 16 | 17 | 18 | # features 19 | * True transparency support with a compositing window manager 20 | * I recommend compton (in ports) over xcompmgr (in base) 21 | * FreeType fonts styled & rendered easily, with all font options 22 | * Fully configurable display via the command line or config file 23 | * Left/Right/Center aligned widgets, and any combination of those 24 | * Configuration file supports multiple themes that can be chosen at runtime 25 | * Types of stats supported: 26 | * Battery/AC status, progress bar, time remaining 27 | * Brightness level w/ progress bar (via Xrandr(3)) 28 | * Volume level w/ progress bar 29 | * Number of processes 30 | * Memory usage & breakdown 31 | * CPUs usage & breakdown w/ or w/out charts 32 | * WiFi signal strength 33 | * Current date/time (is that a status?) 34 | * Others forthcoming 35 | 36 | 37 | # more screenshots 38 | oxbar's default look (with no options): 39 | ![default](images/theme-default.png?raw=true) 40 | 41 | Other themes, all included in the file 42 | [sample.oxbar.conf](sample.oxbar.conf): 43 | 44 | **islands**: each widget is an island, with true transparency between 45 | ![islands](images/theme-islands.png?raw=true) 46 | 47 | **islands-colorful**: like islands, but each widget is a different color 48 | ![islands-colorful](images/theme-islands-colorful.png?raw=true) 49 | 50 | **minimal**: a dark, text only display 51 | ![minimal](images/theme-minimal.png?raw=true) 52 | 53 | **pastels**: a pastel based theme with widgets tightly packed 54 | ![pastels](images/theme-pastels.png?raw=true) 55 | 56 | **ryan**: what my setup looks like 57 | ![ryan](images/theme-ryan.png?raw=true) 58 | 59 | **xstatbar**: looks just like it's predecessor 60 | ![xstatbar](images/theme-xstatbar.png?raw=true) 61 | 62 | 63 | # installing 64 | There is no port/package (yet), as oxbar is still under active development. 65 | To build & install, you'll need to first install 2 dependencies, pango and 66 | cairo, and then clone this repo and run `make install`. 67 | 68 | Roughly: 69 | ```bash 70 | $ doas pkg_add pango cairo # install dependencies (as root) 71 | $ make # build oxbar 72 | $ doas make install # install globally (as root) 73 | -or- 74 | $ PREFIX=~/local make install # install local to a user (or anywhere) 75 | ``` 76 | 77 | 78 | # usage 79 | Full man page available here: 80 | [oxbar(1)](http://htmlpreview.github.io/?https://raw.githubusercontent.com/ryanflannery/oxbar/master/man/oxbar.html). 81 | 82 | `oxbar -H` also has a brief description of each command line flag. 83 | See the sample configuration [sample.oxbar.conf](sample.oxbar.conf) for 84 | examples, like the themes above. 85 | 86 | 87 | # i liked xstatbar's look 88 | You can achieve that using the included sample configuration file, saved as 89 | `~/.oxbar.conf`, and run oxbar via: 90 | ```bash 91 | oxbar xstatbar 92 | ``` 93 | 94 | 95 | # outstanding stuff, prioritized 96 | See the [TODO](TODO) file for various TODO's present throughout the code. 97 | 98 | In addition, more long-term stuff I'd like to do, by my priority... 99 | * big refactor: make all widgets 100% config-driven... Basically, eliminate 100 | the need for individual widget code in `widgets/` entirely, and make them 101 | all configurable via a simple syntax. I know how to do most of this, and 102 | easily from a configuration standpoint, but not all. My current thoughts 103 | would make the configuration too verbose/lengthy, and impractical. Chew on 104 | this more, I will... 105 | * gui: icons in the display could help condense it further 106 | * stats: add collector for hw.sensors & a related widget 107 | * stats: add a weather component...i like weather 108 | * when using compton, need '--shadow-exclude 'name = "oxbar"' to disable 109 | shadow - how can i automate that? 110 | -------------------------------------------------------------------------------- /gui/gui.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "gui.h" 23 | #include "xdraw.h" 24 | 25 | /* private functions */ 26 | static void free_widget_list(struct widget_list*); 27 | static void draw_widget(struct gui*, struct xctx*, struct widget*); 28 | static void draw_widget_list(struct gui*, struct widget_list*,xctx_direction_t); 29 | 30 | struct gui* 31 | gui_init(struct xfont *xfont, struct xwin *xwin, struct gui_settings *settings) 32 | { 33 | struct gui *gui = malloc(sizeof(struct gui)); 34 | if (NULL == gui) 35 | err(1, "failed to malloc gui"); 36 | 37 | gui->xfont = xfont; 38 | gui->xwin = xwin; 39 | gui->s = settings; 40 | 41 | TAILQ_INIT(&gui->left); 42 | TAILQ_INIT(&gui->center); 43 | TAILQ_INIT(&gui->right); 44 | return gui; 45 | } 46 | 47 | static void 48 | free_widget_list(struct widget_list *widgets) 49 | { 50 | struct widget_list_entry *wle = NULL; 51 | while (!TAILQ_EMPTY(widgets)) { 52 | wle = TAILQ_FIRST(widgets); 53 | TAILQ_REMOVE(widgets, wle, widget_entry); 54 | free(wle); 55 | } 56 | } 57 | 58 | void 59 | gui_free(struct gui *gui) 60 | { 61 | free_widget_list(&gui->left); 62 | free_widget_list(&gui->center); 63 | free_widget_list(&gui->right); 64 | free(gui); 65 | } 66 | 67 | void 68 | gui_add_widget(struct gui *gui, xctx_direction_t direction, struct widget* w) 69 | { 70 | struct widget_list_entry *wle; 71 | if (NULL == (wle = malloc(sizeof(struct widget_list_entry)))) 72 | err(1, "failed to malloc widget list entry"); 73 | 74 | wle->widget = w; 75 | switch (direction) { 76 | case L2R: 77 | TAILQ_INSERT_TAIL(&gui->left, wle, widget_entry); 78 | break; 79 | case CENTERED: 80 | TAILQ_INSERT_TAIL(&gui->center, wle, widget_entry); 81 | break; 82 | case R2L: 83 | TAILQ_INSERT_TAIL(&gui->right, wle, widget_entry); 84 | break; 85 | } 86 | } 87 | 88 | static void 89 | draw_widget(struct gui *gui, struct xctx *dest, struct widget *w) 90 | { 91 | struct xctx *scratchpad = xctx_init_scratchpad(gui->xfont, gui->xwin, 92 | L2R, &gui->s->padding); 93 | 94 | if (0 != strlen(gui->s->widget_bgcolor)) 95 | xdraw_colorfill(scratchpad, gui->s->widget_bgcolor); 96 | 97 | if (0 != strlen(*w->bgcolor)) 98 | xdraw_colorfill(scratchpad, *w->bgcolor); 99 | 100 | if (0 == strlen(*w->fgcolor)) 101 | *w->fgcolor = scratchpad->xfont->settings->fgcolor; 102 | 103 | w->draw(w->state, scratchpad); 104 | xctx_complete(scratchpad); 105 | xdraw_headerline(scratchpad, gui->s->header_style, *w->hdcolor); 106 | xdraw_context(dest, scratchpad); 107 | xctx_free(scratchpad); 108 | } 109 | 110 | static void 111 | draw_widget_list( 112 | struct gui *gui, 113 | struct widget_list *widgets, 114 | xctx_direction_t direction) 115 | { 116 | struct widget_list_entry *wle = NULL; 117 | struct xctx *root = xctx_init_root(gui->xfont, gui->xwin, direction, 118 | &gui->s->margin); 119 | struct xctx *temp = xctx_init_scratchpad(gui->xfont, gui->xwin, L2R, 120 | NULL); 121 | 122 | TAILQ_FOREACH(wle, widgets, widget_entry) { 123 | if (wle->widget->enabled(wle->widget->state)) { 124 | draw_widget(gui, temp, wle->widget); 125 | if (NULL != TAILQ_NEXT(wle, widget_entry)) 126 | xctx_advance(temp, AFTER_RENDER, 127 | gui->s->spacing, 0); 128 | } 129 | } 130 | 131 | xctx_complete(temp); 132 | xdraw_context(root, temp); 133 | xctx_free(temp); 134 | xctx_free(root); 135 | } 136 | 137 | void 138 | gui_draw(struct gui *gui) 139 | { 140 | xwin_push(gui->xwin); 141 | draw_widget_list(gui, &gui->left, L2R); 142 | draw_widget_list(gui, &gui->center, CENTERED); 143 | draw_widget_list(gui, &gui->right, R2L); 144 | xwin_pop(gui->xwin); 145 | } 146 | -------------------------------------------------------------------------------- /gui/xcore.d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /* 18 | * Test driver (system test) for xcore.* components. 19 | * Compile and run: 20 | * ./xcore.d [ xfont | xdisp | xwin ] 21 | * 22 | * xfont 23 | * Let's you test typing in font descriptions and see if they can load 24 | * and what they load to. If any font fails, process exits. 25 | * 26 | * xdisp 27 | * Connect to display and reports width/height of full X display. 28 | * 29 | * xwin 30 | * Sample showing connection to xcb, making a window, and then testing 31 | * the cairo setup within xwin. 32 | */ 33 | 34 | #include 35 | #include 36 | #include "xcore.h" 37 | 38 | void 39 | test_font(char *description) 40 | { 41 | struct xfont_settings s = { 42 | .desc = description, 43 | .fgcolor = "ff0000" 44 | }; 45 | struct xfont *f = xfont_init(&s); 46 | printf("%s :: family '%s' height: %d\n", 47 | 0 == f->height ? "FAILED!" : "GOOD", 48 | pango_font_description_get_family(f->pfont), 49 | f->height); 50 | xfont_free(f); 51 | } 52 | 53 | int 54 | main_xfont() 55 | { 56 | size_t lsize = 100; 57 | char *line = malloc(lsize); 58 | if (NULL == line) 59 | err(1, "malloc failed"); 60 | 61 | printf("Now enter font descriptions to see how pango parses them.\n"); 62 | printf("Enter one per line and hit enter. We'll use pango to parse\n"); 63 | printf("it and see if it loads.\n\n"); 64 | printf("Hit control-d to exit\n"); 65 | for (printf("$ "); -1 != getline(&line, &lsize, stdin); printf("$ ")) 66 | test_font(line); 67 | 68 | printf("bye\n"); 69 | free(line); 70 | return 0; 71 | } 72 | 73 | 74 | int 75 | main_xdisp() 76 | { 77 | struct xdisp *x = xdisp_init(); 78 | printf("display: %d x %d\n", x->display_width, x->display_height); 79 | xdisp_free(x); 80 | return 0; 81 | } 82 | 83 | int 84 | main_xwin() 85 | { 86 | struct xdisp *x = xdisp_init(); 87 | printf("display: %d x %d\n", x->display_width, x->display_height); 88 | 89 | struct xwin_settings s = { 90 | .bgcolor = "#ff0000", 91 | .wname = "xcore.d :: xwin test", 92 | .x = 500, .y = 500, 93 | .w = 500, .h = 500 94 | }; 95 | struct xwin *w = xwin_init(x, &s); 96 | 97 | /* start double buffer - NOTE you must do this w/ xcb backend + alpha */ 98 | cairo_push_group(w->cairo); 99 | 100 | /* draw background (light gray / alpha is 0.1) */ 101 | cairo_set_source_rgba(w->cairo, 0, 0, 0, 0.1); 102 | cairo_paint(w->cairo); 103 | 104 | /* draw red square */ 105 | cairo_set_source_rgba(w->cairo, 1, 0, 0, 0.5); 106 | cairo_rectangle(w->cairo, 50, 50, 200, 200); 107 | cairo_fill(w->cairo); 108 | 109 | /* draw green square */ 110 | cairo_set_source_rgba(w->cairo, 0, 1, 0, 0.5); 111 | cairo_rectangle(w->cairo, 150, 150, 200, 200); 112 | cairo_fill(w->cairo); 113 | 114 | /* draw blue square */ 115 | cairo_set_source_rgba(w->cairo, 0, 0, 1, 0.5); 116 | cairo_rectangle(w->cairo, 250, 250, 200, 200); 117 | cairo_fill(w->cairo); 118 | 119 | /* copy buffer back to root (that's all of the next 4 lines) */ 120 | cairo_pop_group_to_source(w->cairo); 121 | cairo_set_operator(w->cairo, CAIRO_OPERATOR_SOURCE); 122 | cairo_paint(w->cairo); 123 | cairo_set_operator(w->cairo, CAIRO_OPERATOR_OVER); 124 | 125 | xcb_flush(x->con); 126 | 127 | printf("You should now see a transparent gray box with 3 squares.\n"); 128 | printf("Move the windows behind the window to ensure the transparency is\n"); 129 | printf("true and working correctly.\n\n"); 130 | printf("Hit enter to continue"); 131 | getchar(); 132 | 133 | printf("bye\n"); 134 | xwin_free(w); 135 | xdisp_free(x); 136 | return 0; 137 | } 138 | 139 | int 140 | main(int argc, char *argv[]) 141 | { 142 | if (2 != argc) { 143 | printf("usage: %s [ xfont | xdisp | xwin ]\n", argv[0]); 144 | return 1; 145 | } 146 | 147 | if (0 == strcmp("xfont", argv[1])) 148 | return main_xfont(); 149 | else if (0 == strcmp("xdisp", argv[1])) 150 | return main_xdisp(); 151 | else if (0 == strcmp("xwin", argv[1])) 152 | return main_xwin(); 153 | 154 | printf("unknown option '%s'\n", argv[1]); 155 | return 1; 156 | } 157 | -------------------------------------------------------------------------------- /stats/brightness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "brightness.h" 28 | 29 | /* all the xcb/xrandr private local state */ 30 | static xcb_connection_t *x; 31 | static xcb_generic_error_t *error; 32 | static xcb_intern_atom_cookie_t cookie; 33 | static xcb_intern_atom_reply_t *reply; 34 | static xcb_atom_t atom; 35 | static xcb_screen_iterator_t si; 36 | static xcb_screen_t *screen; 37 | static xcb_window_t window; 38 | 39 | static xcb_randr_get_screen_resources_current_cookie_t rec_cookie; 40 | static xcb_randr_get_screen_resources_current_reply_t *rec_reply; 41 | static xcb_randr_output_t *outputs; 42 | static xcb_randr_query_output_property_cookie_t query_cookie; 43 | static xcb_randr_query_output_property_reply_t *query_reply; 44 | 45 | static int32_t max_backlight; 46 | static int32_t min_backlight; 47 | /* 48 | * if http had been designed like the x11 protocol, the internet wouldn't have 49 | * happened... 50 | */ 51 | 52 | void 53 | brightness_init(struct brightness_stats *stats) 54 | { 55 | stats->is_setup = false; 56 | xcb_randr_get_output_property_cookie_t prop_cookie; 57 | xcb_randr_get_output_property_reply_t *prop_reply; 58 | 59 | x = xcb_connect(NULL, NULL); 60 | cookie = xcb_intern_atom(x, 0, strlen("Backlight"), "Backlight"); 61 | reply = xcb_intern_atom_reply(x, cookie, NULL); 62 | if (!reply) { 63 | warnx("xcb atom reply failed for Backlight"); 64 | return; 65 | } 66 | 67 | atom = reply->atom; 68 | free(reply); 69 | 70 | if (XCB_ATOM_NONE == atom) 71 | warnx("no xcb atom for Backlight"); 72 | 73 | si = xcb_setup_roots_iterator(xcb_get_setup(x));; 74 | screen = si.data; 75 | window = screen->root; 76 | 77 | rec_cookie = xcb_randr_get_screen_resources_current(x, window); 78 | rec_reply = xcb_randr_get_screen_resources_current_reply(x, rec_cookie, 79 | &error); 80 | outputs = xcb_randr_get_screen_resources_current_outputs(rec_reply); 81 | 82 | prop_cookie = xcb_randr_get_output_property(x, outputs[0], atom, 83 | XCB_ATOM_NONE, 0, 4, 0, 0); 84 | prop_reply = xcb_randr_get_output_property_reply(x, prop_cookie, 85 | &error); 86 | 87 | if (NULL == prop_reply 88 | || XCB_ATOM_INTEGER != prop_reply->type 89 | || 1 != prop_reply->num_items 90 | || 32 != prop_reply->format) { 91 | warnx("xcb randr backlight query failed\n"); 92 | return; 93 | } 94 | 95 | query_cookie = xcb_randr_query_output_property(x, outputs[0], atom); 96 | query_reply = xcb_randr_query_output_property_reply(x, query_cookie, 97 | &error); 98 | 99 | int32_t *scale; 100 | scale = xcb_randr_query_output_property_valid_values(query_reply); 101 | min_backlight = scale[0]; 102 | max_backlight = scale[1]; 103 | 104 | uint8_t value = *xcb_randr_get_output_property_data(prop_reply); 105 | stats->brightness = ((float)value - (float)min_backlight) 106 | / ((float)max_backlight - (float)min_backlight) 107 | * 100.0; 108 | 109 | free(prop_reply); 110 | stats->is_setup = true; 111 | } 112 | 113 | void 114 | brightness_update(struct brightness_stats *stats) 115 | { 116 | if (!stats->is_setup) 117 | return; 118 | 119 | xcb_randr_get_output_property_cookie_t prop_cookie; 120 | xcb_randr_get_output_property_reply_t *prop_reply; 121 | 122 | prop_cookie = xcb_randr_get_output_property(x, outputs[0], atom, 123 | XCB_ATOM_NONE, 0, 4, 0, 0); 124 | prop_reply = xcb_randr_get_output_property_reply(x, prop_cookie, 125 | &error); 126 | 127 | if (NULL == prop_reply 128 | || XCB_ATOM_INTEGER != prop_reply->type 129 | || 1 != prop_reply->num_items 130 | || 32 != prop_reply->format) 131 | warnx("xcb randr backlight query failed\n"); 132 | 133 | uint8_t value = *xcb_randr_get_output_property_data(prop_reply); 134 | stats->brightness = ((float)value - (float)min_backlight) 135 | / ((float)max_backlight - (float)min_backlight) 136 | * 100.0; 137 | free(prop_reply); 138 | } 139 | 140 | void 141 | brightness_close(struct brightness_stats *stats) 142 | { 143 | if (stats->is_setup) { 144 | free(query_reply); 145 | free(rec_reply); 146 | xcb_disconnect(x); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /stats/net.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "net.h" 37 | #include "util.h" 38 | 39 | /* private functions */ 40 | static void net_update_packets(struct net_stats*); 41 | static void get_rtaddrs(int, struct sockaddr*, struct sockaddr**); 42 | static void net_update_bytes(struct net_stats*); 43 | 44 | void 45 | net_init(struct net_stats *stats) 46 | { 47 | stats->iface = get_egress(); 48 | stats->is_setup = NULL != stats->iface; 49 | if (stats->is_setup) 50 | net_update(stats); /* to set initial counters */ 51 | } 52 | 53 | static void 54 | net_update_packets(struct net_stats *stats) 55 | { 56 | static struct ipstat current; 57 | static int mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS }; 58 | static size_t len = sizeof(current); 59 | 60 | if (-1 == sysctl(mib, sizeof(mib) / sizeof(mib[0]), ¤t, &len, NULL, 0)) 61 | err(1, "CTL_NET.PF_INET.IPPROTO_IP.IPCTL_STATS"); 62 | 63 | /* update inbound packets */ 64 | if (current.ips_total < stats->packets_in) 65 | stats->packets_in_new = ULONG_MAX - stats->packets_in 66 | + current.ips_total; 67 | else 68 | stats->packets_in_new = current.ips_total - stats->packets_in; 69 | 70 | /* update outbound packets */ 71 | if (current.ips_localout < stats->packets_out) 72 | stats->packets_out_new = ULONG_MAX - stats->packets_out 73 | + current.ips_localout; 74 | else 75 | stats->packets_out_new = current.ips_localout 76 | - stats->packets_out; 77 | 78 | stats->packets_in = current.ips_total; 79 | stats->packets_out = current.ips_localout; 80 | } 81 | 82 | /* 83 | * TODO Refactor network bytes logic below 84 | * I'm pretty sure this could be greatly simplified 85 | */ 86 | static void 87 | get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 88 | { 89 | int i; 90 | 91 | for (i = 0; i < RTAX_MAX; i++) { 92 | if (addrs & (1 << i)) { 93 | rti_info[i] = sa; 94 | sa = (struct sockaddr *)((char *)(sa) 95 | + roundup(sa->sa_len, sizeof(long))); 96 | } else 97 | rti_info[i] = NULL; 98 | } 99 | } 100 | 101 | static void 102 | net_update_bytes(struct net_stats *stats) 103 | { 104 | struct rt_msghdr *rtm; 105 | static int mib[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 106 | size_t sizeneeded = 0; 107 | char *buf = NULL; 108 | 109 | if (-1 == sysctl(mib, 6, NULL, &sizeneeded, NULL, 0)) 110 | err(1, "sysctl CTL_NET.PF_ROUTE.0.0.NET_RT_IFLIST.0 failed"); 111 | 112 | if (NULL == (buf = malloc(sizeneeded))) 113 | err(1, "%s: malloc failed", __FUNCTION__); 114 | 115 | if (-1 == sysctl(mib, 6, buf, &sizeneeded, NULL, 0)) 116 | err(1, "%s: sysctl2 failed", __FUNCTION__); 117 | 118 | char *lim = buf + sizeneeded; 119 | char *next; 120 | struct if_msghdr ifm; 121 | struct if_data *ifd; 122 | char name[IFNAMSIZ + 1]; 123 | struct sockaddr *sa, *rti_info[RTAX_MAX];; 124 | struct sockaddr_dl *sdl; 125 | 126 | for (next = buf; next < lim; next += rtm->rtm_msglen) { 127 | rtm = (struct rt_msghdr*)next; 128 | switch (rtm->rtm_type) { 129 | case RTM_IFINFO: 130 | bcopy(next, &ifm, sizeof(ifm)); 131 | ifd = &ifm.ifm_data; 132 | sa = (struct sockaddr*)(next + rtm->rtm_hdrlen); 133 | get_rtaddrs(ifm.ifm_addrs, sa, rti_info); 134 | sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; 135 | if (NULL == sdl || AF_LINK != sdl->sdl_family) 136 | continue; 137 | 138 | bzero(name, sizeof(name)); 139 | if (sdl->sdl_nlen >= IFNAMSIZ) 140 | memcpy(name, sdl->sdl_data, IFNAMSIZ - 1); 141 | else if (sdl->sdl_nlen > 0) 142 | memcpy(name, sdl->sdl_data, sdl->sdl_nlen); 143 | 144 | if (strcmp(stats->iface, name)) 145 | break; 146 | 147 | stats->bytes_in_new = ifd->ifi_ibytes 148 | - stats->bytes_in; 149 | stats->bytes_out_new = ifd->ifi_obytes 150 | - stats->bytes_out; 151 | stats->bytes_in = ifd->ifi_ibytes; 152 | stats->bytes_out = ifd->ifi_obytes; 153 | break; 154 | 155 | case RTM_NEWADDR: 156 | break; 157 | } 158 | } 159 | free(buf); 160 | } 161 | 162 | void 163 | net_update(struct net_stats *stats) 164 | { 165 | if (!stats->is_setup) 166 | return; 167 | 168 | net_update_packets(stats); 169 | net_update_bytes(stats); 170 | } 171 | 172 | void 173 | net_close(struct net_stats *stats) 174 | { 175 | if (stats->is_setup) 176 | free(stats->iface); 177 | } 178 | -------------------------------------------------------------------------------- /oxbar.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /* 18 | * Various outstanding stuff that doesn't belong elsewhere... 19 | * TODO allow configuration of interfaces used by net & wifi collectors 20 | * TODO polish error messages (err/errx calls) 21 | * TODO make window FLOAT & ALWAYS-ON-TOP properties set-able 22 | */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "widgets.h" 29 | #include "settings.h" 30 | #include "gui/gui.h" 31 | #include "gui/xcore.h" 32 | #include "stats/stats.h" 33 | 34 | static struct xfont *xfont = NULL; /* loaded pango font info */ 35 | static struct xdisp *xdisp = NULL; /* core x display (via xcb) info */ 36 | static struct xwin *xwin = NULL; /* oxbar's x window (xcb) info */ 37 | static struct gui *gui = NULL; /* oxbar's gui */ 38 | static struct settings settings; /* global settings for oxbar */ 39 | 40 | static pthread_t pt_stats_updater; /* update stats & draw every second */ 41 | static pthread_t pt_sig_handler; /* listen & respond to signals */ 42 | static pthread_t pt_gui; /* handle x events and redraw */ 43 | static pthread_mutex_t mutex_gui; /* guard all calls to gui */ 44 | 45 | volatile sig_atomic_t SIG_QUIT = 0; /* SIGKILL/SIGQUIT/exit flag */ 46 | volatile sig_atomic_t SIG_PAUSE = 0; /* suspend/sleep flag */ 47 | volatile sig_atomic_t SIG_CONT = 0; /* continue/wakeup flag */ 48 | volatile sig_atomic_t SIG_RELOAD = 0; /* SIGHUP/reload config flag */ 49 | 50 | void 51 | ignore_all_signals() 52 | { 53 | sigset_t set; 54 | if (sigfillset(&set)) 55 | err(1, "%s: sigfillset failed", __FUNCTION__); 56 | if (pthread_sigmask(SIG_SETMASK, &set, NULL)) 57 | errx(1, "%s: pthread_sigmask failed", __FUNCTION__); 58 | } 59 | 60 | void 61 | setup_gui() 62 | { 63 | xfont = xfont_init(&settings.font); 64 | 65 | if (-1 == settings.window.h) 66 | settings.window.h = xfont->height 67 | + settings.gui.padding.top + settings.gui.padding.bottom 68 | + settings.gui.margin.top + settings.gui.margin.bottom; 69 | 70 | if (-1 == settings.window.y) 71 | settings.window.y = xdisp->display_height - settings.window.h; 72 | 73 | if (-1 == settings.window.w) 74 | settings.window.w = xdisp->display_width; 75 | 76 | xwin = xwin_init(xdisp, &settings.window); 77 | gui = gui_init(xfont, xwin, &settings.gui); 78 | widgets_init(gui, &settings, &OXSTATS); 79 | gui_draw(gui); 80 | } 81 | 82 | void 83 | cleanup_gui() 84 | { 85 | widgets_free(); 86 | gui_free(gui); 87 | xwin_free(xwin); 88 | xfont_free(xfont); 89 | } 90 | 91 | /* thread: every 1 second, update stats and re-draw the gui */ 92 | void* 93 | thread_stats_updater() 94 | { 95 | ignore_all_signals(); 96 | while (1) { 97 | usleep(1000000); /* 1 second */ 98 | if (!SIG_PAUSE) { 99 | pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 100 | stats_update(); 101 | pthread_mutex_lock(&mutex_gui); 102 | gui_draw(gui); 103 | pthread_mutex_unlock(&mutex_gui); 104 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 105 | } 106 | } 107 | return NULL; 108 | } 109 | 110 | /* thread: x event loop (blocking & infinite) - redraw on certain events */ 111 | void* 112 | thread_gui() 113 | { 114 | ignore_all_signals(); 115 | xcb_generic_event_t *xevent; 116 | while ((xevent = xcb_wait_for_event(xdisp->con))) { 117 | switch (xevent->response_type & ~0x80) { 118 | case XCB_EXPOSE: 119 | pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 120 | pthread_mutex_lock(&mutex_gui); 121 | gui_draw(gui); 122 | pthread_mutex_unlock(&mutex_gui); 123 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 124 | break; 125 | default: 126 | break; 127 | } 128 | } 129 | return NULL; 130 | } 131 | 132 | void 133 | signal_handler(int sig) 134 | { 135 | switch (sig) { 136 | case SIGHUP: 137 | SIG_RELOAD = 1; 138 | break; 139 | case SIGINT: 140 | case SIGQUIT: 141 | case SIGTERM: 142 | SIG_QUIT = 1; 143 | break; 144 | case SIGTSTP: 145 | SIG_PAUSE = 1; 146 | break; 147 | case SIGCONT: 148 | SIG_CONT = 1; 149 | break; 150 | } 151 | } 152 | 153 | /* thread: just listen for signals and respond appropriately */ 154 | void* 155 | thread_sig_handler() 156 | { 157 | sigset_t set; 158 | if (sigemptyset(&set) 159 | || sigaddset(&set, SIGHUP) 160 | || sigaddset(&set, SIGINT) 161 | || sigaddset(&set, SIGQUIT) 162 | || sigaddset(&set, SIGTERM) 163 | || sigaddset(&set, SIGTSTP) 164 | || sigaddset(&set, SIGCONT)) 165 | err(1, "%s: sigaddset failed", __FUNCTION__); 166 | if (pthread_sigmask(SIG_SETMASK, &set, NULL)) 167 | errx(1, "%s: pthread_sigmask failed", __FUNCTION__); 168 | 169 | struct sigaction sig_act; 170 | sig_act.sa_flags = 0; 171 | sig_act.sa_handler = signal_handler; 172 | if (sigaction(SIGHUP, &sig_act, NULL) 173 | || sigaction(SIGINT, &sig_act, NULL) 174 | || sigaction(SIGQUIT, &sig_act, NULL) 175 | || sigaction(SIGTERM, &sig_act, NULL) 176 | || sigaction(SIGTSTP, &sig_act, NULL) 177 | || sigaction(SIGCONT, &sig_act, NULL)) 178 | err(1, "%s: failed to install signal handlers", __FUNCTION__); 179 | 180 | while (1) { 181 | usleep(100000); /* 1/10 second */ 182 | if (SIG_RELOAD) { 183 | pthread_mutex_lock(&mutex_gui); 184 | settings_reload_config(&settings); 185 | cleanup_gui(); 186 | setup_gui(); 187 | pthread_mutex_unlock(&mutex_gui); 188 | SIG_RELOAD = 0; 189 | } 190 | if (SIG_CONT) { 191 | SIG_PAUSE = 0; 192 | SIG_CONT = 0; 193 | } 194 | if (SIG_QUIT) { 195 | if (pthread_cancel(pt_gui) 196 | || pthread_cancel(pt_stats_updater) 197 | || pthread_cancel(pt_sig_handler)) 198 | errx(1, "failed to cancel ongoing pthreads"); 199 | } 200 | } 201 | return NULL; 202 | } 203 | 204 | int 205 | main(int argc, char *argv[]) 206 | { 207 | stats_init(); 208 | settings_init(&settings, argc, argv); 209 | xdisp = xdisp_init(); 210 | setup_gui(); 211 | 212 | /* 213 | * XXX Note pledge(2) will not work for oxbar :( 214 | * All the ioctl(2) calls and what-not in stats/ prohibit that. 215 | */ 216 | 217 | /* and we're running! start all threads */ 218 | if (pthread_create(&pt_sig_handler, NULL, thread_sig_handler, NULL) 219 | || pthread_create(&pt_stats_updater, NULL, thread_stats_updater, NULL) 220 | || pthread_create(&pt_gui, NULL, thread_gui, NULL)) 221 | errx(1, "failed to create pthreads"); 222 | 223 | /* wait for done (only from signal handler) */ 224 | if (pthread_join(pt_gui, NULL) 225 | || pthread_join(pt_stats_updater, NULL) 226 | || pthread_join(pt_sig_handler, NULL)) 227 | errx(1, "failed to join pthreads"); 228 | 229 | /* cleanup */ 230 | cleanup_gui(); 231 | xdisp_free(xdisp); 232 | stats_close(); 233 | 234 | return 0; 235 | } 236 | -------------------------------------------------------------------------------- /gui/xcore.t.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | extern "C" { 6 | #include "xcore.h" 7 | }; 8 | 9 | /* TODO either fix googletest's [ASSERT|EXPECT]_EXIT* on openbsd or switch */ 10 | 11 | /* xfont tests */ 12 | 13 | TEST(xfont, EmptyString_ShouldExit) 14 | { 15 | struct xfont_settings s = { 16 | .desc = (char*)"", 17 | .fgcolor = (char*)"" 18 | }; 19 | ASSERT_EXIT(xfont_init(&s), ::testing::ExitedWithCode(1), ""); 20 | } 21 | 22 | TEST(xfont, FixedUsingPt_ShouldWork) 23 | { 24 | struct xfont_settings s = { 25 | .desc = (char*)"fixed 12pt", 26 | .fgcolor = (char*)"" 27 | }; 28 | struct xfont *f = xfont_init(&s); 29 | ASSERT_EQ(f->height, 19); 30 | xfont_free(f); 31 | } 32 | 33 | TEST(xfont, FixedUsingPx_ShouldSucced) 34 | { 35 | struct xfont_settings s = { 36 | .desc = (char*)"fixed 12px", 37 | .fgcolor = (char*)"" 38 | }; 39 | struct xfont *f = xfont_init(&s); 40 | ASSERT_EQ(f->height, 12); 41 | xfont_free(f); 42 | } 43 | 44 | TEST(xfont, FixedUsingNoSuffix_ShouldSucced) 45 | { 46 | struct xfont_settings s = { 47 | .desc = (char*)"fixed 12", 48 | .fgcolor = (char*)"" 49 | }; 50 | struct xfont *f = xfont_init(&s); 51 | ASSERT_EQ(f->height, 16); 52 | xfont_free(f); 53 | } 54 | 55 | TEST(xfont, TimesBold48_ShouldSucceed) 56 | { 57 | struct xfont_settings s = { 58 | .desc = (char*)"Times Bold 48", 59 | .fgcolor = (char*)"" 60 | }; 61 | struct xfont *f = xfont_init(&s); 62 | ASSERT_EQ(f->height, 84); 63 | xfont_free(f); 64 | } 65 | 66 | TEST(xfont, TimesOrHelveticaBold8px_ShouldSucceed) 67 | { 68 | struct xfont_settings s = { 69 | .desc = (char*)"Times,Helvetica Bold 8px", 70 | .fgcolor = (char*)"" 71 | }; 72 | struct xfont *f = xfont_init(&s); 73 | ASSERT_EQ(f->height, 8); 74 | xfont_free(f); 75 | } 76 | 77 | TEST(xfont, XFontFree_ShouldSucceed) 78 | { 79 | struct xfont_settings s = { 80 | .desc = (char*)"Times,Helvetica Bold 8px", 81 | .fgcolor = (char*)"" 82 | }; 83 | struct xfont *f = xfont_init(&s); 84 | ASSERT_EQ(f->height, 8); 85 | xfont_free(f); 86 | } 87 | 88 | /* xdisp tests */ 89 | 90 | TEST(xdisp, Init_IsntNull) 91 | { 92 | struct xdisp *x = xdisp_init(); 93 | ASSERT_NE(x, NULL); 94 | } 95 | 96 | TEST(xdisp, Free_ShouldSucced) 97 | { 98 | struct xdisp *x = xdisp_init(); 99 | xdisp_free(x); 100 | } 101 | 102 | TEST(xdisp, Dimensions_AreReasonable) 103 | { 104 | struct xdisp *x = xdisp_init(); 105 | ASSERT_GT(x->display_width, 0); 106 | ASSERT_GT(x->display_height, 0); 107 | 108 | ASSERT_LT(x->display_width, 10000); 109 | ASSERT_LT(x->display_height, 10000); 110 | xdisp_free(x); 111 | } 112 | 113 | /* xwin tests */ 114 | 115 | TEST(xwin, Init_ShouldSucceed) 116 | { 117 | struct xwin_settings s = { 118 | .bgcolor = (char*) "ff0000", 119 | .wname = (char*) "test", 120 | .x = 1, .y = 2, 121 | .w = 3, .h = 4 122 | }; 123 | 124 | struct xdisp *x = xdisp_init(); 125 | struct xwin *w = xwin_init(x, &s); 126 | xwin_free(w); 127 | } 128 | 129 | TEST(xwin, Init_OutputSettingsShouldMatchInput) 130 | { 131 | struct xwin_settings s = { 132 | .bgcolor = (char*) "ff0000", 133 | .wname = (char*) "test", 134 | .x = 1, .y = 2, 135 | .w = 3, .h = 4 136 | }; 137 | 138 | struct xdisp *x = xdisp_init(); 139 | struct xwin *w = xwin_init(x, &s); 140 | ASSERT_STREQ(s.bgcolor, w->settings->bgcolor); 141 | ASSERT_STREQ(s.wname, w->settings->wname); 142 | ASSERT_EQ(s.x, w->settings->x); 143 | ASSERT_EQ(s.y, w->settings->y); 144 | ASSERT_EQ(s.w, w->settings->w); 145 | ASSERT_EQ(s.h, w->settings->h); 146 | xwin_free(w); 147 | } 148 | 149 | /* hex2rgba tests */ 150 | 151 | TEST(hex2rgba, EmptyString_ShouldExit) 152 | { 153 | double r, g, b, a; 154 | ASSERT_EXIT(hex2rgba("",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 155 | } 156 | 157 | TEST(hex2rgba, PoundEmptyString_ShouldExit) 158 | { 159 | double r, g, b, a; 160 | ASSERT_EXIT(hex2rgba("#",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 161 | } 162 | 163 | TEST(hex2rgba, FooString_ShouldExit) 164 | { 165 | double r, g, b, a; 166 | ASSERT_EXIT(hex2rgba("foo",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 167 | } 168 | 169 | TEST(hex2rgba, PoundFooString_ShouldExit) 170 | { 171 | double r, g, b, a; 172 | ASSERT_EXIT(hex2rgba("#foo",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 173 | } 174 | 175 | TEST(hex2rgba, OneTwoAndFiveNumbers_ShouldExit) 176 | { 177 | double r, g, b, a; 178 | ASSERT_EXIT(hex2rgba("f",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 179 | ASSERT_EXIT(hex2rgba("ff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 180 | ASSERT_EXIT(hex2rgba("fffff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 181 | } 182 | 183 | TEST(hex2rgba, PoundOneTwoAndFiveNumbers_ShouldExit) 184 | { 185 | double r, g, b, a; 186 | ASSERT_EXIT(hex2rgba("#f",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 187 | ASSERT_EXIT(hex2rgba("#ff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 188 | ASSERT_EXIT(hex2rgba("#fffff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 189 | } 190 | 191 | TEST(hex2rgba, SevenNineTenNumbers_ShouldExit) 192 | { 193 | double r, g, b, a; 194 | ASSERT_EXIT(hex2rgba("fffffff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 195 | ASSERT_EXIT(hex2rgba("fffffffff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 196 | ASSERT_EXIT(hex2rgba("ffffffffff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 197 | } 198 | 199 | TEST(hex2rgba, PoundSevenNineTenNumbers_ShouldExit) 200 | { 201 | double r, g, b, a; 202 | ASSERT_EXIT(hex2rgba("#fffffff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 203 | ASSERT_EXIT(hex2rgba("#fffffffff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 204 | ASSERT_EXIT(hex2rgba("#ffffffffff",&r,&g,&b,&a), ::testing::ExitedWithCode(1), ""); 205 | } 206 | 207 | TEST(hex2rgba, Red3_ShouldSucceed) 208 | { 209 | double r, g, b, a; 210 | hex2rgba("f00", &r, &g, &b, &a); 211 | ASSERT_EQ(r, 1.0); 212 | ASSERT_EQ(g, 0.0); 213 | ASSERT_EQ(b, 0.0); 214 | ASSERT_EQ(a, 1.0); 215 | } 216 | 217 | TEST(hex2rgba, PoundRed3_ShouldSucceed) 218 | { 219 | double r, g, b, a; 220 | hex2rgba("#f00", &r, &g, &b, &a); 221 | ASSERT_EQ(r, 1.0); 222 | ASSERT_EQ(g, 0.0); 223 | ASSERT_EQ(b, 0.0); 224 | ASSERT_EQ(a, 1.0); 225 | } 226 | 227 | TEST(hex2rgba, Red4_ShouldSucceed) 228 | { 229 | double r, g, b, a; 230 | hex2rgba("f003", &r, &g, &b, &a); 231 | ASSERT_EQ(r, 1.0); 232 | ASSERT_EQ(g, 0.0); 233 | ASSERT_EQ(b, 0.0); 234 | ASSERT_EQ(a, 0.2); 235 | } 236 | 237 | TEST(hex2rgba, PoundRed4_ShouldSucceed) 238 | { 239 | double r, g, b, a; 240 | hex2rgba("#f003", &r, &g, &b, &a); 241 | ASSERT_EQ(r, 1.0); 242 | ASSERT_EQ(g, 0.0); 243 | ASSERT_EQ(b, 0.0); 244 | ASSERT_EQ(a, 0.2); 245 | } 246 | 247 | TEST(hex2rgba, Red6_ShouldSucceed) 248 | { 249 | double r, g, b, a; 250 | hex2rgba("ff0000", &r, &g, &b, &a); 251 | ASSERT_EQ(r, 1.0); 252 | ASSERT_EQ(g, 0.0); 253 | ASSERT_EQ(b, 0.0); 254 | ASSERT_EQ(a, 1.0); 255 | } 256 | 257 | TEST(hex2rgba, PoundRed6_ShouldSucceed) 258 | { 259 | double r, g, b, a; 260 | hex2rgba("#ff0000", &r, &g, &b, &a); 261 | ASSERT_EQ(r, 1.0); 262 | ASSERT_EQ(g, 0.0); 263 | ASSERT_EQ(b, 0.0); 264 | ASSERT_EQ(a, 1.0); 265 | } 266 | 267 | TEST(hex2rgba, Red8_ShouldSucceed) 268 | { 269 | double r, g, b, a; 270 | hex2rgba("ff000033", &r, &g, &b, &a); 271 | ASSERT_EQ(r, 1.0); 272 | ASSERT_EQ(g, 0.0); 273 | ASSERT_EQ(b, 0.0); 274 | ASSERT_EQ(a, 0.2); 275 | } 276 | 277 | TEST(hex2rgba, PoundRed8_ShouldSucceed) 278 | { 279 | double r, g, b, a; 280 | hex2rgba("ff000033", &r, &g, &b, &a); 281 | ASSERT_EQ(r, 1.0); 282 | ASSERT_EQ(g, 0.0); 283 | ASSERT_EQ(b, 0.0); 284 | ASSERT_EQ(a, 0.2); 285 | } 286 | -------------------------------------------------------------------------------- /sample.oxbar.conf: -------------------------------------------------------------------------------- 1 | # This is a sample configuration file for oxbar. 2 | # By default, oxbar tries to load ~/.oxbar.conf on startup. 3 | # That can be changed using `-F /path/to/another.conf` on the command line. 4 | # Regardless of which config file oxbar loads, you can instruct a running 5 | # instance of oxbar to reload that config (and theme) while running by 6 | # sending it a HUP signal (typically just `pkill -HUP oxbar`). 7 | # 8 | # This sample configuration explains the format of the config file. Config 9 | # files are parsed with fparseln(3), which is rather robust. 10 | # 11 | # Lines starting with '#' are comments and ignored. 12 | 13 | # blank lines like the one above and below are ignored 14 | 15 | # most lines look something like this, and alter some setting about oxbar 16 | window.y = 0 17 | 18 | window.y = 0 # comments can also be at the end of a line 19 | 20 | # spacing can be flexible 21 | window.y=0 22 | window.y = 0 23 | 24 | # lines can be continued with a trailing '\' at end of a line 25 | window.y \ 26 | = \ 27 | 0 28 | 29 | # oxbar also supports "themes", which are a subset of settings in the config 30 | # file starting with a line like: 31 | # [ThemeName] 32 | # which are then optionally loaded at runtime by running oxbar like this: 33 | # $ oxbar [options] ThemeName 34 | # When run like that, all lines in the config file before ANY theme name 35 | # are treated as global and loaded, and then only lines AFTER [ThemeName], and 36 | # before any other theme definition, are loaded. If no such line [ThemeName] 37 | # appears in the config, oxbar reports an error and exits. 38 | 39 | # This is useful when you run multiple instances of oxbar (say one for the top 40 | # of your display and another at the bottom), or want to simply test different 41 | # visuals quickly and easily (remember you can use a `pkill -HUP oxbar` to 42 | # reload the config at runtime). 43 | # If you only ever run one instance of oxbar, you do not need to define themes. 44 | 45 | # Following that example, we now define some sample themes 46 | 47 | # Shows nprocs/cpu/memory/net info on the top, distributed across the 3 regions 48 | # Run via `oxbar top` 49 | [top] 50 | widgets = "< nprocs cpulong | memory > net" 51 | window.x = 0 52 | window.y = 0 53 | window.w = -1 54 | window.h = -1 55 | gui.header_style = below 56 | 57 | # Shows battery/time/volume distributed on the bottom 58 | # Run via `oxbar bottom` 59 | [bottom] 60 | widgets = "< volume | time > battery" 61 | window.x = 0 62 | window.y = -1 63 | window.w = -1 64 | window.h = -1 65 | gui.header_style = above 66 | 67 | # This is an "island" theme - each widget is visually separated from the next 68 | # Run via `oxbar islands` 69 | [islands] 70 | widgets = "nprocs cpu memory net > battery wifi bright volume time" 71 | font.fgcolor = "fff" 72 | window.x = 0 73 | window.y = 0 74 | window.w = -1 75 | window.h = -1 76 | window.bgcolor = "0000" # totally transparent 77 | gui.widget_bgcolor = "000" 78 | gui.spacing = 40 79 | gui.margin = 0 80 | gui.padding = "10 15 15 15" 81 | gui.header_style = NONE 82 | 83 | # A more colorful version of the above - each widget has a vibrant background 84 | # Run via `oxbar islands-colorful` 85 | [islands-colorful] 86 | widgets = "nprocs cpu memory net > battery wifi bright volume time" 87 | font.fgcolor = "fff" 88 | window.x = 0 89 | window.y = 0 90 | window.w = -1 91 | window.h = -1 92 | window.bgcolor = "0000" # totally transparent 93 | gui.widget_bgcolor = "000" 94 | gui.spacing = 40 95 | gui.margin = 0 96 | gui.padding = "10 10 10 10" 97 | gui.header_style = NONE 98 | font.fgcolor = "000" 99 | battery.bgcolor = "954e9e" 100 | bright.bgcolor = "bf676e" 101 | cpus.bgcolor = "ff9e00" 102 | memory.bgcolor = "009ece" 103 | net.bgcolor = "9ccf31" 104 | nprocs.bgcolor = "ce0000" 105 | time.bgcolor = "f7d708" 106 | volume.bgcolor = "9ccf31" 107 | wifi.bgcolor = "009ece" 108 | memory.chart_color_active = "f00" 109 | memory.chart_color_total = "ff0" 110 | memory.chart_color_free = "0f0" 111 | 112 | # This is an minimal theme - mostly text and just dark charts 113 | # Run via `oxbar minimal` 114 | [minimal] 115 | widgets = "nprocs cpu memory net > battery wifi bright volume time" 116 | font.fgcolor = "000" 117 | font.desc = "Helvetica 20px" 118 | window.x = 0 119 | window.y = 0 120 | window.w = -1 121 | window.h = -1 122 | window.bgcolor = "0000" # totally transparent 123 | gui.spacing = 20 124 | gui.margin = 0 125 | gui.padding = "2 10 20 10" 126 | gui.header_style = NONE 127 | battery.chart_width = 10 128 | battery.chart_bgcolor = "ccc" 129 | battery.chart_pgcolor = "000" 130 | battery.fgcolor_unplugged = "b00" 131 | bright.chart_width = 10 132 | bright.chart_bgcolor = "ccc" 133 | bright.chart_pgcolor = "000" 134 | volume.chart_width = 10 135 | volume.chart_bgcolor = "ccc" 136 | volume.chart_pgcolor = "000" 137 | cpus.chart_bgcolor = "ccc" 138 | cpus.chart_color_system = "000" 139 | cpus.chart_color_interrupt = "222" 140 | cpus.chart_color_user = "444" 141 | cpus.chart_color_nice = "666" 142 | cpus.chart_color_spin = "888" 143 | cpus.chart_color_idle = "bbb" 144 | memory.chart_bgcolor = "ccc" 145 | memory.chart_color_active = "000" 146 | memory.chart_color_total = "444" 147 | memory.chart_color_free = "bbb" 148 | net.inbound_chart_color_bgcolor = "ccc" 149 | net.inbound_chart_color_pgcolor = "000" 150 | net.inbound_text_fgcolor = "500" 151 | net.outbound_chart_color_bgcolor = "ccc" 152 | net.outbound_chart_color_pgcolor = "000" 153 | net.inbound_text_fgcolor = "050" 154 | time.format = "%A %d %B %Y %I:%M %p" 155 | 156 | # A more pastel-based color scheme, similar to default sparc setups from yore 157 | # Run via `oxbar pastel` 158 | [pastels] 159 | widgets = "nprocs cpu memory net > battery wifi bright volume time" 160 | font.fgcolor = "000" 161 | window.bgcolor = "fff" 162 | gui.spacing = 2 163 | gui.margin = 2 164 | gui.padding = 5 165 | gui.header_style = none 166 | nprocs.bgcolor = "ffec94" 167 | cpus.bgcolor = "ffaeae" 168 | memory.bgcolor = "fff0aa" 169 | net.bgcolor = "b0e57c" 170 | battery.bgcolor= "b4d8e7" 171 | bright.bgcolor = "c0f58c" 172 | volume.bgcolor = "56baec" 173 | time.bgcolor = "ff9e00" 174 | wifi.bgcolor = "ff8c8c" 175 | memory.chart_color_active = "f00" 176 | memory.chart_color_total = "ff7f00" 177 | memory.chart_color_free = "014141" 178 | 179 | # My personal setup 180 | [ryan] 181 | widgets = "nprocs cpulong memory net > battery wifi bright volume time" 182 | font.desc = "dejavu sans mono 17px" 183 | window.bgcolor = "0000" 184 | gui.widget_bgcolor = "0009" 185 | gui.margin = 0 186 | gui.padding = "0 5 7 5" 187 | 188 | [ryan-bottom] 189 | widgets = "nprocs cpulong memory net > battery wifi bright volume time" 190 | font.desc = "dejavu sans mono 17px" 191 | window.bgcolor = "0000" 192 | gui.widget_bgcolor = "0009" 193 | gui.margin = 0 194 | gui.padding = "7 5 0 5" 195 | window.y = -1 196 | gui.header_style = above 197 | 198 | # This defines a version of oxbar that looks just like old xstatbar 199 | # Run via `oxbar xstatbar` 200 | [xstatbar] 201 | widgets = "cpulong memory nprocs battery volume bright wifi > time" 202 | font.fgcolor = "ffffff" 203 | font.desc = "fixed 16px" 204 | window.x = 0 205 | window.y = 0 206 | window.w = -1 207 | window.h = -1 208 | window.bgcolor = "000" 209 | gui.padding = 0 210 | gui.widget_bgcolor = "000" 211 | bright.chart_bgcolor = "f00" 212 | bright.chart_pgcolor = "0f0" 213 | cpus.chart_color_user = "f00" 214 | cpus.chart_color_nice = "00f" 215 | cpus.chart_color_system = "ff0" 216 | cpus.chart_color_interrupt = "f0f" 217 | cpus.chart_color_idle = "0f0" 218 | cpus.chart_color_spin = "fff" 219 | memory.chart_color_free = "0f0" 220 | memory.chart_color_total = "ff0" 221 | memory.chart_color_active = "f00" 222 | battery.chart_bgcolor = "f00" 223 | battery.chart_pgcolor = "0f0" 224 | volume.chart_bgcolor = "f00" 225 | volume.chart_pgcolor = "0f0" 226 | time.fgcolor = "0ff" 227 | time.format = "%a %d %b %Y %I:%M:%S %p" 228 | -------------------------------------------------------------------------------- /loc: -------------------------------------------------------------------------------- 1 | 91 text files. 2 | classified 90 files 90 unique files. 3 | 12 files ignored. 4 | 5 | github.com/AlDanial/cloc v 1.74 T=1.16 s (69.8 files/s, 7067.5 lines/s) 6 | ------------------------------------------------------------------------------- 7 | Language files blank comment code 8 | ------------------------------------------------------------------------------- 9 | C 40 654 891 3180 10 | HTML 1 5 14 1195 11 | C/C++ Header 28 199 538 556 12 | C++ 2 46 5 273 13 | Markdown 3 47 0 179 14 | make 5 55 20 175 15 | Bourne Shell 2 26 34 106 16 | ------------------------------------------------------------------------------- 17 | SUM: 81 1032 1502 5664 18 | ------------------------------------------------------------------------------- 19 | 92 text files. 20 | classified 91 files 91 unique files. 21 | 12 files ignored. 22 | 23 | github.com/AlDanial/cloc v 1.74 T=1.15 s (70.6 files/s, 7142.6 lines/s) 24 | ------------------------------------------------------------------------------------ 25 | File blank comment code 26 | ------------------------------------------------------------------------------------ 27 | ./man/oxbar.html 5 14 1195 28 | ./settings.c 79 154 481 29 | ./gui/xdraw.c 49 31 324 30 | ./gui/xcore.c 56 50 320 31 | ./gui/xcore.t.cc 38 5 242 32 | ./widgets.c 34 23 216 33 | ./oxbar.c 24 37 174 34 | ./stats/net.c 26 23 128 35 | ./gui/gui.c 19 16 110 36 | ./stats/brightness.c 24 20 102 37 | ./gui/xcore.d.c 22 37 97 38 | ./gui/chart.c 26 16 92 39 | ./Makefile 20 12 87 40 | ./README.md 25 0 82 41 | ./stats/volume.c 23 21 75 42 | ./gui/xdraw.h 20 42 73 43 | ./stats/cpu.c 20 23 69 44 | ./widgets/cpus.c 15 15 66 45 | ./stats/memory.c 16 23 64 46 | ./CONTRIBUTING.md 18 0 63 47 | ./screenshots.sh 17 24 56 48 | ./stats/wifi.c 14 15 56 49 | ./widgets/memory.c 11 15 55 50 | ./widgets/net.c 11 17 52 51 | ./testruns.sh 9 10 50 52 | ./gui/xdraw.d.c 15 15 49 53 | ./gui/xcore.h 16 34 45 54 | ./stats/battery.c 12 15 44 55 | ./widgets/cpuslong.c 7 15 41 56 | ./widgets/volume.c 11 16 40 57 | ./widgets/util.c 11 16 40 58 | ./stats/stats.c 6 16 39 59 | ./gui/Makefile 15 4 39 60 | ./stats/util.c 12 15 37 61 | ./stats/cpu.d.c 8 15 36 62 | ./gui/gui.h 10 26 36 63 | ./widgets/battery.c 8 15 35 64 | ./settings.h 9 19 34 65 | ./stats/README.md 4 0 34 66 | ./stats/net.d.c 8 15 32 67 | ./stats/memory.d.c 8 15 31 68 | ./gui/chart.t.cc 8 0 31 69 | ./widgets/cpus.h 7 21 28 70 | ./gui/chart.d.c 6 21 27 71 | ./widgets/net.h 7 17 27 72 | ./stats/volume.d.c 8 15 26 73 | ./stats/battery.d.c 8 15 26 74 | ./stats/stats.h 6 15 25 75 | ./gui/chart.h 10 54 25 76 | ./widgets/cpushort.c 5 15 25 77 | ./stats/wifi.d.c 8 15 24 78 | ./widgets/memory.h 7 17 24 79 | ./stats/brightness.d.c 8 15 23 80 | ./stats/nprocs.d.c 8 15 23 81 | ./widgets/bright.c 7 15 23 82 | ./stats/nprocs.c 7 16 22 83 | ./widgets/time.c 5 15 20 84 | ./widgets/wifi.c 4 15 19 85 | ./man/Makefile 9 0 18 86 | ./stats/cpu.h 7 16 18 87 | ./stats/Makefile 6 2 18 88 | ./widgets/battery.h 6 15 17 89 | ./widgets/nprocs.c 5 15 17 90 | ./widgets/volume.h 6 15 16 91 | ./widgets/bright.h 6 15 16 92 | ./stats/net.h 9 18 16 93 | ./stats/memory.h 7 17 14 94 | ./widgets/time.h 6 15 14 95 | ./widgets/Makefile 5 2 13 96 | ./widgets/nprocs.h 6 15 13 97 | ./stats/battery.h 5 15 13 98 | ./widgets/wifi.h 6 15 13 99 | ./stats/volume.h 5 15 12 100 | ./stats/wifi.h 5 15 12 101 | ./widgets/util.h 5 17 11 102 | ./stats/brightness.h 5 15 11 103 | ./stats/nprocs.h 5 15 11 104 | ./widgets.h 5 15 11 105 | ./widgets/cpuslong.h 5 15 9 106 | ./widgets/cpushort.h 5 15 8 107 | ./stats/util.h 3 15 4 108 | ------------------------------------------------------------------------------------ 109 | SUM: 1032 1502 5664 110 | ------------------------------------------------------------------------------------ 111 | 112 | 113 | Lines in core oxbar 114 | 714 ./settings.c 115 | 235 ./oxbar.c 116 | 273 ./widgets.c 117 | 58 ./widgets/battery.c 118 | 67 ./widgets/volume.c 119 | 81 ./widgets/memory.c 120 | 37 ./widgets/nprocs.c 121 | 80 ./widgets/net.c 122 | 96 ./widgets/cpus.c 123 | 40 ./widgets/time.c 124 | 38 ./widgets/wifi.c 125 | 63 ./widgets/cpuslong.c 126 | 45 ./widgets/bright.c 127 | 45 ./widgets/cpushort.c 128 | 67 ./widgets/util.c 129 | 426 ./gui/xcore.c 130 | 404 ./gui/xdraw.c 131 | 145 ./gui/gui.c 132 | 134 ./gui/chart.c 133 | 71 ./stats/battery.c 134 | 61 ./stats/stats.c 135 | 103 ./stats/memory.c 136 | 45 ./stats/nprocs.c 137 | 112 ./stats/cpu.c 138 | 119 ./stats/volume.c 139 | 85 ./stats/wifi.c 140 | 177 ./stats/net.c 141 | 146 ./stats/brightness.c 142 | 64 ./stats/util.c 143 | 4031 total 144 | Lines in tests and drivers 145 | 285 ./gui/xcore.t.cc 146 | 54 ./gui/chart.d.c 147 | 156 ./gui/xcore.d.c 148 | 79 ./gui/xdraw.d.c 149 | 39 ./gui/chart.t.cc 150 | 59 ./stats/cpu.d.c 151 | 55 ./stats/net.d.c 152 | 49 ./stats/battery.d.c 153 | 46 ./stats/nprocs.d.c 154 | 49 ./stats/volume.d.c 155 | 54 ./stats/memory.d.c 156 | 47 ./stats/wifi.d.c 157 | 46 ./stats/brightness.d.c 158 | 1018 total 159 | Lines in build setup 160 | 119 ./Makefile 161 | 227 ./sample.oxbar.conf 162 | 27 ./man/Makefile 163 | 69 ./testruns.sh 164 | 20 ./widgets/Makefile 165 | 58 ./gui/Makefile 166 | 26 ./stats/Makefile 167 | 546 total 168 | -------------------------------------------------------------------------------- /widgets.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "gui/xdraw.h" 21 | #include "widgets.h" 22 | #include "widgets/util.h" 23 | 24 | #include "widgets/battery.h" 25 | #include "widgets/bright.h" 26 | #include "widgets/cpus.h" 27 | #include "widgets/cpushort.h" 28 | #include "widgets/cpuslong.h" 29 | #include "widgets/memory.h" 30 | #include "widgets/net.h" 31 | #include "widgets/nprocs.h" 32 | #include "widgets/time.h" 33 | #include "widgets/volume.h" 34 | #include "widgets/wifi.h" 35 | 36 | /* private functions */ 37 | static struct widget_recipe* find_recipe(const char *); 38 | static void *get_settings_component(const char * const, 39 | struct settings*); 40 | static struct widget *widget_create_from_recipe(const char *, 41 | struct settings *, 42 | struct oxstats*); 43 | static void widgets_create(const char *, struct gui *, 44 | struct settings *, struct oxstats *); 45 | 46 | /* 47 | * Global list of all known widget types and how to create them. 48 | * When adding a widget, they must be added here. 49 | */ 50 | struct widget_recipe { 51 | struct widget widget; /* the widget itself */ 52 | void *(*init)(struct oxstats *, void *settings);/* how to build it */ 53 | void (*free)(void *widget); /* how to destroy it */ 54 | }; 55 | 56 | /* define all widget recipes */ 57 | #define WCLRS() NULL, NULL, NULL 58 | struct widget_recipe WIDGET_RECIPES[] = { 59 | {{"battery", WCLRS(), wbattery_enabled, wbattery_draw, NULL}, generic_init, generic_free }, 60 | {{"bright", WCLRS(), wbright_enabled, wbright_draw, NULL}, generic_init, generic_free }, 61 | {{"cpu", WCLRS(), wcpu_enabled, wcpu_draw, NULL}, wcpu_init, wcpu_free }, 62 | {{"cpulong", WCLRS(), wcpulong_enabled, wcpulong_draw, NULL}, wcpu_init, wcpu_free }, 63 | {{"cpushort", WCLRS(), wcpushort_enabled,wcpushort_draw, NULL}, wcpu_init, wcpu_free }, 64 | {{"memory", WCLRS(), wmemory_enabled, wmemory_draw, NULL}, wmemory_init, wmemory_free }, 65 | {{"net", WCLRS(), wnet_enabled, wnet_draw, NULL}, wnet_init, wnet_free }, 66 | {{"nprocs", WCLRS(), wnprocs_enabled, wnprocs_draw, NULL}, generic_init, generic_free }, 67 | {{"time", WCLRS(), wtime_enabled, wtime_draw, NULL}, generic_init, generic_free }, 68 | {{"volume", WCLRS(), wvolume_enabled, wvolume_draw, NULL}, generic_init, generic_free }, 69 | {{"wifi", WCLRS(), wwifi_enabled, wwifi_draw, NULL}, generic_init, generic_free } 70 | }; 71 | const size_t NWIDGET_RECIPES = sizeof(WIDGET_RECIPES) / sizeof(struct widget_recipe); 72 | 73 | /* this tracks all widgets created, so they can be destroyed on shutdown */ 74 | #define MAX_ALL_WIDGETS 1000 75 | static struct widget *WIDGETS[MAX_ALL_WIDGETS]; 76 | static size_t NWIDGETS = 0; 77 | 78 | static struct widget_recipe* 79 | find_recipe(const char *name) 80 | { 81 | size_t i = 0; 82 | for (; i < NWIDGET_RECIPES; i++) { 83 | if (0 == strcmp(name, WIDGET_RECIPES[i].widget.name)) 84 | return &WIDGET_RECIPES[i]; 85 | } 86 | return NULL; 87 | } 88 | 89 | static void * 90 | get_settings_component(const char * const name, struct settings *settings) 91 | { 92 | if (0 == strcmp(name, "battery")) 93 | return &settings->battery; 94 | if (0 == strcmp(name, "bright")) 95 | return &settings->bright; 96 | if (0 == strcmp(name, "cpu")) 97 | return &settings->cpus; 98 | if (0 == strcmp(name, "cpulong")) 99 | return &settings->cpus; 100 | if (0 == strcmp(name, "cpushort")) 101 | return &settings->cpus; 102 | if (0 == strcmp(name, "memory")) 103 | return &settings->memory; 104 | if (0 == strcmp(name, "net")) 105 | return &settings->net; 106 | if (0 == strcmp(name, "nprocs")) 107 | return &settings->nprocs; 108 | if (0 == strcmp(name, "time")) 109 | return &settings->time; 110 | if (0 == strcmp(name, "volume")) 111 | return &settings->volume; 112 | if (0 == strcmp(name, "wifi")) 113 | return &settings->wifi; 114 | 115 | errx(1, "failed to find settings component for '%s'", name); 116 | } 117 | 118 | static struct widget* 119 | widget_create_from_recipe( 120 | const char *name, 121 | struct settings *settings, 122 | struct oxstats *stats) 123 | { 124 | struct widget_recipe *recipe; 125 | struct widget *w; 126 | 127 | if (NWIDGETS == MAX_ALL_WIDGETS) 128 | errx(1, "reached max widget count %d", MAX_ALL_WIDGETS); 129 | 130 | if (NULL == (recipe = find_recipe(name))) 131 | errx(1, "no widget recipe found named '%s'", name); 132 | 133 | w = malloc(sizeof(struct widget)); 134 | if (NULL == w) 135 | err(1, "failed to malloc widget named '%s'", name); 136 | 137 | w->name = recipe->widget.name; 138 | w->hdcolor = recipe->widget.hdcolor; 139 | w->bgcolor = recipe->widget.bgcolor; 140 | w->fgcolor = recipe->widget.fgcolor; 141 | w->enabled = recipe->widget.enabled; 142 | w->draw = recipe->widget.draw; 143 | 144 | if (NULL != recipe->init) { 145 | void *state = recipe->init(stats, 146 | get_settings_component(name, settings)); 147 | w->state = state; 148 | } 149 | 150 | WIDGETS[NWIDGETS++] = w; /* track to cleanup in widgets_free() */ 151 | return w; 152 | } 153 | 154 | static void 155 | widgets_create( 156 | const char *list, 157 | struct gui *gui, 158 | struct settings *settings, 159 | struct oxstats *stats) 160 | { 161 | xctx_direction_t direction = L2R; 162 | char *token; 163 | char *copylist = strdup(list); /* strsep(3) will change this */ 164 | char *memhandle = copylist; /* need this for free() and clang */ 165 | 166 | if (NULL == copylist) 167 | err(1, "failed to strdup widget list '%s'", list); 168 | 169 | while (NULL != (token = strsep(©list, " ,"))) { 170 | if ('\0' == *token) 171 | continue; 172 | 173 | if (0 == strcasecmp("<", token)) 174 | direction = L2R; 175 | else if (0 == strcasecmp("|", token)) 176 | direction = CENTERED; 177 | else if (0 == strcasecmp(">", token)) 178 | direction = R2L; 179 | else { 180 | gui_add_widget(gui, direction, 181 | widget_create_from_recipe(token, settings, stats)); 182 | } 183 | } 184 | free(memhandle); 185 | } 186 | 187 | void 188 | widgets_init(struct gui *gui, struct settings *settings, struct oxstats *stats) 189 | { 190 | /* connect hdcolor, bgcolor, and fgcolor components to their globals */ 191 | widget_set_hdcolor("battery", &settings->battery.hdcolor); 192 | widget_set_hdcolor("bright", &settings->bright.hdcolor); 193 | widget_set_hdcolor("cpu", &settings->cpus.hdcolor); 194 | widget_set_hdcolor("cpushort", &settings->cpus.hdcolor); 195 | widget_set_hdcolor("cpulong", &settings->cpus.hdcolor); 196 | widget_set_hdcolor("memory", &settings->memory.hdcolor); 197 | widget_set_hdcolor("net", &settings->net.hdcolor); 198 | widget_set_hdcolor("nprocs", &settings->nprocs.hdcolor); 199 | widget_set_hdcolor("time", &settings->time.hdcolor); 200 | widget_set_hdcolor("volume", &settings->volume.hdcolor); 201 | widget_set_hdcolor("wifi", &settings->wifi.hdcolor); 202 | 203 | widget_set_bgcolor("battery", &settings->battery.bgcolor); 204 | widget_set_bgcolor("bright", &settings->bright.bgcolor); 205 | widget_set_bgcolor("cpu", &settings->cpus.bgcolor); 206 | widget_set_bgcolor("cpushort", &settings->cpus.bgcolor); 207 | widget_set_bgcolor("cpulong", &settings->cpus.bgcolor); 208 | widget_set_bgcolor("memory", &settings->memory.bgcolor); 209 | widget_set_bgcolor("net", &settings->net.bgcolor); 210 | widget_set_bgcolor("nprocs", &settings->nprocs.bgcolor); 211 | widget_set_bgcolor("time", &settings->time.bgcolor); 212 | widget_set_bgcolor("volume", &settings->volume.bgcolor); 213 | widget_set_bgcolor("wifi", &settings->wifi.bgcolor); 214 | 215 | widget_set_fgcolor("battery", &settings->battery.fgcolor); 216 | widget_set_fgcolor("bright", &settings->bright.fgcolor); 217 | widget_set_fgcolor("cpu", &settings->cpus.fgcolor); 218 | widget_set_fgcolor("cpushort", &settings->cpus.fgcolor); 219 | widget_set_fgcolor("cpulong", &settings->cpus.fgcolor); 220 | widget_set_fgcolor("memory", &settings->memory.fgcolor); 221 | widget_set_fgcolor("net", &settings->net.fgcolor); 222 | widget_set_fgcolor("nprocs", &settings->nprocs.fgcolor); 223 | widget_set_fgcolor("time", &settings->time.fgcolor); 224 | widget_set_fgcolor("volume", &settings->volume.fgcolor); 225 | widget_set_fgcolor("wifi", &settings->wifi.fgcolor); 226 | 227 | widgets_create(settings->widgets, gui, settings, stats); 228 | } 229 | 230 | void 231 | widgets_free() 232 | { 233 | size_t i = 0; 234 | 235 | for (; i < NWIDGETS; i++) { 236 | struct widget_recipe *recipe = find_recipe(WIDGETS[i]->name); 237 | if (NULL != recipe && NULL != recipe->free) 238 | recipe->free(WIDGETS[i]->state); 239 | 240 | free(WIDGETS[i]); 241 | } 242 | NWIDGETS = 0; 243 | } 244 | 245 | void 246 | widget_set_hdcolor(const char * const name, char **color) 247 | { 248 | struct widget_recipe *recipe = find_recipe(name); 249 | if (NULL == recipe) 250 | errx(1, "unknown widget '%s' used when setting hdcolor", name); 251 | 252 | recipe->widget.hdcolor = color; 253 | } 254 | 255 | void 256 | widget_set_bgcolor(const char * const name, char **color) 257 | { 258 | struct widget_recipe *recipe = find_recipe(name); 259 | if (NULL == recipe) 260 | errx(1, "unknown widget '%s' used when setting bgcolor", name); 261 | 262 | recipe->widget.bgcolor = color; 263 | } 264 | 265 | void 266 | widget_set_fgcolor(const char * const name, char **color) 267 | { 268 | struct widget_recipe *recipe = find_recipe(name); 269 | if (NULL == recipe) 270 | errx(1, "unknown widget '%s' used when setting fgcolor", name); 271 | 272 | recipe->widget.fgcolor = color; 273 | } 274 | -------------------------------------------------------------------------------- /gui/xdraw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Ryan Flannery 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "xdraw.h" 25 | 26 | static struct padding ZEROPAD = { 27 | .top = 0, 28 | .right = 0, 29 | .bottom = 0, 30 | .left = 0 31 | }; 32 | 33 | static struct xctx* 34 | xctx_init( 35 | struct xfont *font, 36 | struct xwin *win, 37 | xctx_direction_t direction, 38 | double height, 39 | struct padding *padding, 40 | bool make_root) 41 | { 42 | struct xctx *ctx = malloc(sizeof(struct xctx)); 43 | if (NULL == ctx) 44 | err(1, "%s: malloc failed", __FUNCTION__); 45 | 46 | ctx->is_root = make_root; 47 | ctx->direction = direction; 48 | ctx->xfont = font; 49 | ctx->h = height; 50 | ctx->w = win->settings->w; 51 | 52 | if (NULL == padding) 53 | ctx->padding = &ZEROPAD; 54 | else 55 | ctx->padding = padding; 56 | 57 | /* if root, use xcore's root window cairo info, otherwise a new one */ 58 | if (make_root) { 59 | ctx->surface = win->surface; 60 | ctx->cairo = win->cairo; 61 | } else { 62 | ctx->surface = cairo_surface_create_similar( 63 | win->surface, 64 | CAIRO_CONTENT_COLOR_ALPHA, 65 | win->settings->w, 66 | win->settings->h); 67 | 68 | if (CAIRO_STATUS_SUCCESS != cairo_surface_status(ctx->surface)) 69 | errx(1, "failed to create cairo surface"); 70 | 71 | ctx->cairo = cairo_create(ctx->surface); 72 | if (CAIRO_STATUS_SUCCESS != cairo_status(ctx->cairo)) 73 | errx(1, "failed to create cairo object"); 74 | } 75 | 76 | xctx_reset(ctx); 77 | return ctx; 78 | } 79 | 80 | struct xctx* 81 | xctx_init_root( 82 | struct xfont *font, 83 | struct xwin *win, 84 | xctx_direction_t direction, 85 | struct padding *padding) 86 | { 87 | return xctx_init(font, win, direction, win->settings->h, padding, true); 88 | } 89 | 90 | struct xctx* 91 | xctx_init_scratchpad( 92 | struct xfont *font, 93 | struct xwin *win, 94 | xctx_direction_t direction, 95 | struct padding *padding) 96 | { 97 | double h = win->settings->h; 98 | if (NULL == padding) 99 | padding = &ZEROPAD; 100 | else 101 | h = font->height + padding->top + padding->bottom; 102 | 103 | return xctx_init(font, win, direction, h, padding, false); 104 | } 105 | 106 | void 107 | xctx_free(struct xctx *ctx) 108 | { 109 | if (!ctx->is_root) { 110 | cairo_surface_destroy(ctx->surface); 111 | cairo_destroy(ctx->cairo); 112 | } 113 | free(ctx); 114 | } 115 | 116 | void 117 | xctx_reset(struct xctx *ctx) 118 | { 119 | switch (ctx->direction) { 120 | case L2R: 121 | ctx->xoffset = ctx->padding->left; 122 | ctx->yoffset = ctx->padding->top; 123 | break; 124 | case R2L: 125 | ctx->xoffset = ctx->w - ctx->padding->right; 126 | ctx->yoffset = ctx->padding->top; 127 | break; 128 | case CENTERED: 129 | ctx->xoffset = ctx->w / 2 - ctx->padding->left; 130 | ctx->yoffset = ctx->padding->top; 131 | break; 132 | } 133 | } 134 | 135 | void 136 | xctx_complete(struct xctx *ctx) 137 | { 138 | switch (ctx->direction) { 139 | case L2R: 140 | ctx->xoffset += ctx->padding->right; 141 | break; 142 | case R2L: 143 | ctx->xoffset -= ctx->padding->left; 144 | break; 145 | case CENTERED: 146 | ctx->xoffset += ctx->padding->right; 147 | break; 148 | } 149 | } 150 | 151 | void 152 | xctx_advance( 153 | struct xctx *ctx, 154 | xctx_state_t state, 155 | double xdelta, 156 | __attribute__((unused)) 157 | double ydelta) 158 | { 159 | switch (ctx->direction) { 160 | case L2R: 161 | switch (state) { 162 | case BEFORE_RENDER: 163 | return; 164 | case AFTER_RENDER: 165 | ctx->xoffset += xdelta; 166 | break; 167 | } 168 | break; 169 | 170 | case R2L: 171 | switch (state) { 172 | case BEFORE_RENDER: 173 | ctx->xoffset -= xdelta; 174 | break; 175 | case AFTER_RENDER: 176 | return; 177 | } 178 | break; 179 | 180 | case CENTERED: 181 | switch (state) { 182 | case BEFORE_RENDER: 183 | ctx->xoffset -= (xdelta / 2); 184 | break; 185 | case AFTER_RENDER: 186 | ctx->xoffset += (xdelta / 2); 187 | break; 188 | } 189 | break; 190 | } 191 | } 192 | 193 | /* 194 | * Drawing Primitives - note they all follow the same pattern of 195 | * 196 | * xctx_advance(dest, BEFORE_RENDER, width, height); 197 | * ...do drawing stuff... 198 | * xctx_advance(dest, AFTER_RENDER, width, height); 199 | * 200 | * This is to support right-to-left (RTL) rendering, in which we need to 201 | * advance the "pen" when drawing *before* we actually begin drawing. 202 | * The xctx_advance() api knows which of these actually advances the pen, 203 | * based on the direction of the destination context. 204 | */ 205 | 206 | void 207 | xdraw_context( 208 | struct xctx *dest, 209 | struct xctx *source) 210 | { 211 | xctx_advance(dest, BEFORE_RENDER, source->xoffset, source->yoffset); 212 | 213 | cairo_set_source_surface( 214 | dest->cairo, 215 | source->surface, 216 | dest->xoffset, 217 | dest->padding->top); 218 | cairo_rectangle( 219 | dest->cairo, 220 | dest->xoffset, 221 | dest->padding->top, 222 | source->xoffset, 223 | source->h); 224 | cairo_fill(dest->cairo); 225 | 226 | xctx_advance(dest, AFTER_RENDER, source->xoffset, source->yoffset); 227 | } 228 | 229 | void 230 | xdraw_colorfill( 231 | struct xctx *ctx, 232 | const char *const color) 233 | { 234 | double r, g, b, a; 235 | hex2rgba(color, &r, &g, &b, &a); 236 | cairo_set_source_rgba(ctx->cairo, r, g, b, a); 237 | cairo_paint(ctx->cairo); 238 | } 239 | 240 | void 241 | xdraw_headerline( 242 | struct xctx *ctx, 243 | header_style_t style, 244 | const char *color) 245 | { 246 | double width, y; 247 | switch (style) { 248 | case NONE: 249 | return; 250 | case ABOVE: 251 | width = ctx->padding->top; 252 | y = 0; 253 | break; 254 | case BELOW: 255 | width = ctx->padding->bottom; 256 | y = ctx->h; 257 | break; 258 | default: 259 | errx(1, "%s: bad header style %d\n", __FUNCTION__, style); 260 | } 261 | 262 | double r, g, b, a; 263 | hex2rgba(color, &r, &g, &b, &a); 264 | cairo_set_source_rgba(ctx->cairo, r, g, b, a); 265 | cairo_set_line_width(ctx->cairo, width); 266 | cairo_move_to(ctx->cairo, 0, y); 267 | cairo_line_to(ctx->cairo, ctx->xoffset, y); 268 | cairo_stroke(ctx->cairo); 269 | } 270 | 271 | void 272 | xdraw_printf( 273 | struct xctx *ctx, 274 | const char *color, 275 | const char *fmt, 276 | ...) 277 | { 278 | #define XDRAW_PRINTF_BUFF_MAXLEN 1000 279 | static char buffer[XDRAW_PRINTF_BUFF_MAXLEN]; 280 | 281 | double r, g, b, a; 282 | int width, height; 283 | hex2rgba(color, &r, &g, &b, &a); 284 | 285 | va_list ap; 286 | va_start(ap, fmt); 287 | vsnprintf(buffer, XDRAW_PRINTF_BUFF_MAXLEN, fmt, ap); 288 | va_end(ap); 289 | 290 | PangoLayout *layout = pango_cairo_create_layout(ctx->cairo); 291 | pango_layout_set_font_description(layout, ctx->xfont->pfont); 292 | pango_layout_set_text(layout, buffer, -1); 293 | pango_layout_get_pixel_size(layout, &width, &height); 294 | 295 | xctx_advance(ctx, BEFORE_RENDER, width, height); 296 | 297 | cairo_set_source_rgba(ctx->cairo, r, g, b, a); 298 | cairo_move_to(ctx->cairo, ctx->xoffset, ctx->yoffset); 299 | pango_cairo_show_layout(ctx->cairo, layout); 300 | 301 | xctx_advance(ctx, AFTER_RENDER, width, height); 302 | 303 | g_object_unref(layout); 304 | } 305 | 306 | void 307 | xdraw_progress_bar( 308 | struct xctx *ctx, 309 | const char *bgcolor, 310 | const char *pgcolor, 311 | double width, 312 | double pct) 313 | { 314 | double r, g, b, a; 315 | double height = ctx->h - ctx->padding->top - ctx->padding->bottom; 316 | 317 | xctx_advance(ctx, BEFORE_RENDER, width, height); 318 | 319 | hex2rgba(bgcolor, &r, &g, &b, &a); 320 | cairo_set_source_rgba(ctx->cairo, r, g, b, a); 321 | cairo_rectangle( 322 | ctx->cairo, 323 | ctx->xoffset, 324 | ctx->padding->top, 325 | width, 326 | height); 327 | cairo_fill(ctx->cairo); 328 | 329 | hex2rgba(pgcolor, &r, &g, &b, &a); 330 | cairo_set_source_rgba(ctx->cairo, r, g, b, a); 331 | cairo_rectangle( 332 | ctx->cairo, 333 | ctx->xoffset, 334 | ctx->padding->top + ((100.0 - pct)/100.0) * height, 335 | width, 336 | (pct/100.0) * height); 337 | cairo_fill(ctx->cairo); 338 | 339 | xctx_advance(ctx, AFTER_RENDER, width, height); 340 | } 341 | 342 | void 343 | xdraw_chart( 344 | struct xctx *ctx, 345 | struct chart *c) 346 | { 347 | double chart_height = ctx->h - ctx->padding->top - ctx->padding->bottom; 348 | double width = c->nsamples; 349 | double r, g, b, a; 350 | 351 | xctx_advance(ctx, BEFORE_RENDER, width, chart_height); 352 | 353 | hex2rgba(c->bgcolor, &r, &g, &b, &a); 354 | cairo_set_source_rgba(ctx->cairo, r, g, b, a); 355 | cairo_rectangle( 356 | ctx->cairo, 357 | ctx->xoffset, 358 | ctx->padding->top, 359 | width, 360 | chart_height); 361 | cairo_fill(ctx->cairo); 362 | 363 | double min, max; 364 | chart_get_minmax(c, &min, &max); 365 | 366 | size_t i, j, count; 367 | for (count = 0, i = c->current + 1; count < c->nsamples; count++, i++) { 368 | if (i >= c->nsamples) 369 | i = 0; 370 | 371 | /* we draw the bars for this sample from the bottom UP */ 372 | double y_bottom = ctx->h - ctx->padding->bottom; 373 | for (j = 0; j < c->nseries; j++) { 374 | if (!c->values[i][j]) 375 | continue; 376 | 377 | double height; 378 | if (c->percents) 379 | height = c->values[i][j] / 100.0 * chart_height; 380 | else 381 | height = c->values[i][j] / max * chart_height; 382 | 383 | double y_top = y_bottom - height; 384 | 385 | /* don't go past the top (can happen w/ rounding) */ 386 | if (y_top < ctx->padding->top) 387 | y_top = ctx->padding->top; 388 | else if (c->percents && j == c->nseries - 1) 389 | y_top = ctx->padding->top; 390 | 391 | /* using cairo lines appears fuzzy - use rectangles */ 392 | hex2rgba(c->colors[j], &r, &g, &b, &a); 393 | cairo_set_source_rgba(ctx->cairo, r, g, b, a); 394 | cairo_rectangle(ctx->cairo, 395 | ctx->xoffset + count, 396 | y_top, 397 | 1.0, 398 | height); 399 | cairo_fill(ctx->cairo); 400 | y_bottom = y_top; 401 | } 402 | } 403 | xctx_advance(ctx, AFTER_RENDER, width, chart_height); 404 | } 405 | --------------------------------------------------------------------------------