polybar/src/main.cpp

157 lines
5.1 KiB
C++
Raw Normal View History

2016-06-15 03:32:35 +00:00
#include <X11/Xlib-xcb.h>
#include "common.hpp"
2016-11-20 22:04:31 +00:00
#include "components/bar.hpp"
2016-06-15 03:32:35 +00:00
#include "components/command_line.hpp"
#include "components/config.hpp"
#include "components/controller.hpp"
#include "components/logger.hpp"
#include "config.hpp"
2016-11-20 22:04:31 +00:00
#include "utils/env.hpp"
2016-06-15 03:32:35 +00:00
#include "utils/inotify.hpp"
2016-11-26 05:13:20 +00:00
#include "x11/ewmh.hpp"
2016-11-20 22:04:31 +00:00
#include "x11/xutils.hpp"
2016-06-15 03:32:35 +00:00
2016-11-19 05:22:44 +00:00
using namespace polybar;
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
struct exit_success {};
struct exit_failure {};
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
int main(int argc, char** argv) {
uint8_t exit_code{EXIT_SUCCESS};
stateflag quit{false};
2016-06-15 03:32:35 +00:00
// clang-format off
const command_line::options opts{
2016-11-25 07:42:31 +00:00
command_line::option{"-h", "--help", "Show help options"},
2016-06-15 03:32:35 +00:00
command_line::option{"-v", "--version", "Print version information"},
command_line::option{"-l", "--log", "Set the logging verbosity (default: WARNING)", "LEVEL", {"warning", "info", "trace"}},
command_line::option{"-q", "--quiet", "Be quiet (will override -l)"},
command_line::option{"-c", "--config", "Path to the configuration file", "FILE"},
command_line::option{"-r", "--reload", "Reload when the configuration has been modified"},
command_line::option{"-d", "--dump", "Show value of PARAM in section [bar_name]", "PARAM"},
command_line::option{"-w", "--print-wmname", "Print the generated WM_NAME"},
command_line::option{"-s", "--stdout", "Output data to stdout instead of drawing the X window"},
};
// clang-format on
2016-11-25 07:42:31 +00:00
logger& logger{configure_logger<decltype(logger)>(loglevel::WARNING).create<decltype(logger)>()};
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
//==================================================
// Connect to X server
//==================================================
XInitThreads();
xcb_connection_t* connection{nullptr};
if ((connection = xutils::get_connection()) == nullptr) {
logger.err("A connection to X could not be established... ");
throw exit_failure{};
}
int xfd{xcb_get_file_descriptor(connection)};
while (!quit) {
2016-06-15 03:32:35 +00:00
try {
//==================================================
// Parse command line arguments
//==================================================
2016-11-25 07:42:31 +00:00
vector<string> args(argv + 1, argv + argc);
2016-11-02 19:22:45 +00:00
cliparser cli{configure_cliparser<decltype(cli)>(argv[0], opts).create<decltype(cli)>()};
2016-06-15 03:32:35 +00:00
cli.process_input(args);
2016-11-25 07:42:31 +00:00
if (cli.has("quiet")) {
2016-06-15 03:32:35 +00:00
logger.verbosity(loglevel::ERROR);
2016-11-25 07:42:31 +00:00
} else if (cli.has("log")) {
2016-06-15 03:32:35 +00:00
logger.verbosity(cli.get("log"));
2016-11-25 07:42:31 +00:00
}
2016-06-15 03:32:35 +00:00
if (cli.has("help")) {
cli.usage();
2016-11-25 07:42:31 +00:00
throw exit_success{};
2016-06-15 03:32:35 +00:00
} else if (cli.has("version")) {
2016-11-20 22:04:31 +00:00
print_build_info(version_details(args));
2016-11-25 07:42:31 +00:00
throw exit_success{};
2016-06-15 03:32:35 +00:00
} else if (args.empty() || args[0][0] == '-') {
cli.usage();
2016-11-25 07:42:31 +00:00
throw exit_failure{};
2016-06-15 03:32:35 +00:00
}
//==================================================
// Load user configuration
//==================================================
config& conf{configure_config<decltype(conf)>().create<decltype(conf)>()};
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
if (cli.has("config")) {
2016-06-15 03:32:35 +00:00
conf.load(cli.get("config"), args[0]);
2016-11-25 07:42:31 +00:00
} else if (env_util::has("XDG_CONFIG_HOME")) {
2016-11-20 22:04:31 +00:00
conf.load(env_util::get("XDG_CONFIG_HOME") + "/polybar/config", args[0]);
2016-11-25 07:42:31 +00:00
} else if (env_util::has("HOME")) {
2016-11-20 22:04:31 +00:00
conf.load(env_util::get("HOME") + "/.config/polybar/config", args[0]);
2016-11-25 07:42:31 +00:00
} else {
2016-06-15 03:32:35 +00:00
throw application_error("Define configuration using --config=PATH");
2016-11-25 07:42:31 +00:00
}
2016-06-15 03:32:35 +00:00
//==================================================
// Dump requested data
//==================================================
if (cli.has("dump")) {
std::cout << conf.get<string>(conf.bar_section(), cli.get("dump")) << std::endl;
2016-11-25 07:42:31 +00:00
throw exit_success{};
2016-06-15 03:32:35 +00:00
}
//==================================================
// Create config watch if we should track changes
//==================================================
2016-11-02 19:22:45 +00:00
inotify_util::watch_t watch;
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
if (cli.has("reload")) {
2016-06-15 03:32:35 +00:00
watch = inotify_util::make_watch(conf.filepath());
2016-11-25 07:42:31 +00:00
}
2016-06-15 03:32:35 +00:00
//==================================================
2016-11-25 07:42:31 +00:00
// Create controller
2016-06-15 03:32:35 +00:00
//==================================================
2016-11-25 07:42:31 +00:00
auto ctrl = configure_controller(watch).create<unique_ptr<controller>>();
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
ctrl->bootstrap(cli.has("stdout"), cli.has("print-wmname"));
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
if (cli.has("print-wmname")) {
throw exit_success{};
}
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
//==================================================
// Run application
//==================================================
ctrl->run();
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
if (ctrl->completed()) {
2016-11-25 12:55:15 +00:00
throw exit_success{};
2016-11-25 07:42:31 +00:00
} else {
logger.info("Reloading application...");
}
2016-11-25 12:55:15 +00:00
2016-11-25 07:42:31 +00:00
} catch (const exit_success& term) {
exit_code = EXIT_SUCCESS;
quit = true;
} catch (const exit_failure& term) {
exit_code = EXIT_FAILURE;
quit = true;
} catch (const exception& err) {
2016-06-15 03:32:35 +00:00
logger.err(err.what());
2016-11-25 07:42:31 +00:00
exit_code = EXIT_FAILURE;
quit = true;
2016-06-15 03:32:35 +00:00
}
2016-11-25 07:42:31 +00:00
}
2016-06-15 03:32:35 +00:00
2016-11-25 07:42:31 +00:00
logger.trace("Close connection to X server");
2016-11-26 05:13:20 +00:00
ewmh_util::dealloc();
2016-11-25 07:42:31 +00:00
xcb_disconnect(connection);
2016-06-15 03:32:35 +00:00
close(xfd);
2016-11-25 07:42:31 +00:00
logger.info("Reached end of application...");
return exit_code;
2016-06-15 03:32:35 +00:00
}