From f5aebc07efc522b49774ab7d5914fcf42ee9c4ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 20:09:07 +0100 Subject: [PATCH 01/59] bar: break out all XCB specific code to separate functions --- bar.c | 168 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 107 insertions(+), 61 deletions(-) diff --git a/bar.c b/bar.c index 2f7e8a7..0946fdd 100644 --- a/bar.c +++ b/bar.c @@ -64,7 +64,13 @@ struct private { int width; int height_with_border; - /* Resources */ + /* Name of currently active cursor */ + char *cursor_name; + + cairo_t *cairo; + cairo_surface_t *cairo_surface; + + /* Backend specifics */ xcb_connection_t *conn; xcb_window_t win; @@ -73,10 +79,6 @@ struct private { xcb_gc_t gc; xcb_cursor_context_t *cursor_ctx; xcb_cursor_t cursor; - char *cursor_name; - - cairo_t *cairo; - cairo_surface_t *cairo_surface; }; /* @@ -114,6 +116,15 @@ calculate_widths(const struct private *b, int *left, int *center, int *right) *right -= b->left_spacing + b->right_spacing; } +static void +backend_commit_surface(const struct bar *_bar) +{ + const struct private *bar = _bar->private; + xcb_copy_area(bar->conn, bar->pixmap, bar->win, bar->gc, + 0, 0, 0, 0, bar->width, bar->height_with_border); + xcb_flush(bar->conn); +} + static void expose(const struct bar *_bar) { @@ -204,14 +215,12 @@ expose(const struct bar *_bar) } cairo_surface_flush(bar->cairo_surface); - xcb_copy_area(bar->conn, bar->pixmap, bar->win, bar->gc, - 0, 0, 0, 0, bar->width, bar->height_with_border); - xcb_flush(bar->conn); + backend_commit_surface(_bar); } static void -refresh(const struct bar *bar) +backend_refresh(const struct bar *bar) { const struct private *b = bar->private; @@ -237,7 +246,13 @@ refresh(const struct bar *bar) } static void -set_cursor(struct bar *bar, const char *cursor) +refresh(const struct bar *bar) +{ + backend_refresh(bar); +} + +static void +backend_set_cursor(struct bar *bar, const char *cursor) { struct private *b = bar->private; @@ -258,6 +273,12 @@ set_cursor(struct bar *bar, const char *cursor) xcb_change_window_attributes(b->conn, b->win, XCB_CW_CURSOR, &b->cursor); } +static void +set_cursor(struct bar *bar, const char *cursor) +{ + backend_set_cursor(bar, cursor); +} + static void on_mouse(struct bar *bar, enum mouse_event event, int x, int y) { @@ -266,7 +287,7 @@ on_mouse(struct bar *bar, enum mouse_event event, int x, int y) if ((y < b->border.width || y >= (b->height_with_border - b->border.width)) || (x < b->border.width || x >= (b->width - b->border.width))) { - set_cursor(bar, "left_ptr"); + backend_set_cursor(bar, "left_ptr"); return; } @@ -315,11 +336,11 @@ on_mouse(struct bar *bar, enum mouse_event event, int x, int y) mx += e->width + b->right_spacing; } - set_cursor(bar, "left_ptr"); + backend_set_cursor(bar, "left_ptr"); } -static int -run(struct bar *_bar) +static bool +backend_setup(struct bar *_bar) { struct private *bar = _bar->private; @@ -331,7 +352,7 @@ run(struct bar *_bar) if (xcb_connection_has_error(bar->conn) > 0) { LOG_ERR("failed to connect to X"); xcb_disconnect(bar->conn); - return 1; + return false; } xcb_screen_t *screen = xcb_aux_get_screen(bar->conn, default_screen); @@ -345,7 +366,7 @@ run(struct bar *_bar) LOG_ERR("failed to get monitor list: %s", xcb_error(e)); free(e); /* TODO: cleanup (disconnect) */ - return 1; + return false; } bar->height_with_border = bar->height + 2 * bar->border.width; @@ -386,7 +407,7 @@ run(struct bar *_bar) if (!found_monitor) { LOG_ERR("no matching monitor"); /* TODO: cleanup */ - return 1; + return false; } uint8_t depth = 0; @@ -522,38 +543,16 @@ run(struct bar *_bar) if (xcb_cursor_context_new(bar->conn, screen, &bar->cursor_ctx) < 0) LOG_WARN("failed to create XCB cursor context"); - else - set_cursor(_bar, "left_ptr"); xcb_flush(bar->conn); + return true; +} - /* Start modules */ - thrd_t thrd_left[bar->left.count]; - thrd_t thrd_center[bar->center.count]; - thrd_t thrd_right[bar->right.count]; - - for (size_t i = 0; i < bar->left.count; i++) { - struct module *mod = bar->left.mods[i]; - - mod->abort_fd = _bar->abort_fd; - thrd_create(&thrd_left[i], (int (*)(void *))bar->left.mods[i]->run, mod); - } - for (size_t i = 0; i < bar->center.count; i++) { - struct module *mod = bar->center.mods[i]; - - mod->abort_fd = _bar->abort_fd; - thrd_create(&thrd_center[i], (int (*)(void *))bar->center.mods[i]->run, mod); - } - for (size_t i = 0; i < bar->right.count; i++) { - struct module *mod = bar->right.mods[i]; - - mod->abort_fd = _bar->abort_fd; - thrd_create(&thrd_right[i], (int (*)(void *))bar->right.mods[i]->run, mod); - } - - LOG_DBG("all modules started"); - - int fd = xcb_get_file_descriptor(bar->conn); +static void +backend_loop(struct bar *_bar) +{ + struct private *bar = _bar->private; + const int fd = xcb_get_file_descriptor(bar->conn); while (true) { struct pollfd fds[] = { @@ -620,6 +619,67 @@ run(struct bar *_bar) xcb_flush(bar->conn); } } +} + +static void +backend_cleanup(struct bar *_bar) +{ + struct private *bar = _bar->private; + + if (bar->cursor_ctx != NULL) { + xcb_free_cursor(bar->conn, bar->cursor); + xcb_cursor_context_free(bar->cursor_ctx); + + free(bar->cursor_name); + bar->cursor_name = NULL; + } + + xcb_free_gc(bar->conn, bar->gc); + xcb_free_pixmap(bar->conn, bar->pixmap); + xcb_destroy_window(bar->conn, bar->win); + xcb_free_colormap(bar->conn, bar->colormap); + xcb_flush(bar->conn); + + xcb_disconnect(bar->conn); +} + +static int +run(struct bar *_bar) +{ + struct private *bar = _bar->private; + + if (!backend_setup(_bar)) + return 1; + + backend_set_cursor(_bar, "left_ptr"); + + /* Start modules */ + thrd_t thrd_left[bar->left.count]; + thrd_t thrd_center[bar->center.count]; + thrd_t thrd_right[bar->right.count]; + + for (size_t i = 0; i < bar->left.count; i++) { + struct module *mod = bar->left.mods[i]; + + mod->abort_fd = _bar->abort_fd; + thrd_create(&thrd_left[i], (int (*)(void *))bar->left.mods[i]->run, mod); + } + for (size_t i = 0; i < bar->center.count; i++) { + struct module *mod = bar->center.mods[i]; + + mod->abort_fd = _bar->abort_fd; + thrd_create(&thrd_center[i], (int (*)(void *))bar->center.mods[i]->run, mod); + } + for (size_t i = 0; i < bar->right.count; i++) { + struct module *mod = bar->right.mods[i]; + + mod->abort_fd = _bar->abort_fd; + thrd_create(&thrd_right[i], (int (*)(void *))bar->right.mods[i]->run, mod); + } + + LOG_DBG("all modules started"); + + backend_loop(_bar); LOG_DBG("shutting down"); @@ -678,21 +738,7 @@ run(struct bar *_bar) cairo_surface_destroy(bar->cairo_surface); cairo_debug_reset_static_data(); - if (bar->cursor_ctx != NULL) { - xcb_free_cursor(bar->conn, bar->cursor); - xcb_cursor_context_free(bar->cursor_ctx); - - free(bar->cursor_name); - bar->cursor_name = NULL; - } - - xcb_free_gc(bar->conn, bar->gc); - xcb_free_pixmap(bar->conn, bar->pixmap); - xcb_destroy_window(bar->conn, bar->win); - xcb_free_colormap(bar->conn, bar->colormap); - xcb_flush(bar->conn); - - xcb_disconnect(bar->conn); + backend_cleanup(_bar); LOG_DBG("bar exiting"); return ret; From aa21991323eb7a7b2322491455305b2715f0c4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 20:18:37 +0100 Subject: [PATCH 02/59] bar: move C file to subdirectory --- CMakeLists.txt | 3 ++- bar.c => bar/bar.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) rename bar.c => bar/bar.c (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cca58a..3632d40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,6 @@ pkg_check_modules(CAIRO REQUIRED cairo cairo-xcb cairo-ft) pkg_check_modules(YAML REQUIRED yaml-0.1) add_executable(f00bar - bar.c bar.h config.c config.h config-verify.c config-verify.h decoration.h @@ -44,6 +43,8 @@ add_executable(f00bar tag.c tag.h xcb.c xcb.h yml.c yml.h + + bar/bar.c bar.h ) # Make global symbols in f00bar visible to dlopen:ed plugins diff --git a/bar.c b/bar/bar.c similarity index 99% rename from bar.c rename to bar/bar.c index 0946fdd..14af0f1 100644 --- a/bar.c +++ b/bar/bar.c @@ -1,4 +1,4 @@ -#include "bar.h" +#include "../bar.h" #include #include @@ -25,8 +25,8 @@ #define LOG_MODULE "bar" #define LOG_ENABLE_DBG 0 -#include "log.h" -#include "xcb.h" +#include "../log.h" +#include "../xcb.h" struct private { /* From bar_config */ From 2d104e4a7d8262779aa4306b780f6f08b121a978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 20:20:11 +0100 Subject: [PATCH 03/59] bar: break out 'private' struct definition to a header file --- CMakeLists.txt | 2 +- bar/bar.c | 64 +------------------------------------------------ bar/private.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 64 deletions(-) create mode 100644 bar/private.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3632d40..07d4ada 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ add_executable(f00bar xcb.c xcb.h yml.c yml.h - bar/bar.c bar.h + bar/bar.c bar/private.h bar.h ) # Make global symbols in f00bar visible to dlopen:ed plugins diff --git a/bar/bar.c b/bar/bar.c index 14af0f1..39d48fb 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -1,4 +1,5 @@ #include "../bar.h" +#include "private.h" #include #include @@ -12,74 +13,11 @@ #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - #define LOG_MODULE "bar" #define LOG_ENABLE_DBG 0 #include "../log.h" #include "../xcb.h" -struct private { - /* From bar_config */ - char *monitor; - enum bar_location location; - int height; - int left_spacing, right_spacing; - int left_margin, right_margin; - - struct rgba background; - - struct { - int width; - struct rgba color; - } border; - - struct { - struct module **mods; - struct exposable **exps; - size_t count; - } left; - struct { - struct module **mods; - struct exposable **exps; - size_t count; - } center; - struct { - struct module **mods; - struct exposable **exps; - size_t count; - } right; - - /* Calculated run-time */ - int x, y; - int width; - int height_with_border; - - /* Name of currently active cursor */ - char *cursor_name; - - cairo_t *cairo; - cairo_surface_t *cairo_surface; - - /* Backend specifics */ - xcb_connection_t *conn; - - xcb_window_t win; - xcb_colormap_t colormap; - xcb_pixmap_t pixmap; - xcb_gc_t gc; - xcb_cursor_context_t *cursor_ctx; - xcb_cursor_t cursor; -}; /* * Calculate total width of left/center/rigth groups. diff --git a/bar/private.h b/bar/private.h new file mode 100644 index 0000000..7415e06 --- /dev/null +++ b/bar/private.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct private { + /* From bar_config */ + char *monitor; + enum bar_location location; + int height; + int left_spacing, right_spacing; + int left_margin, right_margin; + + struct rgba background; + + struct { + int width; + struct rgba color; + } border; + + struct { + struct module **mods; + struct exposable **exps; + size_t count; + } left; + struct { + struct module **mods; + struct exposable **exps; + size_t count; + } center; + struct { + struct module **mods; + struct exposable **exps; + size_t count; + } right; + + /* Calculated run-time */ + int x, y; + int width; + int height_with_border; + + /* Name of currently active cursor */ + char *cursor_name; + + cairo_t *cairo; + cairo_surface_t *cairo_surface; + + /* Backend specifics */ + xcb_connection_t *conn; + + xcb_window_t win; + xcb_colormap_t colormap; + xcb_pixmap_t pixmap; + xcb_gc_t gc; + xcb_cursor_context_t *cursor_ctx; + xcb_cursor_t cursor; +}; From f37dfbc72795385ad58099a48154822d19f81fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 20:58:55 +0100 Subject: [PATCH 04/59] module/mpd: free strdup:ed path string --- modules/mpd.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/mpd.c b/modules/mpd.c index 8c3a7ae..6606df3 100644 --- a/modules/mpd.c +++ b/modules/mpd.c @@ -195,12 +195,15 @@ wait_for_socket_create(const struct module *mod) LOG_DBG("monitoring %s for %s to be created", directory, base); int fd = inotify_init(); - if (fd == -1) + if (fd == -1) { + free(copy); return false; + } int wd = inotify_add_watch(fd, directory, IN_CREATE); if (wd == -1) { close(fd); + free(copy); return false; } @@ -231,6 +234,7 @@ wait_for_socket_create(const struct module *mod) if (!have_mpd_socket) LOG_WARN("MPD doesn't appear to be running"); + bool ret = false; while (!have_mpd_socket) { struct pollfd fds[] = { {.fd = mod->abort_fd, .events = POLLIN}, @@ -239,8 +243,10 @@ wait_for_socket_create(const struct module *mod) poll(fds, 2, -1); - if (fds[0].revents & POLLIN) - return true; + if (fds[0].revents & POLLIN) { + ret = true; + break; + } assert(fds[1].revents & POLLIN); @@ -264,7 +270,7 @@ wait_for_socket_create(const struct module *mod) inotify_rm_watch(fd, wd); close(fd); free(copy); - return false; + return ret; } static struct mpd_connection * From 88daaf0ab7c8957cc104993fb957d94f4b5b79f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 20:59:25 +0100 Subject: [PATCH 05/59] bar: wip: define a 'backend' interface Implement the current XCB backend in terms of this new interface. --- CMakeLists.txt | 4 +- bar/backend.h | 17 ++ bar/bar.c | 440 ++++++------------------------------------------- bar/private.h | 17 +- bar/xcb.c | 421 ++++++++++++++++++++++++++++++++++++++++++++++ bar/xcb.h | 7 + 6 files changed, 503 insertions(+), 403 deletions(-) create mode 100644 bar/backend.h create mode 100644 bar/xcb.c create mode 100644 bar/xcb.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 07d4ada..92d65cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,9 @@ add_executable(f00bar xcb.c xcb.h yml.c yml.h - bar/bar.c bar/private.h bar.h + bar.h + bar/bar.c bar/private.h bar/backend.h + bar/xcb.c bar/xcb.h ) # Make global symbols in f00bar visible to dlopen:ed plugins diff --git a/bar/backend.h b/bar/backend.h new file mode 100644 index 0000000..fc33c37 --- /dev/null +++ b/bar/backend.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "../bar.h" + +struct backend { + bool (*setup)(struct bar *bar); + void (*cleanup)(struct bar *bar); + void (*loop)(struct bar *bar, + void (*expose)(const struct bar *bar), + void (*on_mouse)(struct bar *bar, enum mouse_event event, + int x, int y)); + void (*commit_surface)(const struct bar *bar); + void (*refresh)(const struct bar *bar); + void (*set_cursor)(struct bar *bar, const char *cursor); +}; diff --git a/bar/bar.c b/bar/bar.c index 39d48fb..dd9b8fd 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -1,6 +1,7 @@ #include "../bar.h" #include "private.h" +#include #include #include #include @@ -18,6 +19,7 @@ #include "../log.h" #include "../xcb.h" +#include "xcb.h" /* * Calculate total width of left/center/rigth groups. @@ -54,15 +56,6 @@ calculate_widths(const struct private *b, int *left, int *center, int *right) *right -= b->left_spacing + b->right_spacing; } -static void -backend_commit_surface(const struct bar *_bar) -{ - const struct private *bar = _bar->private; - xcb_copy_area(bar->conn, bar->pixmap, bar->win, bar->gc, - 0, 0, 0, 0, bar->width, bar->height_with_border); - xcb_flush(bar->conn); -} - static void expose(const struct bar *_bar) { @@ -153,443 +146,99 @@ expose(const struct bar *_bar) } cairo_surface_flush(bar->cairo_surface); - backend_commit_surface(_bar); + bar->backend.iface->commit_surface(_bar); } -static void -backend_refresh(const struct bar *bar) -{ - const struct private *b = bar->private; - - /* Send an event to handle refresh from main thread */ - - /* Note: docs say that all X11 events are 32 bytes, reglardless of - * the size of the event structure */ - xcb_expose_event_t *evt = calloc(32, 1); - - *evt = (xcb_expose_event_t){ - .response_type = XCB_EXPOSE, - .window = b->win, - .x = 0, - .y = 0, - .width = b->width, - .height = b->height, - .count = 1 - }; - - xcb_send_event(b->conn, false, b->win, XCB_EVENT_MASK_EXPOSURE, (char *)evt); - xcb_flush(b->conn); - free(evt); -} - static void refresh(const struct bar *bar) { - backend_refresh(bar); -} - -static void -backend_set_cursor(struct bar *bar, const char *cursor) -{ - struct private *b = bar->private; - - if (b->cursor_name != NULL && strcmp(b->cursor_name, cursor) == 0) - return; - - if (b->cursor_ctx == NULL) - return; - - if (b->cursor != 0) { - xcb_free_cursor(b->conn, b->cursor); - free(b->cursor_name); - b->cursor_name = NULL; - } - - b->cursor_name = strdup(cursor); - b->cursor = xcb_cursor_load_cursor(b->cursor_ctx, cursor); - xcb_change_window_attributes(b->conn, b->win, XCB_CW_CURSOR, &b->cursor); + const struct private *b = bar->private; + b->backend.iface->refresh(bar); } static void set_cursor(struct bar *bar, const char *cursor) { - backend_set_cursor(bar, cursor); + struct private *b = bar->private; + b->backend.iface->set_cursor(bar, cursor); } static void -on_mouse(struct bar *bar, enum mouse_event event, int x, int y) +on_mouse(struct bar *_bar, enum mouse_event event, int x, int y) { - struct private *b = bar->private; + struct private *bar = _bar->private; - if ((y < b->border.width || y >= (b->height_with_border - b->border.width)) || - (x < b->border.width || x >= (b->width - b->border.width))) + if ((y < bar->border.width || + y >= (bar->height_with_border - bar->border.width)) || + (x < bar->border.width || x >= (bar->width - bar->border.width))) { - backend_set_cursor(bar, "left_ptr"); + set_cursor(_bar, "left_ptr"); return; } int left_width, center_width, right_width; - calculate_widths(b, &left_width, ¢er_width, &right_width); + calculate_widths(bar, &left_width, ¢er_width, &right_width); - int mx = b->border.width + b->left_margin - b->left_spacing; - for (size_t i = 0; i < b->left.count; i++) { - struct exposable *e = b->left.exps[i]; + int mx = bar->border.width + bar->left_margin - bar->left_spacing; + for (size_t i = 0; i < bar->left.count; i++) { + struct exposable *e = bar->left.exps[i]; - mx += b->left_spacing; + mx += bar->left_spacing; if (x >= mx && x < mx + e->width) { if (e->on_mouse != NULL) - e->on_mouse(e, bar, event, x - mx, y); + e->on_mouse(e, _bar, event, x - mx, y); return; } - mx += e->width + b->right_spacing; + mx += e->width + bar->right_spacing; } - mx = b->width / 2 - center_width / 2 - b->left_spacing; - for (size_t i = 0; i < b->center.count; i++) { - struct exposable *e = b->center.exps[i]; + mx = bar->width / 2 - center_width / 2 - bar->left_spacing; + for (size_t i = 0; i < bar->center.count; i++) { + struct exposable *e = bar->center.exps[i]; - mx += b->left_spacing; + mx += bar->left_spacing; if (x >= mx && x < mx + e->width) { if (e->on_mouse != NULL) - e->on_mouse(e, bar, event, x - mx, y); + e->on_mouse(e, _bar, event, x - mx, y); return; } - mx += e->width + b->right_spacing; + mx += e->width + bar->right_spacing; } - mx = b->width - (right_width + b->left_spacing + b->right_margin + b->border.width); - for (size_t i = 0; i < b->right.count; i++) { - struct exposable *e = b->right.exps[i]; + mx = bar->width - (right_width + + bar->left_spacing + + bar->right_margin + + bar->border.width); - mx += b->left_spacing; + for (size_t i = 0; i < bar->right.count; i++) { + struct exposable *e = bar->right.exps[i]; + + mx += bar->left_spacing; if (x >= mx && x < mx + e->width) { if (e->on_mouse != NULL) - e->on_mouse(e, bar, event, x - mx, y); + e->on_mouse(e, _bar, event, x - mx, y); return; } - mx += e->width + b->right_spacing; + mx += e->width + bar->right_spacing; } - backend_set_cursor(bar, "left_ptr"); + set_cursor(_bar, "left_ptr"); } -static bool -backend_setup(struct bar *_bar) -{ - struct private *bar = _bar->private; - - /* TODO: a lot of this (up to mapping the window) could be done in bar_new() */ - xcb_generic_error_t *e; - - int default_screen; - bar->conn = xcb_connect(NULL, &default_screen); - if (xcb_connection_has_error(bar->conn) > 0) { - LOG_ERR("failed to connect to X"); - xcb_disconnect(bar->conn); - return false; - } - - xcb_screen_t *screen = xcb_aux_get_screen(bar->conn, default_screen); - - xcb_randr_get_monitors_reply_t *monitors = xcb_randr_get_monitors_reply( - bar->conn, - xcb_randr_get_monitors(bar->conn, screen->root, 0), - &e); - - if (e != NULL) { - LOG_ERR("failed to get monitor list: %s", xcb_error(e)); - free(e); - /* TODO: cleanup (disconnect) */ - return false; - } - - bar->height_with_border = bar->height + 2 * bar->border.width; - - /* Find monitor coordinates and width/height */ - bool found_monitor = false; - for (xcb_randr_monitor_info_iterator_t it = - xcb_randr_get_monitors_monitors_iterator(monitors); - it.rem > 0; - xcb_randr_monitor_info_next(&it)) - { - const xcb_randr_monitor_info_t *mon = it.data; - char *name = get_atom_name(bar->conn, mon->name); - - LOG_INFO("monitor: %s: %ux%u+%u+%u (%ux%umm)", name, - mon->width, mon->height, mon->x, mon->y, - mon->width_in_millimeters, mon->height_in_millimeters); - - if (!((bar->monitor == NULL && mon->primary) || - (bar->monitor != NULL && strcmp(bar->monitor, name) == 0))) - { - free(name); - continue; - } - - free(name); - - bar->x = mon->x; - bar->y = mon->y; - bar->width = mon->width; - bar->y += bar->location == BAR_TOP ? 0 - : screen->height_in_pixels - bar->height_with_border; - found_monitor = true; - break; - } - free(monitors); - - if (!found_monitor) { - LOG_ERR("no matching monitor"); - /* TODO: cleanup */ - return false; - } - - uint8_t depth = 0; - xcb_visualtype_t *vis = xcb_aux_find_visual_by_attrs(screen, -1, 32); - - if (vis != NULL) - depth = 32; - else { - vis = xcb_aux_find_visual_by_attrs(screen, -1, 24); - if (vis != NULL) - depth = 24; - } - - assert(depth == 32 || depth == 24); - assert(vis != NULL); - LOG_DBG("using a %hhu-bit visual", depth); - - bar->colormap = xcb_generate_id(bar->conn); - xcb_create_colormap(bar->conn, 0, bar->colormap, screen->root, vis->visual_id); - - bar->win = xcb_generate_id(bar->conn); - xcb_create_window( - bar->conn, - depth, bar->win, screen->root, - bar->x, bar->y, bar->width, bar->height_with_border, - 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, vis->visual_id, - (XCB_CW_BACK_PIXEL | - XCB_CW_BORDER_PIXEL | - XCB_CW_EVENT_MASK | - XCB_CW_COLORMAP), - (const uint32_t []){ - screen->black_pixel, - screen->white_pixel, - (XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_BUTTON_RELEASE | - XCB_EVENT_MASK_BUTTON_PRESS | - XCB_EVENT_MASK_POINTER_MOTION | - XCB_EVENT_MASK_STRUCTURE_NOTIFY), - bar->colormap} - ); - - const char *title = "f00bar"; - xcb_change_property( - bar->conn, - XCB_PROP_MODE_REPLACE, bar->win, - XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, - strlen(title), title); - - xcb_change_property( - bar->conn, - XCB_PROP_MODE_REPLACE, bar->win, - _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){getpid()}); - xcb_change_property( - bar->conn, - XCB_PROP_MODE_REPLACE, bar->win, - _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, - 1, (const uint32_t []){_NET_WM_WINDOW_TYPE_DOCK}); - xcb_change_property( - bar->conn, - XCB_PROP_MODE_REPLACE, bar->win, - _NET_WM_STATE, XCB_ATOM_ATOM, 32, - 2, (const uint32_t []){_NET_WM_STATE_ABOVE, _NET_WM_STATE_STICKY}); - xcb_change_property( - bar->conn, - XCB_PROP_MODE_REPLACE, bar->win, - _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){0xffffffff}); - - /* Always on top */ - xcb_configure_window( - bar->conn, bar->win, XCB_CONFIG_WINDOW_STACK_MODE, - (const uint32_t []){XCB_STACK_MODE_ABOVE}); - - uint32_t top_strut, bottom_strut; - uint32_t top_pair[2], bottom_pair[2]; - - if (bar->location == BAR_TOP) { - top_strut = bar->y + bar->height_with_border; - top_pair[0] = bar->x; - top_pair[1] = bar->x + bar->width - 1; - - bottom_strut = 0; - bottom_pair[0] = bottom_pair[1] = 0; - } else { - bottom_strut = screen->height_in_pixels - bar->y; - bottom_pair[0] = bar->x; - bottom_pair[1] = bar->x + bar->width - 1; - - top_strut = 0; - top_pair[0] = top_pair[1] = 0; - } - - uint32_t strut[] = { - /* left/right/top/bottom */ - 0, 0, - top_strut, - bottom_strut, - - /* start/end pairs for left/right/top/bottom */ - 0, 0, - 0, 0, - top_pair[0], top_pair[1], - bottom_pair[0], bottom_pair[1], - }; - - xcb_change_property( - bar->conn, - XCB_PROP_MODE_REPLACE, bar->win, - _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, - 4, strut); - - xcb_change_property( - bar->conn, - XCB_PROP_MODE_REPLACE, bar->win, - _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, - 12, strut); - - bar->pixmap = xcb_generate_id(bar->conn); - xcb_create_pixmap(bar->conn, depth, bar->pixmap, bar->win, - bar->width, bar->height_with_border); - - bar->gc = xcb_generate_id(bar->conn); - xcb_create_gc(bar->conn, bar->gc, bar->pixmap, - XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES, - (const uint32_t []){screen->white_pixel, 0}); - - LOG_DBG("cairo: %s", cairo_version_string()); - bar->cairo_surface = cairo_xcb_surface_create( - bar->conn, bar->pixmap, vis, bar->width, bar->height_with_border); - bar->cairo = cairo_create(bar->cairo_surface); - - xcb_map_window(bar->conn, bar->win); - - if (xcb_cursor_context_new(bar->conn, screen, &bar->cursor_ctx) < 0) - LOG_WARN("failed to create XCB cursor context"); - - xcb_flush(bar->conn); - return true; -} - -static void -backend_loop(struct bar *_bar) -{ - struct private *bar = _bar->private; - const int fd = xcb_get_file_descriptor(bar->conn); - - while (true) { - struct pollfd fds[] = { - {.fd = _bar->abort_fd, .events = POLLIN}, - {.fd = fd, .events = POLLIN} - }; - - poll(fds, sizeof(fds) / sizeof(fds[0]), -1); - - if (fds[0].revents && POLLIN) - break; - - if (fds[1].revents & POLLHUP) { - LOG_WARN("disconnected from XCB"); - write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)); - break; - } - - for (xcb_generic_event_t *e = xcb_wait_for_event(bar->conn); - e != NULL; - e = xcb_poll_for_event(bar->conn)) - { - switch (XCB_EVENT_RESPONSE_TYPE(e)) { - case 0: - LOG_ERR("XCB: %s", xcb_error((const xcb_generic_error_t *)e)); - break; - - case XCB_EXPOSE: - expose(_bar); - break; - - case XCB_MOTION_NOTIFY: { - const xcb_motion_notify_event_t *evt = (void *)e; - on_mouse(_bar, ON_MOUSE_MOTION, evt->event_x, evt->event_y); - break; - } - - case XCB_BUTTON_PRESS: - break; - - case XCB_BUTTON_RELEASE: { - const xcb_button_release_event_t *evt = (void *)e; - on_mouse(_bar, ON_MOUSE_CLICK, evt->event_x, evt->event_y); - break; - } - - case XCB_DESTROY_NOTIFY: - LOG_WARN("unimplemented event: XCB_DESTROY_NOTIFY"); - break; - - case XCB_REPARENT_NOTIFY: - case XCB_CONFIGURE_NOTIFY: - case XCB_MAP_NOTIFY: - case XCB_MAPPING_NOTIFY: - /* Just ignore */ - break; - - default: - LOG_ERR("unsupported event: %d", XCB_EVENT_RESPONSE_TYPE(e)); - break; - } - - free(e); - xcb_flush(bar->conn); - } - } -} - -static void -backend_cleanup(struct bar *_bar) -{ - struct private *bar = _bar->private; - - if (bar->cursor_ctx != NULL) { - xcb_free_cursor(bar->conn, bar->cursor); - xcb_cursor_context_free(bar->cursor_ctx); - - free(bar->cursor_name); - bar->cursor_name = NULL; - } - - xcb_free_gc(bar->conn, bar->gc); - xcb_free_pixmap(bar->conn, bar->pixmap); - xcb_destroy_window(bar->conn, bar->win); - xcb_free_colormap(bar->conn, bar->colormap); - xcb_flush(bar->conn); - - xcb_disconnect(bar->conn); -} static int run(struct bar *_bar) { struct private *bar = _bar->private; - if (!backend_setup(_bar)) + if (!bar->backend.iface->setup(_bar)) return 1; - backend_set_cursor(_bar, "left_ptr"); + set_cursor(_bar, "left_ptr"); /* Start modules */ thrd_t thrd_left[bar->left.count]; @@ -617,7 +266,7 @@ run(struct bar *_bar) LOG_DBG("all modules started"); - backend_loop(_bar); + bar->backend.iface->loop(_bar, &expose, &on_mouse); LOG_DBG("shutting down"); @@ -676,7 +325,7 @@ run(struct bar *_bar) cairo_surface_destroy(bar->cairo_surface); cairo_debug_reset_static_data(); - backend_cleanup(_bar); + bar->backend.iface->cleanup(_bar); LOG_DBG("bar exiting"); return ret; @@ -694,6 +343,7 @@ destroy(struct bar *bar) free(b->right.mods); free(b->right.exps); free(b->monitor); + free(b->backend.data); free(bar->private); free(bar); @@ -722,9 +372,11 @@ bar_new(const struct bar_config *config) priv->left.count = config->left.count; priv->center.count = config->center.count; priv->right.count = config->right.count; - priv->cursor_ctx = NULL; - priv->cursor = 0; + //priv->cursor_ctx = NULL; + //priv->cursor = 0; priv->cursor_name = NULL; + priv->backend.data = bar_backend_xcb_new(); + priv->backend.iface = &xcb_backend_iface; for (size_t i = 0; i < priv->left.count; i++) { priv->left.mods[i] = config->left.mods[i]; diff --git a/bar/private.h b/bar/private.h index 7415e06..5b202ab 100644 --- a/bar/private.h +++ b/bar/private.h @@ -1,16 +1,11 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include - #include #include +#include "../bar.h" +#include "backend.h" + struct private { /* From bar_config */ char *monitor; @@ -53,6 +48,11 @@ struct private { cairo_t *cairo; cairo_surface_t *cairo_surface; + struct { + void *data; + const struct backend *iface; + } backend; +#if 0 /* Backend specifics */ xcb_connection_t *conn; @@ -62,4 +62,5 @@ struct private { xcb_gc_t gc; xcb_cursor_context_t *cursor_ctx; xcb_cursor_t cursor; +#endif }; diff --git a/bar/xcb.c b/bar/xcb.c new file mode 100644 index 0000000..35da106 --- /dev/null +++ b/bar/xcb.c @@ -0,0 +1,421 @@ +#include "xcb.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "private.h" + +#define LOG_MODULE "bar:xcb" +#include "../log.h" +#include "../xcb.h" + +struct xcb_backend { + xcb_connection_t *conn; + + xcb_window_t win; + xcb_colormap_t colormap; + xcb_pixmap_t pixmap; + xcb_gc_t gc; + xcb_cursor_context_t *cursor_ctx; + xcb_cursor_t cursor; +}; + +void * +bar_backend_xcb_new(void) +{ + return calloc(1, sizeof(struct xcb_backend)); +} + +static bool +setup(struct bar *_bar) +{ + struct private *bar = _bar->private; + struct xcb_backend *backend = bar->backend.data; + + /* TODO: a lot of this (up to mapping the window) could be done in bar_new() */ + xcb_generic_error_t *e; + + int default_screen; + backend->conn = xcb_connect(NULL, &default_screen); + if (xcb_connection_has_error(backend->conn) > 0) { + LOG_ERR("failed to connect to X"); + xcb_disconnect(backend->conn); + return false; + } + + xcb_screen_t *screen = xcb_aux_get_screen(backend->conn, default_screen); + + xcb_randr_get_monitors_reply_t *monitors = xcb_randr_get_monitors_reply( + backend->conn, + xcb_randr_get_monitors(backend->conn, screen->root, 0), + &e); + + if (e != NULL) { + LOG_ERR("failed to get monitor list: %s", xcb_error(e)); + free(e); + /* TODO: cleanup (disconnect) */ + return false; + } + + bar->height_with_border = bar->height + 2 * bar->border.width; + + /* Find monitor coordinates and width/height */ + bool found_monitor = false; + for (xcb_randr_monitor_info_iterator_t it = + xcb_randr_get_monitors_monitors_iterator(monitors); + it.rem > 0; + xcb_randr_monitor_info_next(&it)) + { + const xcb_randr_monitor_info_t *mon = it.data; + char *name = get_atom_name(backend->conn, mon->name); + + LOG_INFO("monitor: %s: %ux%u+%u+%u (%ux%umm)", name, + mon->width, mon->height, mon->x, mon->y, + mon->width_in_millimeters, mon->height_in_millimeters); + + if (!((bar->monitor == NULL && mon->primary) || + (bar->monitor != NULL && strcmp(bar->monitor, name) == 0))) + { + free(name); + continue; + } + + free(name); + + bar->x = mon->x; + bar->y = mon->y; + bar->width = mon->width; + bar->y += bar->location == BAR_TOP ? 0 + : screen->height_in_pixels - bar->height_with_border; + found_monitor = true; + break; + } + free(monitors); + + if (!found_monitor) { + LOG_ERR("no matching monitor"); + /* TODO: cleanup */ + return false; + } + + uint8_t depth = 0; + xcb_visualtype_t *vis = xcb_aux_find_visual_by_attrs(screen, -1, 32); + + if (vis != NULL) + depth = 32; + else { + vis = xcb_aux_find_visual_by_attrs(screen, -1, 24); + if (vis != NULL) + depth = 24; + } + + assert(depth == 32 || depth == 24); + assert(vis != NULL); + LOG_DBG("using a %hhu-bit visual", depth); + + backend->colormap = xcb_generate_id(backend->conn); + xcb_create_colormap(backend->conn, 0, backend->colormap, screen->root, vis->visual_id); + + backend->win = xcb_generate_id(backend->conn); + xcb_create_window( + backend->conn, + depth, backend->win, screen->root, + bar->x, bar->y, bar->width, bar->height_with_border, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, vis->visual_id, + (XCB_CW_BACK_PIXEL | + XCB_CW_BORDER_PIXEL | + XCB_CW_EVENT_MASK | + XCB_CW_COLORMAP), + (const uint32_t []){ + screen->black_pixel, + screen->white_pixel, + (XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_POINTER_MOTION | + XCB_EVENT_MASK_STRUCTURE_NOTIFY), + backend->colormap} + ); + + const char *title = "f00bar"; + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, + strlen(title), title); + + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){getpid()}); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, + 1, (const uint32_t []){_NET_WM_WINDOW_TYPE_DOCK}); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_STATE, XCB_ATOM_ATOM, 32, + 2, (const uint32_t []){_NET_WM_STATE_ABOVE, _NET_WM_STATE_STICKY}); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){0xffffffff}); + + /* Always on top */ + xcb_configure_window( + backend->conn, backend->win, XCB_CONFIG_WINDOW_STACK_MODE, + (const uint32_t []){XCB_STACK_MODE_ABOVE}); + + uint32_t top_strut, bottom_strut; + uint32_t top_pair[2], bottom_pair[2]; + + if (bar->location == BAR_TOP) { + top_strut = bar->y + bar->height_with_border; + top_pair[0] = bar->x; + top_pair[1] = bar->x + bar->width - 1; + + bottom_strut = 0; + bottom_pair[0] = bottom_pair[1] = 0; + } else { + bottom_strut = screen->height_in_pixels - bar->y; + bottom_pair[0] = bar->x; + bottom_pair[1] = bar->x + bar->width - 1; + + top_strut = 0; + top_pair[0] = top_pair[1] = 0; + } + + uint32_t strut[] = { + /* left/right/top/bottom */ + 0, 0, + top_strut, + bottom_strut, + + /* start/end pairs for left/right/top/bottom */ + 0, 0, + 0, 0, + top_pair[0], top_pair[1], + bottom_pair[0], bottom_pair[1], + }; + + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, + 4, strut); + + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, + 12, strut); + + backend->pixmap = xcb_generate_id(backend->conn); + xcb_create_pixmap(backend->conn, depth, backend->pixmap, backend->win, + bar->width, bar->height_with_border); + + backend->gc = xcb_generate_id(backend->conn); + xcb_create_gc(backend->conn, backend->gc, backend->pixmap, + XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES, + (const uint32_t []){screen->white_pixel, 0}); + + LOG_DBG("cairo: %s", cairo_version_string()); + bar->cairo_surface = cairo_xcb_surface_create( + backend->conn, backend->pixmap, vis, bar->width, bar->height_with_border); + bar->cairo = cairo_create(bar->cairo_surface); + + xcb_map_window(backend->conn, backend->win); + + if (xcb_cursor_context_new(backend->conn, screen, &backend->cursor_ctx) < 0) + LOG_WARN("failed to create XCB cursor context"); + + xcb_flush(backend->conn); + return true; +} + +static void +cleanup(struct bar *_bar) +{ + struct private *bar = _bar->private; + struct xcb_backend *backend = bar->backend.data; + + if (backend->cursor_ctx != NULL) { + xcb_free_cursor(backend->conn, backend->cursor); + xcb_cursor_context_free(backend->cursor_ctx); + + free(bar->cursor_name); + bar->cursor_name = NULL; + } + + xcb_free_gc(backend->conn, backend->gc); + xcb_free_pixmap(backend->conn, backend->pixmap); + xcb_destroy_window(backend->conn, backend->win); + xcb_free_colormap(backend->conn, backend->colormap); + xcb_flush(backend->conn); + + xcb_disconnect(backend->conn); +} + +static void +loop(struct bar *_bar, + void (*expose)(const struct bar *bar), + void (*on_mouse)(struct bar *bar, enum mouse_event event, int x, int y)) +{ + struct private *bar = _bar->private; + struct xcb_backend *backend = bar->backend.data; + + const int fd = xcb_get_file_descriptor(backend->conn); + + while (true) { + struct pollfd fds[] = { + {.fd = _bar->abort_fd, .events = POLLIN}, + {.fd = fd, .events = POLLIN} + }; + + poll(fds, sizeof(fds) / sizeof(fds[0]), -1); + + if (fds[0].revents && POLLIN) + break; + + if (fds[1].revents & POLLHUP) { + LOG_WARN("disconnected from XCB"); + write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)); + break; + } + + for (xcb_generic_event_t *e = xcb_wait_for_event(backend->conn); + e != NULL; + e = xcb_poll_for_event(backend->conn)) + { + switch (XCB_EVENT_RESPONSE_TYPE(e)) { + case 0: + LOG_ERR("XCB: %s", xcb_error((const xcb_generic_error_t *)e)); + break; + + case XCB_EXPOSE: + expose(_bar); + break; + + case XCB_MOTION_NOTIFY: { + const xcb_motion_notify_event_t *evt = (void *)e; + on_mouse(_bar, ON_MOUSE_MOTION, evt->event_x, evt->event_y); + break; + } + + case XCB_BUTTON_PRESS: + break; + + case XCB_BUTTON_RELEASE: { + const xcb_button_release_event_t *evt = (void *)e; + on_mouse(_bar, ON_MOUSE_CLICK, evt->event_x, evt->event_y); + break; + } + + case XCB_DESTROY_NOTIFY: + LOG_WARN("unimplemented event: XCB_DESTROY_NOTIFY"); + break; + + case XCB_REPARENT_NOTIFY: + case XCB_CONFIGURE_NOTIFY: + case XCB_MAP_NOTIFY: + case XCB_MAPPING_NOTIFY: + /* Just ignore */ + break; + + default: + LOG_ERR("unsupported event: %d", XCB_EVENT_RESPONSE_TYPE(e)); + break; + } + + free(e); + xcb_flush(backend->conn); + } + } +} + +static void +commit_surface(const struct bar *_bar) +{ + const struct private *bar = _bar->private; + const struct xcb_backend *backend = bar->backend.data; + xcb_copy_area(backend->conn, backend->pixmap, backend->win, backend->gc, + 0, 0, 0, 0, bar->width, bar->height_with_border); + xcb_flush(backend->conn); +} + +static void +refresh(const struct bar *_bar) +{ + const struct private *bar = _bar->private; + const struct xcb_backend *backend = bar->backend.data; + + /* Send an event to handle refresh from main thread */ + + /* Note: docs say that all X11 events are 32 bytes, reglardless of + * the size of the event structure */ + xcb_expose_event_t *evt = calloc(32, 1); + + *evt = (xcb_expose_event_t){ + .response_type = XCB_EXPOSE, + .window = backend->win, + .x = 0, + .y = 0, + .width = bar->width, + .height = bar->height, + .count = 1 + }; + + xcb_send_event( + backend->conn, false, backend->win, XCB_EVENT_MASK_EXPOSURE, + (char *)evt); + + xcb_flush(backend->conn); + free(evt); +} + +static void +set_cursor(struct bar *_bar, const char *cursor) +{ + struct private *bar = _bar->private; + struct xcb_backend *backend = bar->backend.data; + + if (bar->cursor_name != NULL && strcmp(bar->cursor_name, cursor) == 0) + return; + + if (backend->cursor_ctx == NULL) + return; + + if (backend->cursor != 0) { + xcb_free_cursor(backend->conn, backend->cursor); + free(bar->cursor_name); + bar->cursor_name = NULL; + } + + bar->cursor_name = strdup(cursor); + backend->cursor = xcb_cursor_load_cursor(backend->cursor_ctx, cursor); + xcb_change_window_attributes( + backend->conn, backend->win, XCB_CW_CURSOR, &backend->cursor); +} + +const struct backend xcb_backend_iface = { + .setup = &setup, + .cleanup = &cleanup, + .loop = &loop, + .commit_surface = &commit_surface, + .refresh = &refresh, + .set_cursor = &set_cursor, +}; diff --git a/bar/xcb.h b/bar/xcb.h new file mode 100644 index 0000000..d9e1529 --- /dev/null +++ b/bar/xcb.h @@ -0,0 +1,7 @@ +#pragma once + +#include "backend.h" + +extern const struct backend xcb_backend_iface; + +void *bar_backend_xcb_new(void); From 36201e251ea0b1cfb062a968ccc6d78ad26cbb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:00:27 +0100 Subject: [PATCH 06/59] bar: no xcb stuff needed directly by bar anymore --- bar/bar.c | 1 - 1 file changed, 1 deletion(-) diff --git a/bar/bar.c b/bar/bar.c index dd9b8fd..6556313 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -17,7 +17,6 @@ #define LOG_MODULE "bar" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../xcb.h" #include "xcb.h" From c2e7b1c5077c3a645f21f1cfcb9de94ae4618159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:01:16 +0100 Subject: [PATCH 07/59] bar: remove more includes that aren't needed anymore --- bar/bar.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bar/bar.c b/bar/bar.c index 6556313..aff1bc0 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -7,10 +7,6 @@ #include #include #include -#include - -#include -#include #include From 4954479e119796c26dbf171953cc584e584b95e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:02:10 +0100 Subject: [PATCH 08/59] bar: generic setup shouldn't be done by a backend --- bar/bar.c | 2 ++ bar/xcb.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bar/bar.c b/bar/bar.c index aff1bc0..aab67ab 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -230,6 +230,8 @@ run(struct bar *_bar) { struct private *bar = _bar->private; + bar->height_with_border = bar->height + 2 * bar->border.width; + if (!bar->backend.iface->setup(_bar)) return 1; diff --git a/bar/xcb.c b/bar/xcb.c index 35da106..bb9c6c6 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -68,8 +68,6 @@ setup(struct bar *_bar) return false; } - bar->height_with_border = bar->height + 2 * bar->border.width; - /* Find monitor coordinates and width/height */ bool found_monitor = false; for (xcb_randr_monitor_info_iterator_t it = From 0684aaaf955c6ac9cb20fb8bf19974cf7adf20ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:03:13 +0100 Subject: [PATCH 09/59] bar: xcb: cleanup --- bar/xcb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bar/xcb.c b/bar/xcb.c index bb9c6c6..88977d6 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -123,7 +123,8 @@ setup(struct bar *_bar) LOG_DBG("using a %hhu-bit visual", depth); backend->colormap = xcb_generate_id(backend->conn); - xcb_create_colormap(backend->conn, 0, backend->colormap, screen->root, vis->visual_id); + xcb_create_colormap( + backend->conn, 0, backend->colormap, screen->root, vis->visual_id); backend->win = xcb_generate_id(backend->conn); xcb_create_window( From 7f1567c973715ad691be64b73bee84479dd69ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:05:28 +0100 Subject: [PATCH 10/59] bar: do generic cursor stuff in bar, not in backend --- bar/bar.c | 7 +++++++ bar/xcb.c | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/bar/bar.c b/bar/bar.c index aab67ab..36d9ed4 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -156,6 +156,13 @@ static void set_cursor(struct bar *bar, const char *cursor) { struct private *b = bar->private; + + if (b->cursor_name != NULL && strcmp(b->cursor_name, cursor) == 0) + return; + + free(b->cursor_name); + b->cursor_name = strdup(cursor); + b->backend.iface->set_cursor(bar, cursor); } diff --git a/bar/xcb.c b/bar/xcb.c index 88977d6..514639a 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -392,19 +392,13 @@ set_cursor(struct bar *_bar, const char *cursor) struct private *bar = _bar->private; struct xcb_backend *backend = bar->backend.data; - if (bar->cursor_name != NULL && strcmp(bar->cursor_name, cursor) == 0) - return; - if (backend->cursor_ctx == NULL) return; if (backend->cursor != 0) { xcb_free_cursor(backend->conn, backend->cursor); - free(bar->cursor_name); - bar->cursor_name = NULL; } - bar->cursor_name = strdup(cursor); backend->cursor = xcb_cursor_load_cursor(backend->cursor_ctx, cursor); xcb_change_window_attributes( backend->conn, backend->win, XCB_CW_CURSOR, &backend->cursor); From 404a7a7dcdeba08c7cf2690424bacfb17323db4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:05:51 +0100 Subject: [PATCH 11/59] bar: xcb: remove unneeded braces --- bar/xcb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bar/xcb.c b/bar/xcb.c index 514639a..a27b34f 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -395,9 +395,8 @@ set_cursor(struct bar *_bar, const char *cursor) if (backend->cursor_ctx == NULL) return; - if (backend->cursor != 0) { + if (backend->cursor != 0) xcb_free_cursor(backend->conn, backend->cursor); - } backend->cursor = xcb_cursor_load_cursor(backend->cursor_ctx, cursor); xcb_change_window_attributes( From 9239d4298c63c46bf7ae1de6ad8b6e7904fb64dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:35:38 +0100 Subject: [PATCH 12/59] main: drop xcb dependency Handle program termination by a) using a signal handler to detect e.g. ctrl-c, and b) listening on the abort_fd to detect when the bar aborts (e.g. due to XCB disconnect, i.e. when the X server dies). --- main.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/main.c b/main.c index f765eb7..fd1c00c 100644 --- a/main.c +++ b/main.c @@ -121,15 +121,6 @@ main(int argc, const char *const *argv) return 1; } - /* Connect to XCB, to be able to detect a disconnect (allowing us - * to exit) */ - xcb_connection_t *xcb = xcb_connect(NULL, NULL); - if (xcb_connection_has_error(xcb) > 0) { - LOG_ERR("failed to connect to X"); - xcb_disconnect(xcb); - return 1; - } - xcb_init(); bar->abort_fd = abort_fd; @@ -140,27 +131,19 @@ main(int argc, const char *const *argv) /* Now unblock. We should be only thread receiving SIGINT */ pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL); - /* Wait for SIGINT, or XCB disconnect */ while (!aborted) { - struct pollfd fds[] = { - {.fd = xcb_get_file_descriptor(xcb), .events = POLLPRI} - }; + struct pollfd fds[] = {{.fd = abort_fd, .events = POLLIN}}; + int r = poll(fds, 1, -1); - poll(fds, 1, -1); - - if (aborted) - break; - - LOG_INFO("XCB poll data"); - - if (fds[0].revents & POLLHUP) { - LOG_INFO("disconnected from XCB, exiting"); - break; - } + /* + * Either the bar aborted (triggering the abort_fd), or user + * killed us (triggering the signal handler which sets + * 'aborted') + */ + assert(aborted || r == 1); + break; } - xcb_disconnect(xcb); - if (aborted) LOG_INFO("aborted: %s (%d)", strsignal(aborted), aborted); From deb9105d3e2718da2e0fbe5c725c197d2975a9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:37:38 +0100 Subject: [PATCH 13/59] main: move xcb_init() call to bar's XCB backend --- bar/xcb.c | 1 + main.c | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/bar/xcb.c b/bar/xcb.c index a27b34f..db854dc 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -34,6 +34,7 @@ struct xcb_backend { void * bar_backend_xcb_new(void) { + xcb_init(); return calloc(1, sizeof(struct xcb_backend)); } diff --git a/main.c b/main.c index fd1c00c..8a35854 100644 --- a/main.c +++ b/main.c @@ -17,7 +17,6 @@ #include "bar.h" #include "config.h" #include "yml.h" -#include "xcb.h" #define LOG_MODULE "main" #include "log.h" @@ -121,8 +120,6 @@ main(int argc, const char *const *argv) return 1; } - xcb_init(); - bar->abort_fd = abort_fd; thrd_t bar_thread; From 785fe8bb0c35af702e284303d0c1445e5978d584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:38:21 +0100 Subject: [PATCH 14/59] main: poll() return value is unused in release builds Because it's only used in an assert() --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 8a35854..5def04c 100644 --- a/main.c +++ b/main.c @@ -130,7 +130,7 @@ main(int argc, const char *const *argv) while (!aborted) { struct pollfd fds[] = {{.fd = abort_fd, .events = POLLIN}}; - int r = poll(fds, 1, -1); + int r __attribute__((unused)) = poll(fds, 1, -1); /* * Either the bar aborted (triggering the abort_fd), or user From ffa4448b3ce74bf195ae188dd04e58b5d2513223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:39:16 +0100 Subject: [PATCH 15/59] ci: build as much as possible --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b7a2014..531f96f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,7 +15,7 @@ debug: - mkdir -p bld/debug - cd bld/debug - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../../ - - ninja + - ninja -k0 release: stage: build @@ -23,4 +23,4 @@ release: - mkdir -p bld/release - cd bld/release - cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel ../../ - - ninja + - ninja -k0 From ff88d87ca8124da7059d8400efe3396b1bbdb75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 29 Jan 2019 21:46:54 +0100 Subject: [PATCH 16/59] cmake: build bar XCB backend as a (static) library This allows us to remove the XCB dependencies from the main 'f00bar' target. --- CMakeLists.txt | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 92d65cd..fc8ecec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,22 @@ pkg_check_modules(FONTCONFIG REQUIRED fontconfig) pkg_check_modules(CAIRO REQUIRED cairo cairo-xcb cairo-ft) pkg_check_modules(YAML REQUIRED yaml-0.1) +add_library(bar-xcb STATIC xcb.c xcb.h bar/xcb.c bar/xcb.h) + +target_compile_options(bar-xcb PRIVATE + ${XCB_CFLAGS_OTHER} + ${XCB_ERRORS_CFLAGS_OTHER} + ${CAIRO_CFLAGS_OTHER} + ) + +target_include_directories(bar-xcb PRIVATE + ${XCB_INCLUDE_DIRS} + ${XCB_ERRORS_INCLUDE_DIRS} + ${CAIRO_INCLUDE_DIRS} + ) + +target_link_libraries(bar-xcb ${XCB_LIBRARIES} ${XCB_ERRORS_LIBRARIES}) + add_executable(f00bar config.c config.h config-verify.c config-verify.h @@ -41,14 +57,14 @@ add_executable(f00bar particle.c particle.h plugin.c plugin.h tag.c tag.h - xcb.c xcb.h yml.c yml.h bar.h bar/bar.c bar/private.h bar/backend.h - bar/xcb.c bar/xcb.h ) +target_link_libraries(f00bar bar-xcb) + # Make global symbols in f00bar visible to dlopen:ed plugins set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic") @@ -57,16 +73,12 @@ if (XCB_ERRORS_FOUND) endif () target_compile_options(f00bar PRIVATE - ${XCB_CFLAGS_OTHER} - ${XCB_ERRORS_CFLAGS_OTHER} ${FONTCONFIG_CFLAGS_OTHER} ${CAIRO_CFLAGS_OTHER} ${YAML_CFLAGS_OTHER} ) target_include_directories(f00bar PRIVATE - ${XCB_INCLUDE_DIRS} - ${XCB_ERRORS_INCLUDE_DIRS} ${FONTCONFIG_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS} ${YAML_INCLUDE_DIRS} @@ -76,8 +88,6 @@ target_link_libraries(f00bar ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} - ${XCB_LIBRARIES} - ${XCB_ERRORS_LIBRARIES} ${FONTCONFIG_LIBRARIES} ${CAIRO_LIBRARIES} ${YAML_LIBRARIES} From ed8e17c6c915d52866ba0ced2cee5368fc36e871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 11:08:53 +0100 Subject: [PATCH 17/59] wayland: mucho wip: initial sort-of-working wayland backend Bar is drawn, though only TOP is supported atm. No screen/display/output selection is possible yet. Mouse *click* works, but not setting the cursor. Lots of debug output, crappy code yada yada. --- CMakeLists.txt | 51 ++++- bar/bar.c | 21 +- bar/wayland.c | 587 +++++++++++++++++++++++++++++++++++++++++++++++++ bar/wayland.h | 7 + main.c | 2 +- 5 files changed, 658 insertions(+), 10 deletions(-) create mode 100644 bar/wayland.c create mode 100644 bar/wayland.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fc8ecec..f190cfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,11 +26,14 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(XCB REQUIRED xcb xcb-aux xcb-cursor xcb-event xcb-ewmh xcb-randr xcb-render) pkg_check_modules(XCB_ERRORS xcb-errors) +pkg_check_modules(WAYLAND REQUIRED wayland-client wlroots) pkg_check_modules(FONTCONFIG REQUIRED fontconfig) pkg_check_modules(CAIRO REQUIRED cairo cairo-xcb cairo-ft) pkg_check_modules(YAML REQUIRED yaml-0.1) -add_library(bar-xcb STATIC xcb.c xcb.h bar/xcb.c bar/xcb.h) +add_library(xcb-stuff STATIC EXCLUDE_FROM_ALL xcb.c xcb.h) + +add_library(bar-xcb STATIC EXCLUDE_FROM_ALL bar/xcb.c bar/xcb.h) target_compile_options(bar-xcb PRIVATE ${XCB_CFLAGS_OTHER} @@ -44,7 +47,49 @@ target_include_directories(bar-xcb PRIVATE ${CAIRO_INCLUDE_DIRS} ) -target_link_libraries(bar-xcb ${XCB_LIBRARIES} ${XCB_ERRORS_LIBRARIES}) +target_link_libraries(bar-xcb xcb-stuff ${XCB_LIBRARIES} ${XCB_ERRORS_LIBRARIES}) + +add_custom_command( + OUTPUT wlr-layer-shell-unstable-v1.c + COMMAND wayland-scanner private-code < /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1.c + VERBATIM + MAIN_DEPENDENCY /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml + ) +add_custom_command( + OUTPUT wlr-layer-shell-unstable-v1-client.h + COMMAND wayland-scanner client-header < /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1-client.h + VERBATIM + MAIN_DEPENDENCY /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml + ) +add_custom_command( + OUTPUT xdg-shell.c + COMMAND wayland-scanner private-code < /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml > xdg-shell.c + VERBATIM + MAIN_DEPENDENCY /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml + ) + +add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL + wlr-layer-shell-unstable-v1-client.h + wlr-layer-shell-unstable-v1.c + xdg-shell.c + ) +target_include_directories(wayland-protocols PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + +add_library(bar-wayland STATIC EXCLUDE_FROM_ALL bar/wayland.c bar/wayland.h) +target_compile_definitions(bar-wayland PRIVATE _GNU_SOURCE) +target_compile_options(bar-wayland PRIVATE + ${WAYLAND_CFLAGS_OTHER} + ${CAIRO_CFLAGS_OTHER} + ) + +target_include_directories(bar-wayland PRIVATE + ${CURRENT_BINARY_DIR} + ${WAYLAND_INCLUDE_DIRS} + ${CAIRO_INCLUDE_DIRS} + ) + +target_link_libraries(bar-wayland wayland-protocols ${WAYLAND_LIBRARIES}) + add_executable(f00bar config.c config.h @@ -63,7 +108,7 @@ add_executable(f00bar bar/bar.c bar/private.h bar/backend.h ) -target_link_libraries(f00bar bar-xcb) +target_link_libraries(f00bar xcb-stuff bar-xcb bar-wayland) # Make global symbols in f00bar visible to dlopen:ed plugins set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic") diff --git a/bar/bar.c b/bar/bar.c index 36d9ed4..6fffeed 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -15,6 +15,7 @@ #include "../log.h" #include "xcb.h" +#include "wayland.h" /* * Calculate total width of left/center/rigth groups. @@ -323,14 +324,17 @@ run(struct bar *_bar) m->destroy(m); } - cairo_destroy(bar->cairo); - cairo_device_finish(cairo_surface_get_device(bar->cairo_surface)); - cairo_surface_finish(bar->cairo_surface); - cairo_surface_destroy(bar->cairo_surface); - cairo_debug_reset_static_data(); - bar->backend.iface->cleanup(_bar); + if (bar->cairo) + cairo_destroy(bar->cairo); + if (bar->cairo_surface) { + cairo_device_finish(cairo_surface_get_device(bar->cairo_surface)); + cairo_surface_finish(bar->cairo_surface); + cairo_surface_destroy(bar->cairo_surface); + } + cairo_debug_reset_static_data(); + LOG_DBG("bar exiting"); return ret; } @@ -379,8 +383,13 @@ bar_new(const struct bar_config *config) //priv->cursor_ctx = NULL; //priv->cursor = 0; priv->cursor_name = NULL; +#if 0 priv->backend.data = bar_backend_xcb_new(); priv->backend.iface = &xcb_backend_iface; +#else + priv->backend.data = bar_backend_wayland_new(); + priv->backend.iface = &wayland_backend_iface; +#endif for (size_t i = 0; i < priv->left.count; i++) { priv->left.mods[i] = config->left.mods[i]; diff --git a/bar/wayland.c b/bar/wayland.c new file mode 100644 index 0000000..b952998 --- /dev/null +++ b/bar/wayland.c @@ -0,0 +1,587 @@ +#include "wayland.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#define LOG_MODULE "bar:wayland" +#include "../log.h" +#include "../tllist.h" + +#include "private.h" + +struct buffer { + bool busy; + size_t size; + void *mmapped; + + struct wl_buffer *wl_buf; + + cairo_surface_t *cairo_surface; + cairo_t *cairo; +}; + +struct wayland_backend { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_shell_v1 *layer_shell; + struct zwlr_layer_surface_v1 *layer_surface; + struct wl_shm *shm; + struct wl_seat *seat; + + struct { + struct wl_pointer *pointer; + int x; + int y; + } pointer; + + /* TODO: set directly in bar instead */ + int width, height; + + /* Used to signal e.g. refresh */ + int pipe_fds[2]; + + /* We're already waiting for a frame done callback */ + bool render_scheduled; + + tll(struct buffer) buffers; /* List of SHM buffers */ + struct buffer *next_buffer; /* Bar is rendering to this one */ + struct buffer *pending_buffer; /* Finished, but not yet rendered */ +}; + +void * +bar_backend_wayland_new(void) +{ + return calloc(1, sizeof(struct wayland_backend)); +} + +static void +shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) +{ + printf("SHM format: 0x%08x\n", format); +} + +static const struct wl_shm_listener shm_listener = { + .format = &shm_format, +}; + +static void +wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) +{ +} + +static void +wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) +{ +} + +static void +wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) +{ + struct wayland_backend *backend = data; + printf("MOTION: %dx%d\n", wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); + backend->pointer.x = wl_fixed_to_int(surface_x); + backend->pointer.y = wl_fixed_to_int(surface_y); +} + +static void +wl_pointer_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) +{ + if (state != WL_POINTER_BUTTON_STATE_PRESSED) + return; + + struct wayland_backend *backend = data; + printf("BUTTON: %dx%d\n", backend->pointer.x, backend->pointer.y); + + write(backend->pipe_fds[1], &(uint8_t){2}, sizeof(uint8_t)); + write(backend->pipe_fds[1], &backend->pointer.x, sizeof(backend->pointer.x)); + write(backend->pipe_fds[1], &backend->pointer.y, sizeof(backend->pointer.y)); +} + +static void +wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ +} + +static void +wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) +{ +} + +static void +wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) +{ +} + +static void +wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) +{ +} + +static void +wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) +{ +} + +static const struct wl_pointer_listener pointer_listener = { + .enter = wl_pointer_enter, + .leave = wl_pointer_leave, + .motion = wl_pointer_motion, + .button = wl_pointer_button, + .axis = wl_pointer_axis, + .frame = wl_pointer_frame, + .axis_source = wl_pointer_axis_source, + .axis_stop = wl_pointer_axis_stop, + .axis_discrete = wl_pointer_axis_discrete, +}; + +static void +seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) +{ + struct wayland_backend *backend = data; + + if (backend->pointer.pointer != NULL) { + wl_pointer_release(backend->pointer.pointer); + backend->pointer.pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_POINTER)) { + backend->pointer.pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(backend->pointer.pointer, &pointer_listener, backend); + } +} + +static void +seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name) +{ + printf("seat: name=%s\n", name); +} + +static const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; + +static void +handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + struct wayland_backend *backend = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + backend->compositor = wl_registry_bind( + registry, name, &wl_compositor_interface, 4); + } + + else if (strcmp(interface, wl_shm_interface.name) == 0) { + backend->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); + wl_shm_add_listener(backend->shm, &shm_listener, backend); + } + + else if (strcmp(interface, wl_output_interface.name) == 0) { + backend->output = wl_registry_bind(registry, name, &wl_output_interface, 3); + //output_add_listener(backend->output, &output_listener, backend); + } + + else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + backend->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); + } + + else if (strcmp(interface, wl_seat_interface.name) == 0) { + backend->seat = wl_registry_bind(registry, name, &wl_seat_interface, 3); + wl_seat_add_listener(backend->seat, &seat_listener, backend); + } +} + +static void +handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ + //struct wayland_backend *backend = data; +} + +static const struct wl_registry_listener registry_listener = { + .global = &handle_global, + .global_remove = &handle_global_remove, +}; + +static void +layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t w, uint32_t h) +{ + struct wayland_backend *backend = data; + backend->width = w; + backend->height = h; + + zwlr_layer_surface_v1_ack_configure(surface, serial); +} + +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, +}; + +static void +buffer_release(void *data, struct wl_buffer *wl_buffer) +{ + printf("buffer release\n"); + struct buffer *buffer = data; + assert(buffer->busy); + buffer->busy = false; +} + +static const struct wl_buffer_listener buffer_listener = { + .release = &buffer_release, +}; + +static struct buffer * +get_buffer(struct wayland_backend *backend) +{ + tll_foreach(backend->buffers, it) { + if (!it->item.busy) { + printf("re-using non-busy buffer\n"); + it->item.busy = true; + return &it->item; + } + } + + printf("allocating a new buffer\n"); + + struct buffer buffer; + + /* Backing memory for SHM */ + int pool_fd = memfd_create("wayland-test-buffer-pool", MFD_CLOEXEC); + assert(pool_fd != -1); + + /* Allocate memory for our single buffer */ + uint32_t stride = backend->width * 4; + buffer.size = stride * backend->height; + ftruncate(pool_fd, buffer.size); + + buffer.mmapped = mmap( + NULL, buffer.size, PROT_READ | PROT_WRITE, MAP_SHARED, pool_fd, 0); + assert(buffer.mmapped != MAP_FAILED); + + struct wl_shm_pool *pool = wl_shm_create_pool(backend->shm, pool_fd, buffer.size); + assert(pool != NULL); + + buffer.wl_buf = wl_shm_pool_create_buffer( + pool, 0, backend->width, backend->height, stride, WL_SHM_FORMAT_ARGB8888); + assert(buffer.wl_buf != NULL); + buffer.busy = true; + + wl_shm_pool_destroy(pool); + close(pool_fd); + + buffer.cairo_surface = cairo_image_surface_create_for_data( + buffer.mmapped, CAIRO_FORMAT_ARGB32, backend->width, backend->height, stride); + buffer.cairo = cairo_create(buffer.cairo_surface); + assert(cairo_status(buffer.cairo) == CAIRO_STATUS_SUCCESS); + + tll_push_back(backend->buffers, buffer); + + struct buffer *ret = &tll_back(backend->buffers); + wl_buffer_add_listener(buffer.wl_buf, &buffer_listener, ret); + return ret; +} + +static bool +setup(struct bar *_bar) +{ + struct private *bar = _bar->private; + struct wayland_backend *backend = bar->backend.data; + + backend->display = wl_display_connect(NULL); + assert(backend->display != NULL); + + backend->registry = wl_display_get_registry(backend->display); + assert(backend->registry != NULL); + + wl_registry_add_listener(backend->registry, ®istry_listener, backend); + + wl_display_roundtrip(backend->display); + assert(backend->compositor != NULL && + backend->layer_shell != NULL && + backend->output != NULL); + + backend->surface = wl_compositor_create_surface(backend->compositor); + assert(backend->surface != NULL); + + backend->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + backend->layer_shell, backend->surface, backend->output, + ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "f00bar"); + assert(backend->layer_surface != NULL); + + /* Aligned to top, maximum width */ + zwlr_layer_surface_v1_set_anchor( + backend->layer_surface, + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP); + + zwlr_layer_surface_v1_set_size(backend->layer_surface, 0, bar->height_with_border); + zwlr_layer_surface_v1_set_exclusive_zone(backend->layer_surface, bar->height_with_border); + + //zwlr_layer_surface_v1_set_margin( + // layer_surface, margin_top, margin_right, margin_bottom, margin_left); + //zwlr_layer_surface_v1_set_keyboard_interactivity( + // layer_surface, keyboard_interactive); + + zwlr_layer_surface_v1_add_listener( + backend->layer_surface, &layer_surface_listener, backend); + + /* Assign width/height */ + wl_surface_commit(backend->surface); + wl_display_roundtrip(backend->display); + + assert(backend->width != -1 && backend->height == bar->height_with_border); + bar->width = backend->width; + + pipe(backend->pipe_fds); + backend->render_scheduled = false; + + wl_surface_commit(backend->surface); + wl_display_roundtrip(backend->display); + + backend->next_buffer = get_buffer(backend); + assert(backend->next_buffer != NULL && backend->next_buffer->busy); + + bar->cairo_surface = backend->next_buffer->cairo_surface; + bar->cairo = backend->next_buffer->cairo; + + return true; +} + +static void +cleanup(struct bar *_bar) +{ + struct private *bar = _bar->private; + struct wayland_backend *backend = bar->backend.data; + + tll_foreach(backend->buffers, it) { + wl_buffer_destroy(it->item.wl_buf); + cairo_destroy(it->item.cairo); + cairo_surface_destroy(it->item.cairo_surface); + munmap(it->item.mmapped, it->item.size); + + tll_remove(backend->buffers, it); + } + + /* TODO: move to bar */ + free(bar->cursor_name); + + zwlr_layer_surface_v1_destroy(backend->layer_surface); + zwlr_layer_shell_v1_destroy(backend->layer_shell); + wl_compositor_destroy(backend->compositor); + wl_surface_destroy(backend->surface); + wl_shm_destroy(backend->shm); + wl_output_destroy(backend->output); + wl_registry_destroy(backend->registry); + wl_display_disconnect(backend->display); + + /* Destroyed when freeing buffer list */ + bar->cairo_surface = NULL; + bar->cairo = NULL; + +} + +static void +loop(struct bar *_bar, + void (*expose)(const struct bar *bar), + void (*on_mouse)(struct bar *bar, enum mouse_event event, int x, int y)) +{ + struct private *bar = _bar->private; + struct wayland_backend *backend = bar->backend.data; + +#if 0 + while (wl_display_prepare_read(backend->display) != 0){ + printf("initial wayland event\n"); + wl_display_dispatch_pending(backend->display); + } + wl_display_flush(backend->display); +#endif + + wl_display_dispatch_pending(backend->display); + wl_display_flush(backend->display); + + while (true) { + struct pollfd fds[] = { + {.fd = _bar->abort_fd, .events = POLLIN}, + {.fd = wl_display_get_fd(backend->display), .events = POLLIN}, + {.fd = backend->pipe_fds[0], .events = POLLIN}, + }; + + wl_display_flush(backend->display); + + printf("polling\n"); + poll(fds, sizeof(fds) / sizeof(fds[0]), -1); + if (fds[0].revents & POLLIN) { + //wl_display_cancel_read(backend->display); + break; + } + + if (fds[1].revents & POLLHUP) { + LOG_WARN("disconnceted from wayland"); + write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)); + break; + } + + if (fds[2].revents & POLLIN) { + uint8_t command; + //wl_display_cancel_read(backend->display); + read(backend->pipe_fds[0], &command, sizeof(command)); + + if (command == 1) { + printf("refresh\n"); + assert(command == 1); + expose(_bar); +#if 0 + while (wl_display_prepare_read(backend->display) != 0) { + printf("queued wayland events\n"); + wl_display_dispatch_pending(backend->display); + } + wl_display_flush(backend->display); +#endif + } + + if (command == 2) { + printf("mouse\n"); + int x, y; + read(backend->pipe_fds[0], &x, sizeof(x)); + read(backend->pipe_fds[0], &y, sizeof(y)); + on_mouse(_bar, ON_MOUSE_CLICK, x, y); + } + continue; + } + +#if 0 + printf("wayland events\n"); + wl_display_read_events(backend->display); + wl_display_dispatch_pending(backend->display); +#endif + printf("wayland events\n"); + wl_display_dispatch(backend->display); + } +} + +static void frame_callback( + void *data, struct wl_callback *wl_callback, uint32_t callback_data); + +static const struct wl_callback_listener frame_listener = { + .done = &frame_callback, +}; + +static void +frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data) +{ + printf("frame callback\n"); + struct private *bar = data; + struct wayland_backend *backend = bar->backend.data; + + backend->render_scheduled = false; + + wl_callback_destroy(wl_callback); + + if (backend->pending_buffer != NULL) { + struct buffer *buffer = backend->pending_buffer; + assert(buffer->busy); + + wl_surface_attach(backend->surface, buffer->wl_buf, 0, 0); + wl_surface_damage(backend->surface, 0, 0, backend->width, backend->height); + + struct wl_callback *cb = wl_surface_frame(backend->surface); + wl_callback_add_listener(cb, &frame_listener, bar); + wl_surface_commit(backend->surface); + + backend->pending_buffer = NULL; + backend->render_scheduled = true; + } else + printf("nothing more to do\n"); +} + +static void +commit_surface(const struct bar *_bar) +{ + struct private *bar = _bar->private; + struct wayland_backend *backend = bar->backend.data; + + printf("commit: %dxl%d\n", backend->width, backend->height); + + assert(backend->next_buffer != NULL); + assert(backend->next_buffer->busy); + + if (backend->render_scheduled) { + printf("already scheduled\n"); + + if (backend->pending_buffer != NULL) + backend->pending_buffer->busy = false; + + backend->pending_buffer = backend->next_buffer; + backend->next_buffer = NULL; + } else { + + printf("scheduling new frame callback\n"); + struct buffer *buffer = backend->next_buffer; + assert(buffer->busy); + + wl_surface_attach(backend->surface, buffer->wl_buf, 0, 0); + wl_surface_damage(backend->surface, 0, 0, backend->width, backend->height); + + struct wl_callback *cb = wl_surface_frame(backend->surface); + wl_callback_add_listener(cb, &frame_listener, bar); + wl_surface_commit(backend->surface); + + backend->render_scheduled = true; + } + + backend->next_buffer = get_buffer(backend); + assert(backend->next_buffer != NULL && backend->next_buffer->busy); + + bar->cairo_surface = backend->next_buffer->cairo_surface; + bar->cairo = backend->next_buffer->cairo; +} + +static void +refresh(const struct bar *_bar) +{ + const struct private *bar = _bar->private; + const struct wayland_backend *backend = bar->backend.data; + + write(backend->pipe_fds[1], &(uint8_t){1}, sizeof(uint8_t)); +} + +static void +set_cursor(struct bar *_bar, const char *cursor) +{ +} + +const struct backend wayland_backend_iface = { + .setup = &setup, + .cleanup = &cleanup, + .loop = &loop, + .commit_surface = &commit_surface, + .refresh = &refresh, + .set_cursor = &set_cursor, +}; diff --git a/bar/wayland.h b/bar/wayland.h new file mode 100644 index 0000000..465ef46 --- /dev/null +++ b/bar/wayland.h @@ -0,0 +1,7 @@ +#pragma once + +#include "backend.h" + +extern const struct backend wayland_backend_iface; + +void *bar_backend_wayland_new(void); diff --git a/main.c b/main.c index 5def04c..78ec0ba 100644 --- a/main.c +++ b/main.c @@ -46,7 +46,7 @@ get_config_path(void) path_max = 1024; char *path = malloc(path_max + 1); - snprintf(path, path_max + 1, "%s/.config/f00bar/config.yml", home_dir); + snprintf(path, path_max + 1, "%s/.config/f00bar/config-wayland.yml", home_dir); return path; } From 8e769b491a7eb09a38525dd67cf9b9536a23b975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 12:20:59 +0100 Subject: [PATCH 18/59] module/i3: try SWAYSOCK before falling back to I3_SOCKET_PATH --- modules/i3.c | 111 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/modules/i3.c b/modules/i3.c index fbd32c7..133ecae 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -371,57 +371,76 @@ handle_workspace_event(struct private *m, const struct json_object *json) return true; } +static bool +get_socket_address_x11(struct sockaddr_un *addr) +{ + int default_screen; + xcb_connection_t *conn = xcb_connect(NULL, &default_screen); + if (xcb_connection_has_error(conn) > 0) { + LOG_ERR("failed to connect to X"); + xcb_disconnect(conn); + return false; + } + + xcb_screen_t *screen = xcb_aux_get_screen(conn, default_screen); + + xcb_atom_t atom = get_atom(conn, "I3_SOCKET_PATH"); + assert(atom != XCB_ATOM_NONE); + + xcb_get_property_cookie_t cookie + = xcb_get_property_unchecked( + conn, false, screen->root, atom, + XCB_GET_PROPERTY_TYPE_ANY, 0, sizeof(addr->sun_path)); + + xcb_generic_error_t *err; + xcb_get_property_reply_t *reply = + xcb_get_property_reply(conn, cookie, &err); + + if (err != NULL) { + LOG_ERR("failed to get i3 socket path: %s", xcb_error(err)); + free(err); + free(reply); + return false; + } + + const int len = xcb_get_property_value_length(reply); + assert(len < sizeof(addr->sun_path)); + + if (len == 0) { + LOG_ERR("failed to get i3 socket path: empty reply"); + free(reply); + return false; + } + + memcpy(addr->sun_path, xcb_get_property_value(reply), len); + addr->sun_path[len] = '\0'; + + free(reply); + xcb_disconnect(conn); + return true; +} + +static bool +get_socket_address(struct sockaddr_un *addr) +{ + *addr = (struct sockaddr_un){.sun_family = AF_UNIX}; + + const char *sway_sock = getenv("SWAYSOCK"); + if (sway_sock == NULL) + return get_socket_address_x11(addr); + + strncpy(addr->sun_path, sway_sock, sizeof(addr->sun_path)); + return true; +} + static int run(struct module *mod) { struct private *m = mod->private; - struct sockaddr_un addr = {.sun_family = AF_UNIX}; - { - int default_screen; - xcb_connection_t *conn = xcb_connect(NULL, &default_screen); - if (xcb_connection_has_error(conn) > 0) { - LOG_ERR("failed to connect to X"); - xcb_disconnect(conn); - return 1; - } - - xcb_screen_t *screen = xcb_aux_get_screen(conn, default_screen); - - xcb_atom_t atom = get_atom(conn, "I3_SOCKET_PATH"); - assert(atom != XCB_ATOM_NONE); - - xcb_get_property_cookie_t cookie - = xcb_get_property_unchecked( - conn, false, screen->root, atom, - XCB_GET_PROPERTY_TYPE_ANY, 0, sizeof(addr.sun_path)); - - xcb_generic_error_t *err; - xcb_get_property_reply_t *reply = - xcb_get_property_reply(conn, cookie, &err); - - if (err != NULL) { - LOG_ERR("failed to get i3 socket path: %s", xcb_error(err)); - free(err); - free(reply); - return 1; - } - - const int len = xcb_get_property_value_length(reply); - assert(len < sizeof(addr.sun_path)); - - if (len == 0) { - LOG_ERR("failed to get i3 socket path: empty reply"); - free(reply); - return 1; - } - - memcpy(addr.sun_path, xcb_get_property_value(reply), len); - addr.sun_path[len] = '\0'; - - free(reply); - xcb_disconnect(conn); - } + struct sockaddr_un addr; + if (!get_socket_address(&addr)) + return 1; int sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock == -1) { From 130043a259ac17246626f77827ab9827881c5868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 12:21:42 +0100 Subject: [PATCH 19/59] bar/wayland: comment out most of the debug logging --- bar/wayland.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/bar/wayland.c b/bar/wayland.c index b952998..35e37ce 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -72,7 +72,7 @@ bar_backend_wayland_new(void) static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) { - printf("SHM format: 0x%08x\n", format); + //printf("SHM format: 0x%08x\n", format); } static const struct wl_shm_listener shm_listener = { @@ -97,7 +97,7 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct wayland_backend *backend = data; - printf("MOTION: %dx%d\n", wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); + //printf("MOTION: %dx%d\n", wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); backend->pointer.x = wl_fixed_to_int(surface_x); backend->pointer.y = wl_fixed_to_int(surface_y); } @@ -110,7 +110,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, return; struct wayland_backend *backend = data; - printf("BUTTON: %dx%d\n", backend->pointer.x, backend->pointer.y); + //printf("BUTTON: %dx%d\n", backend->pointer.x, backend->pointer.y); write(backend->pipe_fds[1], &(uint8_t){2}, sizeof(uint8_t)); write(backend->pipe_fds[1], &backend->pointer.x, sizeof(backend->pointer.x)); @@ -178,7 +178,7 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, static void seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name) { - printf("seat: name=%s\n", name); + //printf("seat: name=%s\n", name); } static const struct wl_seat_listener seat_listener = { @@ -246,7 +246,7 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { static void buffer_release(void *data, struct wl_buffer *wl_buffer) { - printf("buffer release\n"); + //printf("buffer release\n"); struct buffer *buffer = data; assert(buffer->busy); buffer->busy = false; @@ -261,13 +261,13 @@ get_buffer(struct wayland_backend *backend) { tll_foreach(backend->buffers, it) { if (!it->item.busy) { - printf("re-using non-busy buffer\n"); + //printf("re-using non-busy buffer\n"); it->item.busy = true; return &it->item; } } - printf("allocating a new buffer\n"); + //printf("allocating a new buffer\n"); struct buffer buffer; @@ -417,7 +417,7 @@ loop(struct bar *_bar, #if 0 while (wl_display_prepare_read(backend->display) != 0){ - printf("initial wayland event\n"); + //printf("initial wayland event\n"); wl_display_dispatch_pending(backend->display); } wl_display_flush(backend->display); @@ -435,7 +435,7 @@ loop(struct bar *_bar, wl_display_flush(backend->display); - printf("polling\n"); + //printf("polling\n"); poll(fds, sizeof(fds) / sizeof(fds[0]), -1); if (fds[0].revents & POLLIN) { //wl_display_cancel_read(backend->display); @@ -454,12 +454,12 @@ loop(struct bar *_bar, read(backend->pipe_fds[0], &command, sizeof(command)); if (command == 1) { - printf("refresh\n"); + //printf("refresh\n"); assert(command == 1); expose(_bar); #if 0 while (wl_display_prepare_read(backend->display) != 0) { - printf("queued wayland events\n"); + //printf("queued wayland events\n"); wl_display_dispatch_pending(backend->display); } wl_display_flush(backend->display); @@ -467,7 +467,7 @@ loop(struct bar *_bar, } if (command == 2) { - printf("mouse\n"); + //printf("mouse\n"); int x, y; read(backend->pipe_fds[0], &x, sizeof(x)); read(backend->pipe_fds[0], &y, sizeof(y)); @@ -477,11 +477,11 @@ loop(struct bar *_bar, } #if 0 - printf("wayland events\n"); + //printf("wayland events\n"); wl_display_read_events(backend->display); wl_display_dispatch_pending(backend->display); #endif - printf("wayland events\n"); + //printf("wayland events\n"); wl_display_dispatch(backend->display); } } @@ -496,7 +496,7 @@ static const struct wl_callback_listener frame_listener = { static void frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data) { - printf("frame callback\n"); + //printf("frame callback\n"); struct private *bar = data; struct wayland_backend *backend = bar->backend.data; @@ -518,7 +518,7 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da backend->pending_buffer = NULL; backend->render_scheduled = true; } else - printf("nothing more to do\n"); + ;//printf("nothing more to do\n"); } static void @@ -527,13 +527,13 @@ commit_surface(const struct bar *_bar) struct private *bar = _bar->private; struct wayland_backend *backend = bar->backend.data; - printf("commit: %dxl%d\n", backend->width, backend->height); + //printf("commit: %dxl%d\n", backend->width, backend->height); assert(backend->next_buffer != NULL); assert(backend->next_buffer->busy); if (backend->render_scheduled) { - printf("already scheduled\n"); + //printf("already scheduled\n"); if (backend->pending_buffer != NULL) backend->pending_buffer->busy = false; @@ -542,7 +542,7 @@ commit_surface(const struct bar *_bar) backend->next_buffer = NULL; } else { - printf("scheduling new frame callback\n"); + //printf("scheduling new frame callback\n"); struct buffer *buffer = backend->next_buffer; assert(buffer->busy); From 47ac57dd0385134dd3393ec3b07de62de3fd05a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 13:13:10 +0100 Subject: [PATCH 20/59] bar/wayland: cursor support This implements backend.set_cursor(). --- CMakeLists.txt | 2 +- bar/wayland.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f190cfb..7db892f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(XCB REQUIRED xcb xcb-aux xcb-cursor xcb-event xcb-ewmh xcb-randr xcb-render) pkg_check_modules(XCB_ERRORS xcb-errors) -pkg_check_modules(WAYLAND REQUIRED wayland-client wlroots) +pkg_check_modules(WAYLAND REQUIRED wayland-client wayland-cursor wlroots) pkg_check_modules(FONTCONFIG REQUIRED fontconfig) pkg_check_modules(CAIRO REQUIRED cairo cairo-xcb cairo-ft) pkg_check_modules(YAML REQUIRED yaml-0.1) diff --git a/bar/wayland.c b/bar/wayland.c index 35e37ce..be05f76 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -12,6 +12,7 @@ #include #include +#include #include @@ -45,8 +46,14 @@ struct wayland_backend { struct { struct wl_pointer *pointer; + uint32_t serial; + int x; int y; + + struct wl_surface *surface; + struct wl_cursor_theme *theme; + struct wl_cursor *cursor; } pointer; /* TODO: set directly in bar instead */ @@ -79,11 +86,37 @@ static const struct wl_shm_listener shm_listener = { .format = &shm_format, }; +static void +update_cursor_surface(struct wayland_backend *backend) +{ + assert(backend->pointer.cursor != NULL); + + struct wl_cursor_image *image = backend->pointer.cursor->images[0]; + + wl_surface_attach( + backend->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0); + + wl_pointer_set_cursor( + backend->pointer.pointer, backend->pointer.serial, + backend->pointer.surface, image->hotspot_x, image->hotspot_y); + + wl_surface_damage_buffer( + backend->pointer.surface, 0, 0, INT32_MAX, INT32_MAX); + + wl_surface_commit(backend->pointer.surface); +} + static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { + struct wayland_backend *backend = data; + backend->pointer.serial = serial; + backend->pointer.x = wl_fixed_to_int(surface_x); + backend->pointer.y = wl_fixed_to_int(surface_y); + + update_cursor_surface(backend); } static void @@ -100,6 +133,10 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, //printf("MOTION: %dx%d\n", wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); backend->pointer.x = wl_fixed_to_int(surface_x); backend->pointer.y = wl_fixed_to_int(surface_y); + + write(backend->pipe_fds[1], &(uint8_t){3}, sizeof(uint8_t)); + write(backend->pipe_fds[1], &backend->pointer.x, sizeof(backend->pointer.x)); + write(backend->pipe_fds[1], &backend->pointer.y, sizeof(backend->pointer.y)); } static void @@ -324,11 +361,18 @@ setup(struct bar *_bar) wl_display_roundtrip(backend->display); assert(backend->compositor != NULL && backend->layer_shell != NULL && - backend->output != NULL); + backend->output != NULL && + backend->shm != NULL); backend->surface = wl_compositor_create_surface(backend->compositor); assert(backend->surface != NULL); + backend->pointer.surface = wl_compositor_create_surface(backend->compositor); + assert(backend->pointer.surface != NULL); + + backend->pointer.theme = wl_cursor_theme_load(NULL, 24, backend->shm); + assert(backend->pointer.theme != NULL); + backend->layer_surface = zwlr_layer_shell_v1_get_layer_surface( backend->layer_shell, backend->surface, backend->output, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "f00bar"); @@ -394,8 +438,12 @@ cleanup(struct bar *_bar) zwlr_layer_surface_v1_destroy(backend->layer_surface); zwlr_layer_shell_v1_destroy(backend->layer_shell); - wl_compositor_destroy(backend->compositor); + wl_cursor_theme_destroy(backend->pointer.theme); + wl_pointer_destroy(backend->pointer.pointer); + wl_surface_destroy(backend->pointer.surface); wl_surface_destroy(backend->surface); + wl_seat_destroy(backend->seat); + wl_compositor_destroy(backend->compositor); wl_shm_destroy(backend->shm); wl_output_destroy(backend->output); wl_registry_destroy(backend->registry); @@ -473,6 +521,13 @@ loop(struct bar *_bar, read(backend->pipe_fds[0], &y, sizeof(y)); on_mouse(_bar, ON_MOUSE_CLICK, x, y); } + + if (command == 3) { + int x, y; + read(backend->pipe_fds[0], &x, sizeof(x)); + read(backend->pipe_fds[0], &y, sizeof(y)); + on_mouse(_bar, ON_MOUSE_MOTION, x, y); + } continue; } @@ -575,6 +630,13 @@ refresh(const struct bar *_bar) static void set_cursor(struct bar *_bar, const char *cursor) { + struct private *bar = _bar->private; + struct wayland_backend *backend = bar->backend.data; + + backend->pointer.cursor = wl_cursor_theme_get_cursor( + backend->pointer.theme, cursor); + + update_cursor_surface(backend); } const struct backend wayland_backend_iface = { From c226f9f0c811237e0cd003286e491a1459a59c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 13:55:21 +0100 Subject: [PATCH 21/59] bar/wayland: initial support for multiple monitors We don't actually support multiple monitors, but now we at least track the available monitors. This also adds support for the BAR_BOTTOM location. --- bar/wayland.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 6 deletions(-) diff --git a/bar/wayland.c b/bar/wayland.c index be05f76..2b0889a 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -33,6 +33,24 @@ struct buffer { cairo_t *cairo; }; +struct monitor { + struct wayland_backend *backend; + + struct wl_output *output; + char *name; + + int x; + int y; + + int width_mm; + int height_mm; + + int width_px; + int height_px; + + int scale; +}; + struct wayland_backend { struct wl_display *display; struct wl_registry *registry; @@ -56,6 +74,9 @@ struct wayland_backend { struct wl_cursor *cursor; } pointer; + tll(struct monitor) monitors; + const struct monitor *monitor; + /* TODO: set directly in bar instead */ int width, height; @@ -223,6 +244,53 @@ static const struct wl_seat_listener seat_listener = { .name = seat_handle_name, }; +static void +output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, + int32_t physical_width, int32_t physical_height, + int32_t subpixel, const char *make, const char *model, + int32_t transform) +{ + //printf("output: %s (%s): %dx%dmm %dx%d\n", + // make, model, physical_width, physical_height, x, y); + struct monitor *mon = data; + mon->x = x; + mon->y = y; + mon->width_mm = physical_width; + mon->height_mm = physical_height; + mon->name = NULL; +} + +static void +output_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int32_t width, int32_t height, int32_t refresh) +{ + //printf("output: %dx%d\n", width, height); + struct monitor *mon = data; + mon->width_px = width; + mon->height_px = height; +} + +static void +output_done(void *data, struct wl_output *wl_output) +{ +} + +static void +output_scale(void *data, struct wl_output *wl_output, int32_t factor) +{ + //printf("output: scale: %d\n", factor); + struct monitor *mon = data; + mon->scale = factor; +} + + +static const struct wl_output_listener output_listener = { + .geometry = &output_geometry, + .mode = &output_mode, + .done = &output_done, + .scale = &output_scale, +}; + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) @@ -236,11 +304,18 @@ handle_global(void *data, struct wl_registry *registry, else if (strcmp(interface, wl_shm_interface.name) == 0) { backend->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); wl_shm_add_listener(backend->shm, &shm_listener, backend); + wl_display_roundtrip(backend->display); } else if (strcmp(interface, wl_output_interface.name) == 0) { - backend->output = wl_registry_bind(registry, name, &wl_output_interface, 3); - //output_add_listener(backend->output, &output_listener, backend); + struct wl_output *output = wl_registry_bind( + registry, name, &wl_output_interface, 3); + + tll_push_back(backend->monitors, ((struct monitor){ + .backend = backend, + .output = output})); + wl_output_add_listener(output, &output_listener, &tll_back(backend->monitors)); + wl_display_roundtrip(backend->display); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { @@ -251,6 +326,7 @@ handle_global(void *data, struct wl_registry *registry, else if (strcmp(interface, wl_seat_interface.name) == 0) { backend->seat = wl_registry_bind(registry, name, &wl_seat_interface, 3); wl_seat_add_listener(backend->seat, &seat_listener, backend); + wl_display_roundtrip(backend->display); } } @@ -361,9 +437,18 @@ setup(struct bar *_bar) wl_display_roundtrip(backend->display); assert(backend->compositor != NULL && backend->layer_shell != NULL && - backend->output != NULL && backend->shm != NULL); + tll_foreach(backend->monitors, it) { + const struct monitor *mon = &it->item; + LOG_INFO("monitor: %s: %dx%d+%d+%d (%dx%dmm)", + mon->name, mon->width_px, mon->height_px, + mon->x, mon->y, mon->width_mm, mon->height_mm); + + /* TODO */ + backend->monitor = mon; + } + backend->surface = wl_compositor_create_surface(backend->compositor); assert(backend->surface != NULL); @@ -374,7 +459,7 @@ setup(struct bar *_bar) assert(backend->pointer.theme != NULL); backend->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - backend->layer_shell, backend->surface, backend->output, + backend->layer_shell, backend->surface, backend->monitor->output, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "f00bar"); assert(backend->layer_surface != NULL); @@ -383,7 +468,10 @@ setup(struct bar *_bar) backend->layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | - ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP); + ((bar->location == BAR_TOP) + ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) + ); zwlr_layer_surface_v1_set_size(backend->layer_surface, 0, bar->height_with_border); zwlr_layer_surface_v1_set_exclusive_zone(backend->layer_surface, bar->height_with_border); @@ -402,6 +490,11 @@ setup(struct bar *_bar) assert(backend->width != -1 && backend->height == bar->height_with_border); bar->width = backend->width; + bar->x = backend->monitor->x; + bar->y = backend->monitor->y; + bar->y += bar->location == BAR_TOP + ? 0 + : backend->monitor->height_px - bar->height_with_border; pipe(backend->pipe_fds); backend->render_scheduled = false; @@ -445,7 +538,12 @@ cleanup(struct bar *_bar) wl_seat_destroy(backend->seat); wl_compositor_destroy(backend->compositor); wl_shm_destroy(backend->shm); - wl_output_destroy(backend->output); + tll_foreach(backend->monitors, it) { + struct monitor *mon = &it->item; + free(mon->name); + wl_output_destroy(mon->output); + tll_remove(backend->monitors, it); + } wl_registry_destroy(backend->registry); wl_display_disconnect(backend->display); From c6fd99f0056487b98a684b9047aa9a25fbfd69f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 15:10:26 +0100 Subject: [PATCH 22/59] bar/wayland: track XDG outputs, as this gets us the monitor identifiers --- CMakeLists.txt | 14 ++++++++++ bar/wayland.c | 73 +++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 77 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7db892f..aaf696e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,11 +67,25 @@ add_custom_command( VERBATIM MAIN_DEPENDENCY /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml ) +add_custom_command( + OUTPUT xdg-output-unstable-v1-client.h + COMMAND wayland-scanner client-header < /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1-client.h + VERBATIM + MAIN_DEPENDENCY /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml + ) +add_custom_command( + OUTPUT xdg-output-unstable-v1.c + COMMAND wayland-scanner private-code < /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1.c + VERBATIM + MAIN_DEPENDENCY /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml + ) add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL wlr-layer-shell-unstable-v1-client.h wlr-layer-shell-unstable-v1.c xdg-shell.c + xdg-output-unstable-v1-client.h + xdg-output-unstable-v1.c ) target_include_directories(wayland-protocols PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/bar/wayland.c b/bar/wayland.c index 2b0889a..1ef3822 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -14,6 +14,7 @@ #include #include +#include #include #define LOG_MODULE "bar:wayland" @@ -37,6 +38,7 @@ struct monitor { struct wayland_backend *backend; struct wl_output *output; + struct zxdg_output_v1 *xdg; char *name; int x; @@ -55,7 +57,6 @@ struct wayland_backend { struct wl_display *display; struct wl_registry *registry; struct wl_compositor *compositor; - struct wl_output *output; struct wl_surface *surface; struct zwlr_layer_shell_v1 *layer_shell; struct zwlr_layer_surface_v1 *layer_surface; @@ -77,6 +78,8 @@ struct wayland_backend { tll(struct monitor) monitors; const struct monitor *monitor; + struct zxdg_output_manager_v1 *xdg_output_manager; + /* TODO: set directly in bar instead */ int width, height; @@ -236,7 +239,6 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, static void seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name) { - //printf("seat: name=%s\n", name); } static const struct wl_seat_listener seat_listener = { @@ -250,21 +252,17 @@ output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t subpixel, const char *make, const char *model, int32_t transform) { - //printf("output: %s (%s): %dx%dmm %dx%d\n", - // make, model, physical_width, physical_height, x, y); struct monitor *mon = data; mon->x = x; mon->y = y; mon->width_mm = physical_width; mon->height_mm = physical_height; - mon->name = NULL; } static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { - //printf("output: %dx%d\n", width, height); struct monitor *mon = data; mon->width_px = width; mon->height_px = height; @@ -278,7 +276,6 @@ output_done(void *data, struct wl_output *wl_output) static void output_scale(void *data, struct wl_output *wl_output, int32_t factor) { - //printf("output: scale: %d\n", factor); struct monitor *mon = data; mon->scale = factor; } @@ -291,6 +288,46 @@ static const struct wl_output_listener output_listener = { .scale = &output_scale, }; +static void +xdg_output_handle_logical_position(void *data, + struct zxdg_output_v1 *xdg_output, + int32_t x, int32_t y) +{ +} + +static void +xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, + int32_t width, int32_t height) +{ +} + +static void +xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) +{ +} + +static void +xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, + const char *name) +{ + struct monitor *mon = data; + mon->name = strdup(name); +} + +static void +xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, + const char *description) +{ +} + +static struct zxdg_output_v1_listener xdg_output_listener = { + .logical_position = xdg_output_handle_logical_position, + .logical_size = xdg_output_handle_logical_size, + .done = xdg_output_handle_done, + .name = xdg_output_handle_name, + .description = xdg_output_handle_description, +}; + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) @@ -314,7 +351,15 @@ handle_global(void *data, struct wl_registry *registry, tll_push_back(backend->monitors, ((struct monitor){ .backend = backend, .output = output})); - wl_output_add_listener(output, &output_listener, &tll_back(backend->monitors)); + + struct monitor *mon = &tll_back(backend->monitors); + wl_output_add_listener(output, &output_listener, mon); + + assert(backend->xdg_output_manager != NULL); + mon->xdg = zxdg_output_manager_v1_get_xdg_output( + backend->xdg_output_manager, mon->output); + + zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon); wl_display_roundtrip(backend->display); } @@ -328,6 +373,11 @@ handle_global(void *data, struct wl_registry *registry, wl_seat_add_listener(backend->seat, &seat_listener, backend); wl_display_roundtrip(backend->display); } + + else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { + backend->xdg_output_manager = wl_registry_bind( + registry, name, &zxdg_output_manager_v1_interface, 2); + } } static void @@ -445,8 +495,11 @@ setup(struct bar *_bar) mon->name, mon->width_px, mon->height_px, mon->x, mon->y, mon->width_mm, mon->height_mm); - /* TODO */ - backend->monitor = mon; + /* TODO: detect primary output when user hasn't specified a monitor */ + if (bar->monitor == NULL) + backend->monitor = mon; + else if (strcmp(bar->monitor, mon->name) == 0) + backend->monitor = mon; } backend->surface = wl_compositor_create_surface(backend->compositor); From 85a1940e4799ed7da23f2ce8f74872ca0551bc35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 15:16:19 +0100 Subject: [PATCH 23/59] bar/wayland: free XDG outputs, and manager, in cleanup() --- bar/wayland.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/bar/wayland.c b/bar/wayland.c index 1ef3822..05d0a28 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -355,6 +355,12 @@ handle_global(void *data, struct wl_registry *registry, struct monitor *mon = &tll_back(backend->monitors); wl_output_add_listener(output, &output_listener, mon); + /* + * The "output" interface doesn't give us the monitors' + * identifiers (e.g. "LVDS-1"). Use the XDG output interface + * for that. + */ + assert(backend->xdg_output_manager != NULL); mon->xdg = zxdg_output_manager_v1_get_xdg_output( backend->xdg_output_manager, mon->output); @@ -383,7 +389,6 @@ handle_global(void *data, struct wl_registry *registry, static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { - //struct wayland_backend *backend = data; } static const struct wl_registry_listener registry_listener = { @@ -579,6 +584,15 @@ cleanup(struct bar *_bar) tll_remove(backend->buffers, it); } + tll_foreach(backend->monitors, it) { + struct monitor *mon = &it->item; + free(mon->name); + zxdg_output_v1_destroy(mon->xdg); + wl_output_destroy(mon->output); + tll_remove(backend->monitors, it); + } + zxdg_output_manager_v1_destroy(backend->xdg_output_manager); + /* TODO: move to bar */ free(bar->cursor_name); @@ -591,12 +605,6 @@ cleanup(struct bar *_bar) wl_seat_destroy(backend->seat); wl_compositor_destroy(backend->compositor); wl_shm_destroy(backend->shm); - tll_foreach(backend->monitors, it) { - struct monitor *mon = &it->item; - free(mon->name); - wl_output_destroy(mon->output); - tll_remove(backend->monitors, it); - } wl_registry_destroy(backend->registry); wl_display_disconnect(backend->display); From 29b57bcc48d05a6ba2bb1cdc1cd9d953c7267219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 15:28:32 +0100 Subject: [PATCH 24/59] bar/wayland: call on_mouse() directly from listeners --- bar/wayland.c | 70 ++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/bar/wayland.c b/bar/wayland.c index 05d0a28..37cb594 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -54,6 +54,8 @@ struct monitor { }; struct wayland_backend { + struct bar *bar; + struct wl_display *display; struct wl_registry *registry; struct wl_compositor *compositor; @@ -92,6 +94,9 @@ struct wayland_backend { tll(struct buffer) buffers; /* List of SHM buffers */ struct buffer *next_buffer; /* Bar is rendering to this one */ struct buffer *pending_buffer; /* Finished, but not yet rendered */ + + void (*bar_expose)(const struct bar *bar); + void (*bar_on_mouse)(struct bar *bar, enum mouse_event event, int x, int y); }; void * @@ -154,13 +159,12 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct wayland_backend *backend = data; - //printf("MOTION: %dx%d\n", wl_fixed_to_int(surface_x), wl_fixed_to_int(surface_y)); + backend->pointer.x = wl_fixed_to_int(surface_x); backend->pointer.y = wl_fixed_to_int(surface_y); - write(backend->pipe_fds[1], &(uint8_t){3}, sizeof(uint8_t)); - write(backend->pipe_fds[1], &backend->pointer.x, sizeof(backend->pointer.x)); - write(backend->pipe_fds[1], &backend->pointer.y, sizeof(backend->pointer.y)); + backend->bar_on_mouse( + backend->bar, ON_MOUSE_MOTION, backend->pointer.x, backend->pointer.y); } static void @@ -171,11 +175,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, return; struct wayland_backend *backend = data; - //printf("BUTTON: %dx%d\n", backend->pointer.x, backend->pointer.y); - - write(backend->pipe_fds[1], &(uint8_t){2}, sizeof(uint8_t)); - write(backend->pipe_fds[1], &backend->pointer.x, sizeof(backend->pointer.x)); - write(backend->pipe_fds[1], &backend->pointer.y, sizeof(backend->pointer.y)); + backend->bar_on_mouse( + backend->bar, ON_MOUSE_CLICK, backend->pointer.x, backend->pointer.y); } static void @@ -481,6 +482,8 @@ setup(struct bar *_bar) struct private *bar = _bar->private; struct wayland_backend *backend = bar->backend.data; + backend->bar = _bar; + backend->display = wl_display_connect(NULL); assert(backend->display != NULL); @@ -622,6 +625,9 @@ loop(struct bar *_bar, struct private *bar = _bar->private; struct wayland_backend *backend = bar->backend.data; + backend->bar_expose = expose; + backend->bar_on_mouse = on_mouse; + #if 0 while (wl_display_prepare_read(backend->display) != 0){ //printf("initial wayland event\n"); @@ -660,43 +666,27 @@ loop(struct bar *_bar, //wl_display_cancel_read(backend->display); read(backend->pipe_fds[0], &command, sizeof(command)); - if (command == 1) { - //printf("refresh\n"); - assert(command == 1); - expose(_bar); + assert(command == 1); + //printf("refresh\n"); + expose(_bar); #if 0 - while (wl_display_prepare_read(backend->display) != 0) { - //printf("queued wayland events\n"); - wl_display_dispatch_pending(backend->display); - } - wl_display_flush(backend->display); + while (wl_display_prepare_read(backend->display) != 0) { + //printf("queued wayland events\n"); + wl_display_dispatch_pending(backend->display); + } + wl_display_flush(backend->display); #endif - } - - if (command == 2) { - //printf("mouse\n"); - int x, y; - read(backend->pipe_fds[0], &x, sizeof(x)); - read(backend->pipe_fds[0], &y, sizeof(y)); - on_mouse(_bar, ON_MOUSE_CLICK, x, y); - } - - if (command == 3) { - int x, y; - read(backend->pipe_fds[0], &x, sizeof(x)); - read(backend->pipe_fds[0], &y, sizeof(y)); - on_mouse(_bar, ON_MOUSE_MOTION, x, y); - } - continue; } + if (fds[1].revents & POLLIN) { #if 0 - //printf("wayland events\n"); - wl_display_read_events(backend->display); - wl_display_dispatch_pending(backend->display); + //printf("wayland events\n"); + wl_display_read_events(backend->display); + wl_display_dispatch_pending(backend->display); #endif - //printf("wayland events\n"); - wl_display_dispatch(backend->display); + //printf("wayland events\n"); + wl_display_dispatch(backend->display); + } } } From 92d165e7e69cf975c54e36f5a8f49432f9d889e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 17:29:41 +0100 Subject: [PATCH 25/59] ci: switch to alpine:edge, which has wlroots --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 531f96f..df2e0fb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: alpine:latest +image: alpine:edge stages: - build @@ -7,6 +7,7 @@ before_script: - apk update - apk add musl-dev eudev-libs eudev-dev linux-headers cmake ninja gcc - apk add libxcb-dev xcb-util-wm-dev xcb-util-cursor-dev cairo-dev yaml-dev + - apk add wayland wlroots - apk add json-c-dev libmpdclient-dev alsa-lib-dev i3wm debug: From 9ad7626b3f73ccd3e3221ab0e5b4cf81845c03ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 17:32:24 +0100 Subject: [PATCH 26/59] ci: how about now? --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index df2e0fb..ee57ce0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ before_script: - apk update - apk add musl-dev eudev-libs eudev-dev linux-headers cmake ninja gcc - apk add libxcb-dev xcb-util-wm-dev xcb-util-cursor-dev cairo-dev yaml-dev - - apk add wayland wlroots + - apk add wayland - apk add json-c-dev libmpdclient-dev alsa-lib-dev i3wm debug: From c7c378d8443a02390ff50a7148b3c8517acbb640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 17:34:15 +0100 Subject: [PATCH 27/59] ci: again --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ee57ce0..ce78c4d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ before_script: - apk update - apk add musl-dev eudev-libs eudev-dev linux-headers cmake ninja gcc - apk add libxcb-dev xcb-util-wm-dev xcb-util-cursor-dev cairo-dev yaml-dev - - apk add wayland + - apk add wayland-dev sway - apk add json-c-dev libmpdclient-dev alsa-lib-dev i3wm debug: From 38c87ad1652f307791ed3e558150298337079272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 17:35:29 +0100 Subject: [PATCH 28/59] ci: nein --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ce78c4d..f2d1422 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ before_script: - apk update - apk add musl-dev eudev-libs eudev-dev linux-headers cmake ninja gcc - apk add libxcb-dev xcb-util-wm-dev xcb-util-cursor-dev cairo-dev yaml-dev - - apk add wayland-dev sway + - apk add wayland-dev - apk add json-c-dev libmpdclient-dev alsa-lib-dev i3wm debug: From 73c62e97979df803e07f7a3d9c7296e162700339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 17:45:26 +0100 Subject: [PATCH 29/59] bar/wayland: cleanup --- bar/bar.c | 3 +-- bar/wayland.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/bar/bar.c b/bar/bar.c index 6fffeed..dc0b5bd 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -380,9 +380,8 @@ bar_new(const struct bar_config *config) priv->left.count = config->left.count; priv->center.count = config->center.count; priv->right.count = config->right.count; - //priv->cursor_ctx = NULL; - //priv->cursor = 0; priv->cursor_name = NULL; + #if 0 priv->backend.data = bar_backend_xcb_new(); priv->backend.iface = &xcb_backend_iface; diff --git a/bar/wayland.c b/bar/wayland.c index 37cb594..a56f186 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -525,17 +525,20 @@ setup(struct bar *_bar) assert(backend->layer_surface != NULL); /* Aligned to top, maximum width */ + enum zwlr_layer_surface_v1_anchor top_or_bottom = bar->location == BAR_TOP + ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + zwlr_layer_surface_v1_set_anchor( backend->layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | - ((bar->location == BAR_TOP) - ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP - : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) - ); + top_or_bottom); - zwlr_layer_surface_v1_set_size(backend->layer_surface, 0, bar->height_with_border); - zwlr_layer_surface_v1_set_exclusive_zone(backend->layer_surface, bar->height_with_border); + zwlr_layer_surface_v1_set_size( + backend->layer_surface, 0, bar->height_with_border); + zwlr_layer_surface_v1_set_exclusive_zone( + backend->layer_surface, bar->height_with_border); //zwlr_layer_surface_v1_set_margin( // layer_surface, margin_top, margin_right, margin_bottom, margin_left); @@ -545,7 +548,7 @@ setup(struct bar *_bar) zwlr_layer_surface_v1_add_listener( backend->layer_surface, &layer_surface_listener, backend); - /* Assign width/height */ + /* Trigger a 'configure' event, after which we'll have the width */ wl_surface_commit(backend->surface); wl_display_roundtrip(backend->display); From 578c76326dbcc626498543969af564f306d86fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 19:12:58 +0100 Subject: [PATCH 30/59] cmake: pull in wlr-layer-shell-unstable-v1 from wlroots git submodule --- .gitmodules | 3 +++ CMakeLists.txt | 4 ++-- external/wlroots | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .gitmodules create mode 160000 external/wlroots diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..887b1f9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/wlroots"] + path = external/wlroots + url = https://github.com/swaywm/wlroots.git diff --git a/CMakeLists.txt b/CMakeLists.txt index aaf696e..85a5954 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,9 +51,9 @@ target_link_libraries(bar-xcb xcb-stuff ${XCB_LIBRARIES} ${XCB_ERRORS_LIBRARIES} add_custom_command( OUTPUT wlr-layer-shell-unstable-v1.c - COMMAND wayland-scanner private-code < /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1.c + COMMAND wayland-scanner private-code < ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1.c VERBATIM - MAIN_DEPENDENCY /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml + MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml ) add_custom_command( OUTPUT wlr-layer-shell-unstable-v1-client.h diff --git a/external/wlroots b/external/wlroots new file mode 160000 index 0000000..59d1b67 --- /dev/null +++ b/external/wlroots @@ -0,0 +1 @@ +Subproject commit 59d1b6790dd187c2e110e98a2fa17c1fbfee40ca From f3b225adf7bf8ea6a4b52c92f0e2b71b825b240e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 19:27:03 +0100 Subject: [PATCH 31/59] make: let pkg_check_module() create targets --- CMakeLists.txt | 79 ++++++++++-------------------------------- modules/CMakeLists.txt | 43 ++++++++--------------- 2 files changed, 33 insertions(+), 89 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 85a5954..9a5a32d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,31 +23,23 @@ set(CMAKE_C_FLAGS "-Wall -Werror ${CMAKE_C_FLAGS}") find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) -pkg_check_modules(XCB REQUIRED xcb xcb-aux xcb-cursor xcb-event xcb-ewmh - xcb-randr xcb-render) -pkg_check_modules(XCB_ERRORS xcb-errors) -pkg_check_modules(WAYLAND REQUIRED wayland-client wayland-cursor wlroots) -pkg_check_modules(FONTCONFIG REQUIRED fontconfig) -pkg_check_modules(CAIRO REQUIRED cairo cairo-xcb cairo-ft) -pkg_check_modules(YAML REQUIRED yaml-0.1) +pkg_check_modules(xcb REQUIRED IMPORTED_TARGET + xcb xcb-aux xcb-cursor xcb-event xcb-ewmh xcb-randr xcb-render) +pkg_check_modules(xcb-errors IMPORTED_TARGET xcb-errors) +pkg_check_modules(wayland REQUIRED IMPORTED_TARGET + wayland-client wayland-cursor wlroots) +pkg_check_modules(fontconfig REQUIRED IMPORTED_TARGET fontconfig) +pkg_check_modules(cairo REQUIRED IMPORTED_TARGET cairo cairo-xcb cairo-ft) +pkg_check_modules(yaml REQUIRED IMPORTED_TARGET yaml-0.1) add_library(xcb-stuff STATIC EXCLUDE_FROM_ALL xcb.c xcb.h) +if (XCB_ERRORS_FOUND) + target_compile_definitions(xcb-stuff PRIVATE HAVE_XCB_ERRORS) +endif () add_library(bar-xcb STATIC EXCLUDE_FROM_ALL bar/xcb.c bar/xcb.h) - -target_compile_options(bar-xcb PRIVATE - ${XCB_CFLAGS_OTHER} - ${XCB_ERRORS_CFLAGS_OTHER} - ${CAIRO_CFLAGS_OTHER} - ) - -target_include_directories(bar-xcb PRIVATE - ${XCB_INCLUDE_DIRS} - ${XCB_ERRORS_INCLUDE_DIRS} - ${CAIRO_INCLUDE_DIRS} - ) - -target_link_libraries(bar-xcb xcb-stuff ${XCB_LIBRARIES} ${XCB_ERRORS_LIBRARIES}) +target_link_libraries(bar-xcb + xcb-stuff PkgConfig::xcb PkgConfig::xcb-errors PkgConfig::cairo) add_custom_command( OUTPUT wlr-layer-shell-unstable-v1.c @@ -91,19 +83,8 @@ target_include_directories(wayland-protocols PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) add_library(bar-wayland STATIC EXCLUDE_FROM_ALL bar/wayland.c bar/wayland.h) target_compile_definitions(bar-wayland PRIVATE _GNU_SOURCE) -target_compile_options(bar-wayland PRIVATE - ${WAYLAND_CFLAGS_OTHER} - ${CAIRO_CFLAGS_OTHER} - ) - -target_include_directories(bar-wayland PRIVATE - ${CURRENT_BINARY_DIR} - ${WAYLAND_INCLUDE_DIRS} - ${CAIRO_INCLUDE_DIRS} - ) - -target_link_libraries(bar-wayland wayland-protocols ${WAYLAND_LIBRARIES}) - +target_link_libraries( + bar-wayland wayland-protocols PkgConfig::wayland PkgConfig::cairo) add_executable(f00bar config.c config.h @@ -122,36 +103,14 @@ add_executable(f00bar bar/bar.c bar/private.h bar/backend.h ) -target_link_libraries(f00bar xcb-stuff bar-xcb bar-wayland) +target_link_libraries(f00bar + bar-xcb bar-wayland + PkgConfig::cairo PkgConfig::fontconfig PkgConfig::yaml + ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) # Make global symbols in f00bar visible to dlopen:ed plugins set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic") -if (XCB_ERRORS_FOUND) - target_compile_definitions(f00bar PRIVATE HAVE_XCB_ERRORS) -endif () - -target_compile_options(f00bar PRIVATE - ${FONTCONFIG_CFLAGS_OTHER} - ${CAIRO_CFLAGS_OTHER} - ${YAML_CFLAGS_OTHER} - ) - -target_include_directories(f00bar PRIVATE - ${FONTCONFIG_INCLUDE_DIRS} - ${CAIRO_INCLUDE_DIRS} - ${YAML_INCLUDE_DIRS} - ) - -target_link_libraries(f00bar - ${CMAKE_THREAD_LIBS_INIT} - ${CMAKE_DL_LIBS} - - ${FONTCONFIG_LIBRARIES} - ${CAIRO_LIBRARIES} - ${YAML_LIBRARIES} - ) - set_property(TARGET f00bar PROPERTY INSTALL_RPATH \$ORIGIN/../lib/f00bar) set_property(TARGET f00bar PROPERTY BUILD_RPATH "\$ORIGIN/modules;\$ORIGIN/particles;\$ORIGIN/decorations") diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index d4dc54f..0a92ac9 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,9 +1,8 @@ cmake_minimum_required(VERSION 3.7) add_library(module-sdk INTERFACE) -target_compile_options(module-sdk INTERFACE ${CAIRO_CFLAGS_OTHER}) -target_include_directories(module-sdk INTERFACE ${CAIRO_INCLUDE_DIRS}) -target_link_libraries(module-sdk INTERFACE ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries( + module-sdk INTERFACE PkgConfig::cairo ${CMAKE_THREAD_LIBS_INIT}) if (CORE_PLUGINS_AS_SHARED_LIBRARIES) set(lib_type MODULE) @@ -13,58 +12,44 @@ endif () set(CMAKE_SHARED_${lib_type}_PREFIX module_) -pkg_check_modules(ALSA REQUIRED alsa) +pkg_check_modules(alsa REQUIRED IMPORTED_TARGET alsa) add_library(alsa ${lib_type} alsa.c) -target_compile_options(alsa PRIVATE ${ALSA_CFLAGS_OTHER}) -target_include_directories(alsa PRIVATE ${ALSA_INCLUDE_DIRS}) -target_link_libraries(alsa module-sdk ${ALSA_LIBRARIES}) +target_link_libraries(alsa module-sdk PkgConfig::alsa) -pkg_check_modules(UDEV REQUIRED libudev) +pkg_check_modules(udev REQUIRED IMPORTED_TARGET libudev) add_library(backlight ${lib_type} backlight.c) -target_compile_options(backlight PRIVATE ${UDEV_CFLAGS_OTHER}) -target_include_directories(backlight PRIVATE ${UDEV_INCLUDE_DIRS}) -target_link_libraries(backlight module-sdk ${UDEV_LIBRARIES}) +target_link_libraries(backlight module-sdk PkgConfig::udev) add_library(battery ${lib_type} battery.c) -target_compile_options(battery PRIVATE ${UDEV_CFLAGS_OTHER}) -target_include_directories(battery PRIVATE ${UDEV_INCLUDE_DIRS}) -target_link_libraries(battery module-sdk ${UDEV_LIBRARIES}) +target_link_libraries(battery module-sdk PkgConfig::udev) add_library(clock ${lib_type} clock.c) target_link_libraries(clock module-sdk) -pkg_check_modules(JSON REQUIRED json-c) +pkg_check_modules(json REQUIRED IMPORTED_TARGET json-c) find_file(I3_IPC_H i3/ipc.h) if (NOT I3_IPC_H) message(FATAL_ERROR "cannot find header file: i3/ipc.h") endif () add_library(i3 ${lib_type} i3.c) -target_compile_options(i3 PRIVATE ${JSON_CFLAGS_OTHER}) -target_include_directories(i3 PRIVATE ${JSON_INCLUDE_DIRS}) -target_link_libraries(i3 module-sdk dynlist ${JSON_LIBRARIES}) +target_link_libraries(i3 module-sdk dynlist PkgConfig::json) add_library(label ${lib_type} label.c) target_link_libraries(label module-sdk) -pkg_check_modules(MPD REQUIRED libmpdclient) +pkg_check_modules(mpd REQUIRED IMPORTED_TARGET libmpdclient) add_library(mpd ${lib_type} mpd.c) -target_compile_options(mpd PRIVATE ${MPD_CFLAGS_OTHER}) -target_include_directories(mpd PRIVATE ${MPD_INCLUDE_DIRS}) -target_link_libraries(mpd module-sdk ${MPD_LIBRARIES}) +target_link_libraries(mpd module-sdk PkgConfig::mpd) add_library(network ${lib_type} network.c) target_link_libraries(network module-sdk) add_library(removables ${lib_type} removables.c) -target_compile_options(removables PRIVATE ${UDEV_CFLAGS_OTHER}) -target_include_directories(removables PRIVATE ${UDEV_INCLUDE_DIRS}) -target_link_libraries(removables module-sdk dynlist ${UDEV_LIBRARIES}) +target_link_libraries(removables module-sdk dynlist PkgConfig::udev) -pkg_check_modules(XCB_XKB REQUIRED xcb-xkb) +pkg_check_modules(xkb REQUIRED IMPORTED_TARGET xcb-xkb) add_library(xkb ${lib_type} xkb.c) -target_compile_options(xkb PRIVATE ${XCB_XKB_CFLAGS_OTHER}) -target_include_directories(xkb PRIVATE ${XCB_XKB_INCLUDE_DIRS}) -target_link_libraries(xkb module-sdk ${XCB_XKB_LIBRARIES}) +target_link_libraries(xkb module-sdk PkgConfig::xkb) add_library(xwindow ${lib_type} xwindow.c) target_link_libraries(xwindow module-sdk) From 727d7b343f5754fc2ed27c2125fa83789eb1d91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 20:05:44 +0100 Subject: [PATCH 32/59] cmake: initial support for building wayland-only, or x11-only --- CMakeLists.txt | 148 ++++++++++++++++++++++--------------- bar/bar.c | 21 +++++- decorations/CMakeLists.txt | 5 +- modules/CMakeLists.txt | 48 +++++++----- modules/i3.c | 21 +++++- particles/CMakeLists.txt | 5 +- plugin.c | 4 + 7 files changed, 162 insertions(+), 90 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a5a32d..edadd6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,68 +23,87 @@ set(CMAKE_C_FLAGS "-Wall -Werror ${CMAKE_C_FLAGS}") find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) -pkg_check_modules(xcb REQUIRED IMPORTED_TARGET - xcb xcb-aux xcb-cursor xcb-event xcb-ewmh xcb-randr xcb-render) -pkg_check_modules(xcb-errors IMPORTED_TARGET xcb-errors) -pkg_check_modules(wayland REQUIRED IMPORTED_TARGET - wayland-client wayland-cursor wlroots) pkg_check_modules(fontconfig REQUIRED IMPORTED_TARGET fontconfig) -pkg_check_modules(cairo REQUIRED IMPORTED_TARGET cairo cairo-xcb cairo-ft) +pkg_check_modules(cairo REQUIRED IMPORTED_TARGET cairo cairo-ft) pkg_check_modules(yaml REQUIRED IMPORTED_TARGET yaml-0.1) -add_library(xcb-stuff STATIC EXCLUDE_FROM_ALL xcb.c xcb.h) -if (XCB_ERRORS_FOUND) - target_compile_definitions(xcb-stuff PRIVATE HAVE_XCB_ERRORS) +set(ENABLE_X11 1 CACHE BOOL "Enables support for the XCB (X11) backend") +set_property(DIRECTORY . APPEND PROPERTY + COMPILE_DEFINITIONS $<$:ENABLE_X11>) + +if (ENABLE_X11) + pkg_check_modules(xcb REQUIRED IMPORTED_TARGET + xcb xcb-aux xcb-cursor xcb-event xcb-ewmh xcb-randr xcb-render cairo-xcb) + pkg_check_modules(xcb-errors IMPORTED_TARGET xcb-errors) endif () -add_library(bar-xcb STATIC EXCLUDE_FROM_ALL bar/xcb.c bar/xcb.h) -target_link_libraries(bar-xcb - xcb-stuff PkgConfig::xcb PkgConfig::xcb-errors PkgConfig::cairo) +set(ENABLE_WAYLAND 1 CACHE BOOL "Enables support for the wayland backend") +set_property(DIRECTORY . APPEND PROPERTY + COMPILE_DEFINITIONS $<$:ENABLE_WAYLAND>) -add_custom_command( - OUTPUT wlr-layer-shell-unstable-v1.c - COMMAND wayland-scanner private-code < ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1.c - VERBATIM - MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml - ) -add_custom_command( - OUTPUT wlr-layer-shell-unstable-v1-client.h - COMMAND wayland-scanner client-header < /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1-client.h - VERBATIM - MAIN_DEPENDENCY /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml - ) -add_custom_command( - OUTPUT xdg-shell.c - COMMAND wayland-scanner private-code < /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml > xdg-shell.c - VERBATIM - MAIN_DEPENDENCY /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml - ) -add_custom_command( - OUTPUT xdg-output-unstable-v1-client.h - COMMAND wayland-scanner client-header < /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1-client.h - VERBATIM - MAIN_DEPENDENCY /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml - ) -add_custom_command( - OUTPUT xdg-output-unstable-v1.c - COMMAND wayland-scanner private-code < /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1.c - VERBATIM - MAIN_DEPENDENCY /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml - ) +if (ENABLE_WAYLAND) + pkg_check_modules(wayland REQUIRED IMPORTED_TARGET + wayland-client wayland-cursor wlroots) +endif () -add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL - wlr-layer-shell-unstable-v1-client.h - wlr-layer-shell-unstable-v1.c - xdg-shell.c - xdg-output-unstable-v1-client.h - xdg-output-unstable-v1.c - ) -target_include_directories(wayland-protocols PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +if (ENABLE_X11) + add_library(xcb-stuff STATIC EXCLUDE_FROM_ALL xcb.c xcb.h) + if (XCB_ERRORS_FOUND) + target_compile_definitions(xcb-stuff PRIVATE HAVE_XCB_ERRORS) + endif () + target_link_libraries(xcb-stuff PkgConfig::xcb PkgConfig::xcb-errors) -add_library(bar-wayland STATIC EXCLUDE_FROM_ALL bar/wayland.c bar/wayland.h) -target_compile_definitions(bar-wayland PRIVATE _GNU_SOURCE) -target_link_libraries( - bar-wayland wayland-protocols PkgConfig::wayland PkgConfig::cairo) + add_library(bar-xcb STATIC EXCLUDE_FROM_ALL bar/xcb.c bar/xcb.h) + target_link_libraries(bar-xcb + xcb-stuff PkgConfig::cairo) +endif () + +if (ENABLE_WAYLAND) + add_custom_command( + OUTPUT wlr-layer-shell-unstable-v1.c + COMMAND wayland-scanner private-code < ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1.c + VERBATIM + MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml + ) + add_custom_command( + OUTPUT wlr-layer-shell-unstable-v1-client.h + COMMAND wayland-scanner client-header < /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1-client.h + VERBATIM + MAIN_DEPENDENCY /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml + ) + add_custom_command( + OUTPUT xdg-shell.c + COMMAND wayland-scanner private-code < /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml > xdg-shell.c + VERBATIM + MAIN_DEPENDENCY /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml + ) + add_custom_command( + OUTPUT xdg-output-unstable-v1-client.h + COMMAND wayland-scanner client-header < /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1-client.h + VERBATIM + MAIN_DEPENDENCY /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml + ) + add_custom_command( + OUTPUT xdg-output-unstable-v1.c + COMMAND wayland-scanner private-code < /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1.c + VERBATIM + MAIN_DEPENDENCY /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml + ) + + add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL + wlr-layer-shell-unstable-v1-client.h + wlr-layer-shell-unstable-v1.c + xdg-shell.c + xdg-output-unstable-v1-client.h + xdg-output-unstable-v1.c + ) + target_include_directories(wayland-protocols PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + + add_library(bar-wayland STATIC EXCLUDE_FROM_ALL bar/wayland.c bar/wayland.h) + target_compile_definitions(bar-wayland PRIVATE _GNU_SOURCE) + target_link_libraries( + bar-wayland wayland-protocols PkgConfig::wayland PkgConfig::cairo) +endif () add_executable(f00bar config.c config.h @@ -104,7 +123,8 @@ add_executable(f00bar ) target_link_libraries(f00bar - bar-xcb bar-wayland + $<$:bar-xcb> + $<$:bar-wayland> PkgConfig::cairo PkgConfig::fontconfig PkgConfig::yaml ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) @@ -117,13 +137,23 @@ set_property(TARGET f00bar PROPERTY install(TARGETS f00bar DESTINATION bin) +set(enabled_modules "") +set(enabled_particles "") +set(enabled_decorations "") + add_subdirectory(modules) add_subdirectory(particles) add_subdirectory(decorations) + + if (NOT CORE_PLUGINS_AS_SHARED_LIBRARIES) - target_link_libraries(f00bar background stack underline) - target_link_libraries(f00bar dynlist empty list map progress-bar ramp string) - target_link_libraries(f00bar alsa backlight battery clock i3 label mpd network - removables xkb xwindow) + target_link_libraries(f00bar ${enabled_decorations}) + target_link_libraries(f00bar ${enabled_particles}) + target_link_libraries(f00bar ${enabled_modules}) + + foreach (plug ${enabled_decorations} ${enabled_particles} ${enabled_modules}) + string(REPLACE "-" "_" fixed "${plug}") + target_compile_definitions(f00bar PRIVATE "HAVE_PLUGIN_${fixed}") + endforeach () endif () diff --git a/bar/bar.c b/bar/bar.c index dc0b5bd..aef9ac1 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -14,8 +14,13 @@ #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "xcb.h" -#include "wayland.h" +#if defined(ENABLE_X11) + #include "xcb.h" +#endif + +#if defined(ENABLE_WAYLAND) + #include "wayland.h" +#endif /* * Calculate total width of left/center/rigth groups. @@ -382,12 +387,22 @@ bar_new(const struct bar_config *config) priv->right.count = config->right.count; priv->cursor_name = NULL; -#if 0 +#if defined(ENABLE_X11) && !defined(ENABLE_WAYLAND) priv->backend.data = bar_backend_xcb_new(); priv->backend.iface = &xcb_backend_iface; #else +#if !defined(ENABLE_X11) && defined(ENABLE_WAYLAND) priv->backend.data = bar_backend_wayland_new(); priv->backend.iface = &wayland_backend_iface; +#else + if (getenv("WAYLAND_DISPLAY") != NULL) { + priv->backend.data = bar_backend_wayland_new(); + priv->backend.iface = &wayland_backend_iface; + } else { + priv->backend.data = bar_backend_xcb_new(); + priv->backend.iface = &xcb_backend_iface; + } +#endif #endif for (size_t i = 0; i < priv->left.count; i++) { diff --git a/decorations/CMakeLists.txt b/decorations/CMakeLists.txt index 3702be6..43e1713 100644 --- a/decorations/CMakeLists.txt +++ b/decorations/CMakeLists.txt @@ -1,8 +1,7 @@ cmake_minimum_required(VERSION 3.7) add_library(decoration-sdk INTERFACE) -target_compile_options(decoration-sdk INTERFACE ${CAIRO_CFLAGS_OTHER}) -target_include_directories(decoration-sdk INTERFACE ${CAIRO_INCLUDE_DIRS}) +target_link_libraries(decoration-sdk INTERFACE PkgConfig::cairo) set(CMAKE_SHARED_MODULE_PREFIX decoration_) @@ -22,3 +21,5 @@ endforeach () if (CORE_PLUGINS_AS_SHARED_LIBRARIES) install(TARGETS ${decorations} DESTINATION lib/f00bar) endif () + +set(enabled_decorations ${decorations} PARENT_SCOPE) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 0a92ac9..d449824 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -12,19 +12,25 @@ endif () set(CMAKE_SHARED_${lib_type}_PREFIX module_) +set(enabled "") + pkg_check_modules(alsa REQUIRED IMPORTED_TARGET alsa) add_library(alsa ${lib_type} alsa.c) target_link_libraries(alsa module-sdk PkgConfig::alsa) +list(APPEND enabled alsa) pkg_check_modules(udev REQUIRED IMPORTED_TARGET libudev) add_library(backlight ${lib_type} backlight.c) target_link_libraries(backlight module-sdk PkgConfig::udev) +list(APPEND enabled backlight) add_library(battery ${lib_type} battery.c) target_link_libraries(battery module-sdk PkgConfig::udev) +list(APPEND enabled battery) add_library(clock ${lib_type} clock.c) target_link_libraries(clock module-sdk) +list(APPEND enabled clock) pkg_check_modules(json REQUIRED IMPORTED_TARGET json-c) find_file(I3_IPC_H i3/ipc.h) @@ -33,41 +39,43 @@ if (NOT I3_IPC_H) endif () add_library(i3 ${lib_type} i3.c) target_link_libraries(i3 module-sdk dynlist PkgConfig::json) +if (ENABLE_X11) + target_link_libraries(i3 xcb-stuff) +endif () +list(APPEND enabled i3) add_library(label ${lib_type} label.c) target_link_libraries(label module-sdk) +list(APPEND enabled label) pkg_check_modules(mpd REQUIRED IMPORTED_TARGET libmpdclient) add_library(mpd ${lib_type} mpd.c) target_link_libraries(mpd module-sdk PkgConfig::mpd) +list(APPEND enabled mpd) add_library(network ${lib_type} network.c) target_link_libraries(network module-sdk) +list(APPEND enabled network) add_library(removables ${lib_type} removables.c) target_link_libraries(removables module-sdk dynlist PkgConfig::udev) +list(APPEND enabled removables) -pkg_check_modules(xkb REQUIRED IMPORTED_TARGET xcb-xkb) -add_library(xkb ${lib_type} xkb.c) -target_link_libraries(xkb module-sdk PkgConfig::xkb) +if (ENABLE_X11) + pkg_check_modules(xkb REQUIRED IMPORTED_TARGET xcb-xkb) + add_library(xkb ${lib_type} xkb.c) + target_link_libraries(xkb module-sdk PkgConfig::xcb PkgConfig::xkb) + list(APPEND enabled xkb) +endif () -add_library(xwindow ${lib_type} xwindow.c) -target_link_libraries(xwindow module-sdk) +if (ENABLE_X11) + add_library(xwindow ${lib_type} xwindow.c) + target_link_libraries(xwindow module-sdk xcb-stuff) + list(APPEND enabled xwindow) +endif () if (CORE_PLUGINS_AS_SHARED_LIBRARIES) - install( - TARGETS - alsa - backlight - battery - clock - i3 - label - mpd - network - removables - xkb - xwindow - - DESTINATION lib/f00bar) + install(TARGETS ${enabled} DESTINATION lib/f00bar) endif () + +set(enabled_modules ${enabled} PARENT_SCOPE) diff --git a/modules/i3.c b/modules/i3.c index 133ecae..cce5ca3 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -10,8 +10,11 @@ #include #include -#include -#include +#if defined(ENABLE_X11) + #include + #include +#endif + #include #include @@ -26,7 +29,10 @@ #include "../config-verify.h" #include "../particles/dynlist.h" #include "../plugin.h" -#include "../xcb.h" + +#if defined(ENABLE_X11) + #include "../xcb.h" +#endif struct ws_content { char *name; @@ -371,6 +377,7 @@ handle_workspace_event(struct private *m, const struct json_object *json) return true; } +#if defined(ENABLE_X11) static bool get_socket_address_x11(struct sockaddr_un *addr) { @@ -419,6 +426,7 @@ get_socket_address_x11(struct sockaddr_un *addr) xcb_disconnect(conn); return true; } +#endif static bool get_socket_address(struct sockaddr_un *addr) @@ -426,8 +434,13 @@ get_socket_address(struct sockaddr_un *addr) *addr = (struct sockaddr_un){.sun_family = AF_UNIX}; const char *sway_sock = getenv("SWAYSOCK"); - if (sway_sock == NULL) + if (sway_sock == NULL) { +#if defined(ENABLE_X11) return get_socket_address_x11(addr); +#else + return false; +#endif + } strncpy(addr->sun_path, sway_sock, sizeof(addr->sun_path)); return true; diff --git a/particles/CMakeLists.txt b/particles/CMakeLists.txt index 0ca7674..f80e3df 100644 --- a/particles/CMakeLists.txt +++ b/particles/CMakeLists.txt @@ -1,8 +1,7 @@ cmake_minimum_required(VERSION 3.7) add_library(particle-sdk INTERFACE) -target_compile_options(particle-sdk INTERFACE ${CAIRO_CFLAGS_OTHER}) -target_include_directories(particle-sdk INTERFACE ${CAIRO_INCLUDE_DIRS}) +target_link_libraries(particle-sdk INTERFACE PkgConfig::cairo) if (CORE_PLUGINS_AS_SHARED_LIBRARIES) set(lib_type MODULE) @@ -30,3 +29,5 @@ target_link_libraries(string ${CAIRO_LIBRARIES}) if (CORE_PLUGINS_AS_SHARED_LIBRARIES) install(TARGETS ${particles} dynlist DESTINATION lib/f00bar) endif () + +set(enabled_particles "dynlist;${particles}" PARENT_SCOPE) diff --git a/plugin.c b/plugin.c index 5731f40..8935317 100644 --- a/plugin.c +++ b/plugin.c @@ -112,8 +112,12 @@ init(void) REGISTER_CORE_MODULE(mpd, mpd); REGISTER_CORE_MODULE(network, network); REGISTER_CORE_MODULE(removables, removables); +#if defined(HAVE_MODULE_xkb) REGISTER_CORE_MODULE(xkb, xkb); +#endif +#if defined(HAVE_MODULE_xwindow) REGISTER_CORE_MODULE(xwindow, xwindow); +#endif REGISTER_CORE_PARTICLE(empty, empty); REGISTER_CORE_PARTICLE(list, list); From 63618b8fab473dbc3a06d445b7e87d1449f94749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 20:07:03 +0100 Subject: [PATCH 33/59] ci: no working wayland dev environment on CI The docker image lacks wlroots. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f2d1422..9dbbc18 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,7 +15,7 @@ debug: script: - mkdir -p bld/debug - cd bld/debug - - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../../ + - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DENABLE_WAYLAND=no ../../ - ninja -k0 release: @@ -23,5 +23,5 @@ release: script: - mkdir -p bld/release - cd bld/release - - cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel ../../ + - cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel -DENABLE_WAYLAND=no ../../ - ninja -k0 From 6562cb61df02e2b9f57f803752dfaade44d2e1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 3 Feb 2019 20:09:02 +0100 Subject: [PATCH 34/59] cmake: don't try to link againt xcb-errors when we didn't find it --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index edadd6b..5e80df8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,10 +48,11 @@ endif () if (ENABLE_X11) add_library(xcb-stuff STATIC EXCLUDE_FROM_ALL xcb.c xcb.h) + target_link_libraries(xcb-stuff PkgConfig::xcb) if (XCB_ERRORS_FOUND) target_compile_definitions(xcb-stuff PRIVATE HAVE_XCB_ERRORS) + target_link_libraries(xcb-stuff PkgConfig::xcb-errors) endif () - target_link_libraries(xcb-stuff PkgConfig::xcb PkgConfig::xcb-errors) add_library(bar-xcb STATIC EXCLUDE_FROM_ALL bar/xcb.c bar/xcb.h) target_link_libraries(bar-xcb From 70499654a3d05e044abc9c7436b6e9fe1050c151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 6 Feb 2019 15:39:11 +0100 Subject: [PATCH 35/59] module/i3: delay bar refresh until all received events have been processed This fixes an issue where switching between empty workspaces (or one empty, one non-empty) momentarily flashed two workspaces. I.e. we immediately rendered the new workspace, and then re-rendered when the first workspace was destroyed. --- modules/i3.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/i3.c b/modules/i3.c index cce5ca3..a9963a4 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -504,6 +504,8 @@ run(struct module *mod) buf_idx += bytes; bool err = false; + bool need_bar_refresh = false; + while (!err && buf_idx >= sizeof(i3_ipc_header_t)) { const i3_ipc_header_t *hdr = (const i3_ipc_header_t *)buf; if (strncmp(hdr->magic, I3_IPC_MAGIC, sizeof(hdr->magic)) != 0) { @@ -551,12 +553,12 @@ run(struct module *mod) case I3_IPC_REPLY_TYPE_WORKSPACES: handle_get_workspaces_reply(m, json); - mod->bar->refresh(mod->bar); + need_bar_refresh = true; break; case I3_IPC_EVENT_WORKSPACE: handle_workspace_event(m, json); - mod->bar->refresh(mod->bar); + need_bar_refresh = true; break; case I3_IPC_EVENT_OUTPUT: @@ -583,6 +585,9 @@ run(struct module *mod) if (err) break; + + if (need_bar_refresh) + mod->bar->refresh(mod->bar); } free(buf); From da062f26d55c8a447d314a62ebe9f8a60540ce1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 6 Feb 2019 15:41:21 +0100 Subject: [PATCH 36/59] cmake: remove hardcoded, local, path --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e80df8..fd9cec2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,9 +68,9 @@ if (ENABLE_WAYLAND) ) add_custom_command( OUTPUT wlr-layer-shell-unstable-v1-client.h - COMMAND wayland-scanner client-header < /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1-client.h + COMMAND wayland-scanner client-header < ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1-client.h VERBATIM - MAIN_DEPENDENCY /home/daniel/AUR/wlroots-git/src/wlroots-git/protocol/wlr-layer-shell-unstable-v1.xml + MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml ) add_custom_command( OUTPUT xdg-shell.c From 93831428589d417c51740ba4c4e7e76c7c526603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 6 Feb 2019 16:01:18 +0100 Subject: [PATCH 37/59] cmake: manually run pkg-config --variable=pkgdatadir wayland-protocols To get the path to the wayland protocol definitions, manually run pkg-config with --variable=pkgdatadir. Then use this instead of a hardcoded path into /usr/share/wayland-protocols when defining the custom commands to generate .c/.h files from the protocol XML definitions. --- CMakeLists.txt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd9cec2..68cce9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,23 +72,28 @@ if (ENABLE_WAYLAND) VERBATIM MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml ) + + execute_process( + COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols + OUTPUT_VARIABLE WAYLAND_PROTOCOLS + OUTPUT_STRIP_TRAILING_WHITESPACE) add_custom_command( OUTPUT xdg-shell.c - COMMAND wayland-scanner private-code < /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml > xdg-shell.c + COMMAND wayland-scanner private-code < ${WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml > xdg-shell.c VERBATIM - MAIN_DEPENDENCY /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml + MAIN_DEPENDENCY ${WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml ) add_custom_command( OUTPUT xdg-output-unstable-v1-client.h - COMMAND wayland-scanner client-header < /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1-client.h + COMMAND wayland-scanner client-header < ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1-client.h VERBATIM - MAIN_DEPENDENCY /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml + MAIN_DEPENDENCY ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml ) add_custom_command( OUTPUT xdg-output-unstable-v1.c - COMMAND wayland-scanner private-code < /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1.c + COMMAND wayland-scanner private-code < ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1.c VERBATIM - MAIN_DEPENDENCY /usr/share/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml + MAIN_DEPENDENCY ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml ) add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL From ed7b6e20d31746ccf9463b7a84c507c675fa9845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 6 Feb 2019 16:13:24 +0100 Subject: [PATCH 38/59] cmake: add function that generates custom commands for wayland protocols --- CMakeLists.txt | 69 ++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 68cce9e..0b4ec8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,49 +60,46 @@ if (ENABLE_X11) endif () if (ENABLE_WAYLAND) - add_custom_command( - OUTPUT wlr-layer-shell-unstable-v1.c - COMMAND wayland-scanner private-code < ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1.c - VERBATIM - MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml - ) - add_custom_command( - OUTPUT wlr-layer-shell-unstable-v1-client.h - COMMAND wayland-scanner client-header < ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml > wlr-layer-shell-unstable-v1-client.h - VERBATIM - MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml - ) + function (wayland_protocol _deps) + set(deps "") + foreach (xml_file ${ARGN}) + get_filename_component(base ${xml_file} NAME_WE) + set(out_c ${base}.c) + set(out_h ${base}.h) + + add_custom_command( + OUTPUT ${out_h} + COMMAND wayland-scanner client-header < ${xml_file} > ${out_h} + VERBATIM + MAIN_DEPENDENCY ${xml_file} + ) + add_custom_command( + OUTPUT ${out_c} + COMMAND wayland-scanner private-code < ${xml_file} > ${out_c} + VERBATIM + MAIN_DEPENDENCY ${xml_file} + ) + + list(APPEND deps ${out_h}) + list(APPEND deps ${out_c}) + endforeach () + + set(${_deps} ${deps} PARENT_SCOPE) + endfunction () execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols OUTPUT_VARIABLE WAYLAND_PROTOCOLS OUTPUT_STRIP_TRAILING_WHITESPACE) - add_custom_command( - OUTPUT xdg-shell.c - COMMAND wayland-scanner private-code < ${WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml > xdg-shell.c - VERBATIM - MAIN_DEPENDENCY ${WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml - ) - add_custom_command( - OUTPUT xdg-output-unstable-v1-client.h - COMMAND wayland-scanner client-header < ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1-client.h - VERBATIM - MAIN_DEPENDENCY ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml - ) - add_custom_command( - OUTPUT xdg-output-unstable-v1.c - COMMAND wayland-scanner private-code < ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml > xdg-output-unstable-v1.c - VERBATIM - MAIN_DEPENDENCY ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml + + wayland_protocol( + wayland_protos + ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml + ${WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml + ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml ) - add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL - wlr-layer-shell-unstable-v1-client.h - wlr-layer-shell-unstable-v1.c - xdg-shell.c - xdg-output-unstable-v1-client.h - xdg-output-unstable-v1.c - ) + add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL ${wayland_protos}) target_include_directories(wayland-protocols PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) add_library(bar-wayland STATIC EXCLUDE_FROM_ALL bar/wayland.c bar/wayland.h) From dbce871d273c730ee20dd903cf4229a507286fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 6 Feb 2019 16:30:46 +0100 Subject: [PATCH 39/59] module/i3: dynamically grow receive buffer when needed --- modules/i3.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/modules/i3.c b/modules/i3.c index a9963a4..433fcf7 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -472,8 +472,10 @@ run(struct module *mod) send_pkg(sock, I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); send_pkg(sock, I3_IPC_MESSAGE_TYPE_SUBSCRIBE, "[\"workspace\"]"); - /* Some replies are *big*. TODO: grow dynamically */ - static const size_t reply_buf_size = 1 * 1024 * 1024; + /* Initial reply typically requires a couple of KB. But we often + * need more later. For example, switching workspaces can result + * in quite big notification messages. */ + size_t reply_buf_size = 4096; char *buf = malloc(reply_buf_size); size_t buf_idx = 0; @@ -493,6 +495,23 @@ run(struct module *mod) break; assert(fds[1].revents & POLLIN); + + /* Grow receive buffer, if necessary */ + if (buf_idx == reply_buf_size) { + LOG_DBG("growing reply buffer: %zu -> %zu", + reply_buf_size, reply_buf_size * 2); + + char *new_buf = realloc(buf, reply_buf_size * 2); + if (new_buf == NULL) { + LOG_ERR("failed to grow reply buffer from %zu to %zu bytes", + reply_buf_size, reply_buf_size * 2); + break; + } + + buf = new_buf; + reply_buf_size *= 2; + } + assert(reply_buf_size > buf_idx); ssize_t bytes = read(sock, &buf[buf_idx], reply_buf_size - buf_idx); From 4a064ebfffa6ad2f290ce3d9cc30742489be1781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 6 Feb 2019 18:04:32 +0100 Subject: [PATCH 40/59] bar/wayland: fix includes --- bar/wayland.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bar/wayland.c b/bar/wayland.c index a56f186..58a49c8 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -14,8 +14,8 @@ #include #include -#include -#include +#include +#include #define LOG_MODULE "bar:wayland" #include "../log.h" From 0e3866186f203f99c502f300aebdd4dfe1ac30f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 6 Feb 2019 18:09:48 +0100 Subject: [PATCH 41/59] plugin: for now, the defines *all* use the word PLUGIN --- plugin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin.c b/plugin.c index 8935317..3227b06 100644 --- a/plugin.c +++ b/plugin.c @@ -112,10 +112,10 @@ init(void) REGISTER_CORE_MODULE(mpd, mpd); REGISTER_CORE_MODULE(network, network); REGISTER_CORE_MODULE(removables, removables); -#if defined(HAVE_MODULE_xkb) +#if defined(HAVE_PLUGIN_xkb) REGISTER_CORE_MODULE(xkb, xkb); #endif -#if defined(HAVE_MODULE_xwindow) +#if defined(HAVE_PLUGIN_xwindow) REGISTER_CORE_MODULE(xwindow, xwindow); #endif From a831490462e88f837c6e70cfab8f651868a8571c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 6 Feb 2019 18:10:06 +0100 Subject: [PATCH 42/59] modules: fix strncpy calls to ensure strings are NULL-terminated --- modules/i3.c | 2 +- modules/mpd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/i3.c b/modules/i3.c index 433fcf7..81e2ec8 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -442,7 +442,7 @@ get_socket_address(struct sockaddr_un *addr) #endif } - strncpy(addr->sun_path, sway_sock, sizeof(addr->sun_path)); + strncpy(addr->sun_path, sway_sock, sizeof(addr->sun_path) - 1); return true; } diff --git a/modules/mpd.c b/modules/mpd.c index 6606df3..ac74854 100644 --- a/modules/mpd.c +++ b/modules/mpd.c @@ -216,7 +216,7 @@ wait_for_socket_create(const struct module *mod) int s = socket(AF_UNIX, SOCK_STREAM, 0); struct sockaddr_un addr = {.sun_family = AF_UNIX}; - strncpy(addr.sun_path, m->host, sizeof(addr.sun_path)); + strncpy(addr.sun_path, m->host, sizeof(addr.sun_path) - 1); int r = connect(s, (const struct sockaddr *)&addr, sizeof(addr)); From 0fc5778107bab8de47b0047b1ca5524be229207f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 11:22:02 +0100 Subject: [PATCH 43/59] bar/wayland: wl_* APIs typically don't handle destroy(NULL) --- bar/wayland.c | 58 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/bar/wayland.c b/bar/wayland.c index 58a49c8..7a62052 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -118,7 +118,8 @@ static const struct wl_shm_listener shm_listener = { static void update_cursor_surface(struct wayland_backend *backend) { - assert(backend->pointer.cursor != NULL); + if (backend->pointer.cursor == NULL) + return; struct wl_cursor_image *image = backend->pointer.cursor->images[0]; @@ -582,37 +583,56 @@ cleanup(struct bar *_bar) struct wayland_backend *backend = bar->backend.data; tll_foreach(backend->buffers, it) { - wl_buffer_destroy(it->item.wl_buf); - cairo_destroy(it->item.cairo); - cairo_surface_destroy(it->item.cairo_surface); - munmap(it->item.mmapped, it->item.size); + if (it->item.wl_buf != NULL) + wl_buffer_destroy(it->item.wl_buf); + if (it->item.cairo != NULL) + cairo_destroy(it->item.cairo); + if (it->item.cairo_surface != NULL) + cairo_surface_destroy(it->item.cairo_surface); + munmap(it->item.mmapped, it->item.size); tll_remove(backend->buffers, it); } tll_foreach(backend->monitors, it) { struct monitor *mon = &it->item; free(mon->name); - zxdg_output_v1_destroy(mon->xdg); - wl_output_destroy(mon->output); + + if (mon->xdg != NULL) + zxdg_output_v1_destroy(mon->xdg); + if (mon->output != NULL) + wl_output_destroy(mon->output); tll_remove(backend->monitors, it); } - zxdg_output_manager_v1_destroy(backend->xdg_output_manager); + + if (backend->xdg_output_manager != NULL) + zxdg_output_manager_v1_destroy(backend->xdg_output_manager); /* TODO: move to bar */ free(bar->cursor_name); - zwlr_layer_surface_v1_destroy(backend->layer_surface); - zwlr_layer_shell_v1_destroy(backend->layer_shell); - wl_cursor_theme_destroy(backend->pointer.theme); - wl_pointer_destroy(backend->pointer.pointer); - wl_surface_destroy(backend->pointer.surface); - wl_surface_destroy(backend->surface); - wl_seat_destroy(backend->seat); - wl_compositor_destroy(backend->compositor); - wl_shm_destroy(backend->shm); - wl_registry_destroy(backend->registry); - wl_display_disconnect(backend->display); + if (backend->layer_surface != NULL) + zwlr_layer_surface_v1_destroy(backend->layer_surface); + if (backend->layer_shell != NULL) + zwlr_layer_shell_v1_destroy(backend->layer_shell); + if (backend->pointer.theme != NULL) + wl_cursor_theme_destroy(backend->pointer.theme); + if (backend->pointer.pointer != NULL) + wl_pointer_destroy(backend->pointer.pointer); + if (backend->pointer.surface != NULL) + wl_surface_destroy(backend->pointer.surface); + if (backend->surface != NULL) + wl_surface_destroy(backend->surface); + if (backend->seat != NULL) + wl_seat_destroy(backend->seat); + if (backend->compositor != NULL) + wl_compositor_destroy(backend->compositor); + if (backend->shm != NULL) + wl_shm_destroy(backend->shm); + if (backend->registry != NULL) + wl_registry_destroy(backend->registry); + if (backend->display != NULL) + wl_display_disconnect(backend->display); /* Destroyed when freeing buffer list */ bar->cairo_surface = NULL; From f71aaf9615736e8c76e4519430c52f722c1afe84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 11:50:52 +0100 Subject: [PATCH 44/59] bar: call backend->cleanup() when backend->setup() fails This makes it easier to implement proper cleanup in the backends, as setup() doesn't have to clean up it's own mess upon failure. --- bar/bar.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bar/bar.c b/bar/bar.c index aef9ac1..145cfd0 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -245,8 +245,10 @@ run(struct bar *_bar) bar->height_with_border = bar->height + 2 * bar->border.width; - if (!bar->backend.iface->setup(_bar)) + if (!bar->backend.iface->setup(_bar)) { + bar->backend.iface->cleanup(_bar); return 1; + } set_cursor(_bar, "left_ptr"); From e48d90ae12960f88a115652a168b509cbd29b94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 11:51:26 +0100 Subject: [PATCH 45/59] bar/xcb: cleanup: don't try to free NULL resources --- bar/xcb.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/bar/xcb.c b/bar/xcb.c index db854dc..3f0d284 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -253,21 +253,29 @@ cleanup(struct bar *_bar) struct private *bar = _bar->private; struct xcb_backend *backend = bar->backend.data; - if (backend->cursor_ctx != NULL) { + if (backend->conn == NULL) + return; + + if (backend->cursor != 0) xcb_free_cursor(backend->conn, backend->cursor); + if (backend->cursor_ctx != NULL) xcb_cursor_context_free(backend->cursor_ctx); - free(bar->cursor_name); - bar->cursor_name = NULL; - } + /* TODO: move to bar.c */ + free(bar->cursor_name); + + if (backend->gc != 0) + xcb_free_gc(backend->conn, backend->gc); + if (backend->pixmap != 0) + xcb_free_pixmap(backend->conn, backend->pixmap); + if (backend->win != 0) + xcb_destroy_window(backend->conn, backend->win); + if (backend->colormap != 0) + xcb_free_colormap(backend->conn, backend->colormap); - xcb_free_gc(backend->conn, backend->gc); - xcb_free_pixmap(backend->conn, backend->pixmap); - xcb_destroy_window(backend->conn, backend->win); - xcb_free_colormap(backend->conn, backend->colormap); xcb_flush(backend->conn); - xcb_disconnect(backend->conn); + backend->conn = NULL; } static void From 76655bc9447d78cb0a10492ec7bac14e68caaf9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 11:51:42 +0100 Subject: [PATCH 46/59] bar/wayland: much improved error handling Most asserts() have now been replaced with error messages. Cleanup() no longer tries to free/destroy NULL resources. --- bar/wayland.c | 185 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 145 insertions(+), 40 deletions(-) diff --git a/bar/wayland.c b/bar/wayland.c index 7a62052..bb33ac7 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -431,50 +431,115 @@ get_buffer(struct wayland_backend *backend) { tll_foreach(backend->buffers, it) { if (!it->item.busy) { - //printf("re-using non-busy buffer\n"); it->item.busy = true; return &it->item; } } - //printf("allocating a new buffer\n"); + /* + * No existing buffer available. Create a new one by: + * + * 1. open a memory backed "file" with memfd_create() + * 2. mmap() the memory file, to be used by the cairo surface + * 3. create a wayland shm buffer for the same memory file + * + * The cairo surface and the wayland buffer are now sharing + * memory. + */ - struct buffer buffer; + int pool_fd = -1; + void *mmapped = NULL; + size_t size = 0; + + struct wl_shm_pool *pool = NULL; + struct wl_buffer *buf = NULL; + + cairo_surface_t *cairo_surface = NULL; + cairo_t *cairo = NULL; /* Backing memory for SHM */ - int pool_fd = memfd_create("wayland-test-buffer-pool", MFD_CLOEXEC); - assert(pool_fd != -1); + pool_fd = memfd_create("wayland-test-buffer-pool", MFD_CLOEXEC); + if (pool_fd == -1) { + LOG_ERRNO("failed to create SHM backing memory file"); + goto err; + } - /* Allocate memory for our single buffer */ + /* Total size */ uint32_t stride = backend->width * 4; - buffer.size = stride * backend->height; - ftruncate(pool_fd, buffer.size); + size = stride * backend->height; + ftruncate(pool_fd, size); - buffer.mmapped = mmap( - NULL, buffer.size, PROT_READ | PROT_WRITE, MAP_SHARED, pool_fd, 0); - assert(buffer.mmapped != MAP_FAILED); + mmapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, pool_fd, 0); + if (mmapped == MAP_FAILED) { + LOG_ERR("failed to mmap SHM backing memory file"); + goto err; + } - struct wl_shm_pool *pool = wl_shm_create_pool(backend->shm, pool_fd, buffer.size); - assert(pool != NULL); + pool = wl_shm_create_pool(backend->shm, pool_fd, size); + if (pool == NULL) { + LOG_ERR("failed to create SHM pool"); + goto err; + } - buffer.wl_buf = wl_shm_pool_create_buffer( + buf = wl_shm_pool_create_buffer( pool, 0, backend->width, backend->height, stride, WL_SHM_FORMAT_ARGB8888); - assert(buffer.wl_buf != NULL); - buffer.busy = true; + if (buf == NULL) { + LOG_ERR("failed to create SHM buffer"); + goto err; + } - wl_shm_pool_destroy(pool); - close(pool_fd); + /* We use the entire pool for our single buffer */ + wl_shm_pool_destroy(pool); pool = NULL; + close(pool_fd); pool_fd = -1; - buffer.cairo_surface = cairo_image_surface_create_for_data( - buffer.mmapped, CAIRO_FORMAT_ARGB32, backend->width, backend->height, stride); - buffer.cairo = cairo_create(buffer.cairo_surface); - assert(cairo_status(buffer.cairo) == CAIRO_STATUS_SUCCESS); + /* Create a cairo surface around the mmapped memory */ + cairo_surface = cairo_image_surface_create_for_data( + mmapped, CAIRO_FORMAT_ARGB32, backend->width, backend->height, stride); + if (cairo_surface_status(cairo_surface) != CAIRO_STATUS_SUCCESS) { + LOG_ERR("failed to create cairo surface: %s", + cairo_status_to_string(cairo_surface_status(cairo_surface))); + goto err; + } - tll_push_back(backend->buffers, buffer); + cairo = cairo_create(cairo_surface); + if (cairo_status(cairo) != CAIRO_STATUS_SUCCESS) { + LOG_ERR("failed to create cairo context: %s", + cairo_status_to_string(cairo_status(cairo))); + goto err; + } + + /* Push to list of available buffers, but marked as 'busy' */ + tll_push_back( + backend->buffers, + ((struct buffer){ + .busy = true, + .size = size, + .mmapped = mmapped, + .wl_buf = buf, + .cairo_surface = cairo_surface, + .cairo = cairo} + ) + ); struct buffer *ret = &tll_back(backend->buffers); - wl_buffer_add_listener(buffer.wl_buf, &buffer_listener, ret); + wl_buffer_add_listener(ret->wl_buf, &buffer_listener, ret); return ret; + +err: + if (cairo != NULL) + cairo_destroy(cairo); + if (cairo_surface != NULL) + cairo_surface_destroy(cairo_surface); + if (buf != NULL) + wl_buffer_destroy(buf); + if (pool != NULL) + wl_shm_pool_destroy(pool); + if (pool_fd != -1) + close(pool_fd); + if (mmapped != NULL) + munmap(mmapped, size); + + return NULL; } static bool @@ -486,17 +551,37 @@ setup(struct bar *_bar) backend->bar = _bar; backend->display = wl_display_connect(NULL); - assert(backend->display != NULL); + if (backend->display == NULL) { + LOG_ERR("failed to connect to wayland; no compistor running?"); + return false; + } backend->registry = wl_display_get_registry(backend->display); - assert(backend->registry != NULL); + if (backend->registry == NULL) { + LOG_ERR("failed to get wayland registry"); + return false; + } wl_registry_add_listener(backend->registry, ®istry_listener, backend); - wl_display_roundtrip(backend->display); - assert(backend->compositor != NULL && - backend->layer_shell != NULL && - backend->shm != NULL); + + if (backend->compositor == NULL) { + LOG_ERR("no compositor"); + return false; + } + if (backend->layer_shell == NULL) { + LOG_ERR("no layer shell interface"); + return false; + } + if (backend->shm == NULL) { + LOG_ERR("no shared memory buffers interface"); + return false; + } + + if (tll_length(backend->monitors) == 0) { + LOG_ERR("no monitors"); + return false; + } tll_foreach(backend->monitors, it) { const struct monitor *mon = &it->item; @@ -512,18 +597,30 @@ setup(struct bar *_bar) } backend->surface = wl_compositor_create_surface(backend->compositor); - assert(backend->surface != NULL); + if (backend->surface == NULL) { + LOG_ERR("failed to create panel surface"); + return false; + } backend->pointer.surface = wl_compositor_create_surface(backend->compositor); - assert(backend->pointer.surface != NULL); + if (backend->pointer.surface == NULL) { + LOG_ERR("failed to create cursor surface"); + return false; + } backend->pointer.theme = wl_cursor_theme_load(NULL, 24, backend->shm); - assert(backend->pointer.theme != NULL); + if (backend->pointer.theme == NULL) { + LOG_ERR("failed to load cursor theme"); + return false; + } backend->layer_surface = zwlr_layer_shell_v1_get_layer_surface( backend->layer_shell, backend->surface, backend->monitor->output, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "f00bar"); - assert(backend->layer_surface != NULL); + if (backend->layer_surface == NULL) { + LOG_ERR("failed to create layer shell surface"); + return false; + } /* Aligned to top, maximum width */ enum zwlr_layer_surface_v1_anchor top_or_bottom = bar->location == BAR_TOP @@ -543,8 +640,7 @@ setup(struct bar *_bar) //zwlr_layer_surface_v1_set_margin( // layer_surface, margin_top, margin_right, margin_bottom, margin_left); - //zwlr_layer_surface_v1_set_keyboard_interactivity( - // layer_surface, keyboard_interactive); + zwlr_layer_surface_v1_set_keyboard_interactivity(backend->layer_surface, 1); zwlr_layer_surface_v1_add_listener( backend->layer_surface, &layer_surface_listener, backend); @@ -553,7 +649,11 @@ setup(struct bar *_bar) wl_surface_commit(backend->surface); wl_display_roundtrip(backend->display); - assert(backend->width != -1 && backend->height == bar->height_with_border); + if (backend->width == -1 || backend->height != bar->height_with_border) { + LOG_ERR("failed to get panel width"); + return false; + } + bar->width = backend->width; bar->x = backend->monitor->x; bar->y = backend->monitor->y; @@ -561,12 +661,17 @@ setup(struct bar *_bar) ? 0 : backend->monitor->height_px - bar->height_with_border; - pipe(backend->pipe_fds); + if (pipe(backend->pipe_fds) == -1) { + LOG_ERRNO("failed to create pipe"); + return false; + } + backend->render_scheduled = false; - wl_surface_commit(backend->surface); - wl_display_roundtrip(backend->display); + //wl_surface_commit(backend->surface); + //wl_display_roundtrip(backend->display); + /* Prepare a buffer + cairo context for bar to draw to */ backend->next_buffer = get_buffer(backend); assert(backend->next_buffer != NULL && backend->next_buffer->busy); From ae5029826b4b9f250e27488cd1593a4fb5f2a2e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:06:16 +0100 Subject: [PATCH 47/59] cmake: break out bar stuff to separate CMakeLists.txt --- CMakeLists.txt | 84 +++++++------------------------------------- bar/CMakeLists.txt | 64 +++++++++++++++++++++++++++++++++ bar/backend.h | 2 +- bar/bar.c | 2 +- bar.h => bar/bar.h | 4 +-- bar/private.h | 2 +- config.c | 2 +- main.c | 2 +- modules/alsa.c | 2 +- modules/backlight.c | 2 +- modules/battery.c | 2 +- modules/clock.c | 2 +- modules/i3.c | 2 +- modules/mpd.c | 2 +- modules/network.c | 2 +- modules/removables.c | 2 +- modules/xkb.c | 2 +- modules/xwindow.c | 2 +- particle.c | 2 +- 19 files changed, 95 insertions(+), 89 deletions(-) create mode 100644 bar/CMakeLists.txt rename bar.h => bar/bar.h (94%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b4ec8b..643785a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,14 @@ project(f00bar C) set(CORE_PLUGINS_AS_SHARED_LIBRARIES 0 CACHE BOOL "Compiles modules, particles and decorations as shared libraries, which are loaded on-demand") +set(ENABLE_X11 1 CACHE BOOL "Enables support for the XCB (X11) backend") +set_property(DIRECTORY . APPEND PROPERTY + COMPILE_DEFINITIONS $<$:ENABLE_X11>) + +set(ENABLE_WAYLAND 1 CACHE BOOL "Enables support for the wayland backend") +set_property(DIRECTORY . APPEND PROPERTY + COMPILE_DEFINITIONS $<$:ENABLE_WAYLAND>) + set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_C_STANDARD 11) @@ -27,26 +35,11 @@ pkg_check_modules(fontconfig REQUIRED IMPORTED_TARGET fontconfig) pkg_check_modules(cairo REQUIRED IMPORTED_TARGET cairo cairo-ft) pkg_check_modules(yaml REQUIRED IMPORTED_TARGET yaml-0.1) -set(ENABLE_X11 1 CACHE BOOL "Enables support for the XCB (X11) backend") -set_property(DIRECTORY . APPEND PROPERTY - COMPILE_DEFINITIONS $<$:ENABLE_X11>) - if (ENABLE_X11) pkg_check_modules(xcb REQUIRED IMPORTED_TARGET xcb xcb-aux xcb-cursor xcb-event xcb-ewmh xcb-randr xcb-render cairo-xcb) pkg_check_modules(xcb-errors IMPORTED_TARGET xcb-errors) -endif () -set(ENABLE_WAYLAND 1 CACHE BOOL "Enables support for the wayland backend") -set_property(DIRECTORY . APPEND PROPERTY - COMPILE_DEFINITIONS $<$:ENABLE_WAYLAND>) - -if (ENABLE_WAYLAND) - pkg_check_modules(wayland REQUIRED IMPORTED_TARGET - wayland-client wayland-cursor wlroots) -endif () - -if (ENABLE_X11) add_library(xcb-stuff STATIC EXCLUDE_FROM_ALL xcb.c xcb.h) target_link_libraries(xcb-stuff PkgConfig::xcb) if (XCB_ERRORS_FOUND) @@ -54,60 +47,15 @@ if (ENABLE_X11) target_link_libraries(xcb-stuff PkgConfig::xcb-errors) endif () - add_library(bar-xcb STATIC EXCLUDE_FROM_ALL bar/xcb.c bar/xcb.h) - target_link_libraries(bar-xcb - xcb-stuff PkgConfig::cairo) endif () if (ENABLE_WAYLAND) - function (wayland_protocol _deps) - set(deps "") - foreach (xml_file ${ARGN}) - get_filename_component(base ${xml_file} NAME_WE) - set(out_c ${base}.c) - set(out_h ${base}.h) - - add_custom_command( - OUTPUT ${out_h} - COMMAND wayland-scanner client-header < ${xml_file} > ${out_h} - VERBATIM - MAIN_DEPENDENCY ${xml_file} - ) - add_custom_command( - OUTPUT ${out_c} - COMMAND wayland-scanner private-code < ${xml_file} > ${out_c} - VERBATIM - MAIN_DEPENDENCY ${xml_file} - ) - - list(APPEND deps ${out_h}) - list(APPEND deps ${out_c}) - endforeach () - - set(${_deps} ${deps} PARENT_SCOPE) - endfunction () - - execute_process( - COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols - OUTPUT_VARIABLE WAYLAND_PROTOCOLS - OUTPUT_STRIP_TRAILING_WHITESPACE) - - wayland_protocol( - wayland_protos - ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml - ${WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml - ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml - ) - - add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL ${wayland_protos}) - target_include_directories(wayland-protocols PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) - - add_library(bar-wayland STATIC EXCLUDE_FROM_ALL bar/wayland.c bar/wayland.h) - target_compile_definitions(bar-wayland PRIVATE _GNU_SOURCE) - target_link_libraries( - bar-wayland wayland-protocols PkgConfig::wayland PkgConfig::cairo) + pkg_check_modules(wayland REQUIRED IMPORTED_TARGET + wayland-client wayland-cursor wlroots) endif () +add_subdirectory(bar) + add_executable(f00bar config.c config.h config-verify.c config-verify.h @@ -120,14 +68,10 @@ add_executable(f00bar plugin.c plugin.h tag.c tag.h yml.c yml.h - - bar.h - bar/bar.c bar/private.h bar/backend.h ) target_link_libraries(f00bar - $<$:bar-xcb> - $<$:bar-wayland> + bar PkgConfig::cairo PkgConfig::fontconfig PkgConfig::yaml ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) @@ -148,8 +92,6 @@ add_subdirectory(modules) add_subdirectory(particles) add_subdirectory(decorations) - - if (NOT CORE_PLUGINS_AS_SHARED_LIBRARIES) target_link_libraries(f00bar ${enabled_decorations}) target_link_libraries(f00bar ${enabled_particles}) diff --git a/bar/CMakeLists.txt b/bar/CMakeLists.txt new file mode 100644 index 0000000..6b5f3ae --- /dev/null +++ b/bar/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 3.7) + +# X11/XCB bar backend +if (ENABLE_X11) + add_library(bar-xcb STATIC EXCLUDE_FROM_ALL xcb.c xcb.h) + target_link_libraries(bar-xcb xcb-stuff PkgConfig::cairo) +endif () + +# Wayland/wlroots bar backend +if (ENABLE_WAYLAND) + function (wayland_protocol _deps) + set(deps "") + foreach (xml_file ${ARGN}) + get_filename_component(base ${xml_file} NAME_WE) + set(out_c ${base}.c) + set(out_h ${base}.h) + + add_custom_command( + OUTPUT ${out_h} + COMMAND wayland-scanner client-header < ${xml_file} > ${out_h} + VERBATIM + MAIN_DEPENDENCY ${xml_file} + ) + add_custom_command( + OUTPUT ${out_c} + COMMAND wayland-scanner private-code < ${xml_file} > ${out_c} + VERBATIM + MAIN_DEPENDENCY ${xml_file} + ) + + list(APPEND deps ${out_h}) + list(APPEND deps ${out_c}) + endforeach () + + set(${_deps} ${deps} PARENT_SCOPE) + endfunction () + + execute_process( + COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols + OUTPUT_VARIABLE WAYLAND_PROTOCOLS + OUTPUT_STRIP_TRAILING_WHITESPACE) + + wayland_protocol( + wayland_protos + ${PROJECT_SOURCE_DIR}/external/wlroots/protocol/wlr-layer-shell-unstable-v1.xml + ${WAYLAND_PROTOCOLS}/stable/xdg-shell/xdg-shell.xml + ${WAYLAND_PROTOCOLS}/unstable/xdg-output/xdg-output-unstable-v1.xml + ) + + add_library(wayland-protocols STATIC EXCLUDE_FROM_ALL ${wayland_protos}) + target_include_directories(wayland-protocols PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + + add_library(bar-wayland STATIC EXCLUDE_FROM_ALL wayland.c wayland.h) + target_compile_definitions(bar-wayland PRIVATE _GNU_SOURCE) + target_link_libraries( + bar-wayland wayland-protocols PkgConfig::wayland PkgConfig::cairo) +endif () + +add_library(bar STATIC EXCLUDE_FROM_ALL bar.c bar.h private.h backend.h) + +target_link_libraries(bar + $<$:bar-xcb> + $<$:bar-wayland> +) diff --git a/bar/backend.h b/bar/backend.h index fc33c37..c07e069 100644 --- a/bar/backend.h +++ b/bar/backend.h @@ -2,7 +2,7 @@ #include -#include "../bar.h" +#include "bar.h" struct backend { bool (*setup)(struct bar *bar); diff --git a/bar/bar.c b/bar/bar.c index 145cfd0..065460b 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -1,4 +1,4 @@ -#include "../bar.h" +#include "bar.h" #include "private.h" #include diff --git a/bar.h b/bar/bar.h similarity index 94% rename from bar.h rename to bar/bar.h index 3839b01..b4765a2 100644 --- a/bar.h +++ b/bar/bar.h @@ -1,7 +1,7 @@ #pragma once -#include "color.h" -#include "module.h" +#include "../color.h" +#include "../module.h" struct bar { int abort_fd; diff --git a/bar/private.h b/bar/private.h index 5b202ab..647fb20 100644 --- a/bar/private.h +++ b/bar/private.h @@ -3,7 +3,7 @@ #include #include -#include "../bar.h" +#include "../bar/bar.h" #include "backend.h" struct private { diff --git a/config.c b/config.c index fdfc1b4..73590ea 100644 --- a/config.c +++ b/config.c @@ -7,7 +7,7 @@ #include -#include "bar.h" +#include "bar/bar.h" #include "color.h" #include "config-verify.h" #include "module.h" diff --git a/main.c b/main.c index 78ec0ba..56460e1 100644 --- a/main.c +++ b/main.c @@ -14,7 +14,7 @@ #include #include -#include "bar.h" +#include "bar/bar.h" #include "config.h" #include "yml.h" diff --git a/modules/alsa.c b/modules/alsa.c index 01fdc8b..0cb5e41 100644 --- a/modules/alsa.c +++ b/modules/alsa.c @@ -6,7 +6,7 @@ #define LOG_MODULE "alsa" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config-verify.h" #include "../config.h" #include "../plugin.h" diff --git a/modules/backlight.c b/modules/backlight.c index 69c67ae..69cb8f5 100644 --- a/modules/backlight.c +++ b/modules/backlight.c @@ -12,7 +12,7 @@ #define LOG_MODULE "backlight" #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../plugin.h" diff --git a/modules/battery.c b/modules/battery.c index 777260d..2192bb0 100644 --- a/modules/battery.c +++ b/modules/battery.c @@ -13,7 +13,7 @@ #define LOG_MODULE "battery" #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../plugin.h" diff --git a/modules/clock.c b/modules/clock.c index a374239..27e19fd 100644 --- a/modules/clock.c +++ b/modules/clock.c @@ -5,7 +5,7 @@ #include -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../plugin.h" diff --git a/modules/i3.c b/modules/i3.c index 81e2ec8..b4951a2 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -24,7 +24,7 @@ #define LOG_MODULE "i3" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../particles/dynlist.h" diff --git a/modules/mpd.c b/modules/mpd.c index ac74854..b91c057 100644 --- a/modules/mpd.c +++ b/modules/mpd.c @@ -22,7 +22,7 @@ #define LOG_MODULE "mpd" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../plugin.h" diff --git a/modules/network.c b/modules/network.c index 6da16af..2c6522f 100644 --- a/modules/network.c +++ b/modules/network.c @@ -16,7 +16,7 @@ #define LOG_MODULE "network" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../module.h" diff --git a/modules/removables.c b/modules/removables.c index 5bbaf2c..e05db7d 100644 --- a/modules/removables.c +++ b/modules/removables.c @@ -15,7 +15,7 @@ #define LOG_MODULE "removables" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../particles/dynlist.h" diff --git a/modules/xkb.c b/modules/xkb.c index 04eb74a..ae86c38 100644 --- a/modules/xkb.c +++ b/modules/xkb.c @@ -11,7 +11,7 @@ #define LOG_MODULE "xkb" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../plugin.h" diff --git a/modules/xwindow.c b/modules/xwindow.c index bb07ea4..a784e37 100644 --- a/modules/xwindow.c +++ b/modules/xwindow.c @@ -15,7 +15,7 @@ #define LOG_MODULE "xwindow" #include "../log.h" -#include "../bar.h" +#include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" #include "../plugin.h" diff --git a/particle.c b/particle.c index 0c926bc..dfca044 100644 --- a/particle.c +++ b/particle.c @@ -10,7 +10,7 @@ #define LOG_MODULE "particle" #define LOG_ENABLE_DBG 0 #include "log.h" -#include "bar.h" +#include "bar/bar.h" void particle_default_destroy(struct particle *particle) From ccd594858506b1ec8041afd50c3d894388a46305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:07:53 +0100 Subject: [PATCH 48/59] bar: cmake: not necessary when building STATIC, but we do depend on threads --- bar/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/bar/CMakeLists.txt b/bar/CMakeLists.txt index 6b5f3ae..e767043 100644 --- a/bar/CMakeLists.txt +++ b/bar/CMakeLists.txt @@ -61,4 +61,5 @@ add_library(bar STATIC EXCLUDE_FROM_ALL bar.c bar.h private.h backend.h) target_link_libraries(bar $<$:bar-xcb> $<$:bar-wayland> + ${CMAKE_THREAD_LIBS_INIT} ) From d185f7237dbdeae07437a688458c5f11bff637f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:09:38 +0100 Subject: [PATCH 49/59] bar: cmake: remove trailing whitespace --- bar/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bar/CMakeLists.txt b/bar/CMakeLists.txt index e767043..e9b9a4a 100644 --- a/bar/CMakeLists.txt +++ b/bar/CMakeLists.txt @@ -61,5 +61,5 @@ add_library(bar STATIC EXCLUDE_FROM_ALL bar.c bar.h private.h backend.h) target_link_libraries(bar $<$:bar-xcb> $<$:bar-wayland> - ${CMAKE_THREAD_LIBS_INIT} + ${CMAKE_THREAD_LIBS_INIT} ) From e4f3695f5e0a8687ced4b7955d175a70615f0b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:24:20 +0100 Subject: [PATCH 50/59] cmake: (maybe) build xcb-stuff STATIC library with -fPIC When building plugins as shared libraries, xcb-stuff needs to be built with -fPIC, since a couple of the plugins link against it. --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 643785a..c462f8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,13 @@ if (ENABLE_X11) target_link_libraries(xcb-stuff PkgConfig::xcb-errors) endif () + # Since there are plugins linking against xcb-stuff, we need to + # ensure it's compiled with -fPIC when the plugins are compiled as + # shared libraries. + if (CORE_PLUGINS_AS_SHARED_LIBRARIES) + set_property(TARGET xcb-stuff PROPERTY POSITION_INDEPENDENT_CODE 1) + endif () + endif () if (ENABLE_WAYLAND) From 5884300b5b2afbf7f006ecf04991bb72ffd7e8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:25:01 +0100 Subject: [PATCH 51/59] cmake: use target_link_options() instead of setting CMAKE_EXE_LINKER_FLAGS --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c462f8f..f42919d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,7 @@ target_link_libraries(f00bar ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) # Make global symbols in f00bar visible to dlopen:ed plugins -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic") +target_link_options(f00bar PRIVATE -rdynamic) set_property(TARGET f00bar PROPERTY INSTALL_RPATH \$ORIGIN/../lib/f00bar) set_property(TARGET f00bar PROPERTY From 7ff0f5a2f33fa2c5c59139ae760561fe25b5bb71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:26:05 +0100 Subject: [PATCH 52/59] cmake: need CMake >= 3.13 since we use target_link_options() --- CMakeLists.txt | 2 +- bar/CMakeLists.txt | 2 +- decorations/CMakeLists.txt | 2 +- modules/CMakeLists.txt | 2 +- particles/CMakeLists.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f42919d..b94966d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.13) project(f00bar C) set(CORE_PLUGINS_AS_SHARED_LIBRARIES 0 CACHE BOOL diff --git a/bar/CMakeLists.txt b/bar/CMakeLists.txt index e9b9a4a..f0e6ffa 100644 --- a/bar/CMakeLists.txt +++ b/bar/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.13) # X11/XCB bar backend if (ENABLE_X11) diff --git a/decorations/CMakeLists.txt b/decorations/CMakeLists.txt index 43e1713..414d0d1 100644 --- a/decorations/CMakeLists.txt +++ b/decorations/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.13) add_library(decoration-sdk INTERFACE) target_link_libraries(decoration-sdk INTERFACE PkgConfig::cairo) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index d449824..723537d 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.13) add_library(module-sdk INTERFACE) target_link_libraries( diff --git a/particles/CMakeLists.txt b/particles/CMakeLists.txt index f80e3df..6fd211c 100644 --- a/particles/CMakeLists.txt +++ b/particles/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.13) add_library(particle-sdk INTERFACE) target_link_libraries(particle-sdk INTERFACE PkgConfig::cairo) From 719d4b95d0fae3f27b61009b7bba40c1d6422715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:37:55 +0100 Subject: [PATCH 53/59] ci: wlroots is available in the "testing" repo (edge only) --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9dbbc18..8470b65 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,10 +4,11 @@ stages: - build before_script: + - echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" > /etc/apk/repositories - apk update - apk add musl-dev eudev-libs eudev-dev linux-headers cmake ninja gcc - apk add libxcb-dev xcb-util-wm-dev xcb-util-cursor-dev cairo-dev yaml-dev - - apk add wayland-dev + - apk add wayland-dev wlroots-dev - apk add json-c-dev libmpdclient-dev alsa-lib-dev i3wm debug: From da3185dc79aa803eb7ff047b8a005cde5f5e4d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:40:24 +0100 Subject: [PATCH 54/59] ci: re-enable wayland port --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8470b65..120d7e7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,7 +16,7 @@ debug: script: - mkdir -p bld/debug - cd bld/debug - - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DENABLE_WAYLAND=no ../../ + - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../../ - ninja -k0 release: @@ -24,5 +24,5 @@ release: script: - mkdir -p bld/release - cd bld/release - - cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel -DENABLE_WAYLAND=no ../../ + - cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel ../../ - ninja -k0 From 4ee2afa48f2b9ff79aad481529e62b0c0f4f6f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:41:00 +0100 Subject: [PATCH 55/59] ci: add x11-only, wayland-only and plugins-as-shared-libraries builds --- .gitlab-ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 120d7e7..f96cc74 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,3 +26,27 @@ release: - cd bld/release - cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel ../../ - ninja -k0 + +x11_only: + stage: build + script: + - mkdir -p bld/debug + - cd bld/debug + - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DENABLE_X11=yes -DENABLE_WAYLAND=no ../../ + - ninja -k0 + +wayland_only: + stage: build + script: + - mkdir -p bld/debug + - cd bld/debug + - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DENABLE_X11=no -DENABLE_WAYLAND=yes ../../ + - ninja -k0 + +plugins_as_shared_modules: + stage: build + script: + - mkdir -p bld/debug + - cd bld/debug + - cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCORE_PLUGINS_AS_SHARED_LIBRARIES=yes ../../ + - ninja -k0 From a62c7e675c15b5aeec7290703ccb0d26a0011693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:43:08 +0100 Subject: [PATCH 56/59] ci: *append* to repository list --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f96cc74..8940a9e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ stages: - build before_script: - - echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" > /etc/apk/repositories + - echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories - apk update - apk add musl-dev eudev-libs eudev-dev linux-headers cmake ninja gcc - apk add libxcb-dev xcb-util-wm-dev xcb-util-cursor-dev cairo-dev yaml-dev From 4b0c4c669c9d8dff7ce8d94effbb0994968805e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:45:05 +0100 Subject: [PATCH 57/59] cmake: ensure the wayland-protocols package is available --- bar/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/bar/CMakeLists.txt b/bar/CMakeLists.txt index f0e6ffa..e57442b 100644 --- a/bar/CMakeLists.txt +++ b/bar/CMakeLists.txt @@ -35,6 +35,7 @@ if (ENABLE_WAYLAND) set(${_deps} ${deps} PARENT_SCOPE) endfunction () + pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols) execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols OUTPUT_VARIABLE WAYLAND_PROTOCOLS From f85117431a7b0de27394f106b0ae4423f125d7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:45:37 +0100 Subject: [PATCH 58/59] ci: install wayland-protocols --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8940a9e..5031693 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ before_script: - apk update - apk add musl-dev eudev-libs eudev-dev linux-headers cmake ninja gcc - apk add libxcb-dev xcb-util-wm-dev xcb-util-cursor-dev cairo-dev yaml-dev - - apk add wayland-dev wlroots-dev + - apk add wayland-dev wayland-protocols wlroots-dev - apk add json-c-dev libmpdclient-dev alsa-lib-dev i3wm debug: From 68727006f31aa612895c921fac383e8cf2049e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 7 Feb 2019 12:47:42 +0100 Subject: [PATCH 59/59] ci: checkout git submodules --- .gitlab-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5031693..9087c8c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,9 @@ image: alpine:edge stages: - build +variables: + GIT_SUBMODULE_STRATEGY: normal + before_script: - echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories - apk update