From de01e654cef2c72dce3adb580e20fe2cbc8aeb16 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 25 Apr 2017 15:06:58 -0400 Subject: [PATCH] Flesh out wayland backend somewhat, add example --- CMakeLists.txt | 2 + backend/CMakeLists.txt | 15 ++++- backend/wayland/CMakeLists.txt | 13 ----- backend/wayland/backend.c | 46 +++++++++++++-- backend/wayland/registry.c | 29 ++++++++++ common/CMakeLists.txt | 6 ++ common/list.c | 91 ++++++++++++++++++++++++++++++ common/log.c | 100 +++++++++++++++++++++++++++++++++ example/CMakeLists.txt | 7 +++ example/main.c | 19 +++++++ include/backend/wayland.h | 21 ++++++- include/common/log.h | 18 ++++++ include/wlr/backend.h | 7 +++ include/wlr/backend/wayland.h | 14 +++++ include/wlr/common/list.h | 31 ++++++++++ include/wlr/common/log.h | 16 ++++++ include/wlr/wayland.h | 32 +++++++++++ 17 files changed, 445 insertions(+), 22 deletions(-) delete mode 100644 backend/wayland/CMakeLists.txt create mode 100644 backend/wayland/registry.c create mode 100644 common/CMakeLists.txt create mode 100644 common/list.c create mode 100644 common/log.c create mode 100644 example/CMakeLists.txt create mode 100644 example/main.c create mode 100644 include/common/log.h create mode 100644 include/wlr/backend.h create mode 100644 include/wlr/backend/wayland.h create mode 100644 include/wlr/common/list.h create mode 100644 include/wlr/common/log.h create mode 100644 include/wlr/wayland.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 19546711..939def0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,3 +58,5 @@ include(Manpage) include_directories(include) add_subdirectory(backend) +add_subdirectory(common) +add_subdirectory(example) diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index d69efdd5..01ac5e4e 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -1 +1,14 @@ -add_subdirectory(wayland) +include_directories( + ${PROTOCOLS_INCLUDE_DIRS} + ${WAYLAND_INCLUDE_DIR} +) + +add_library(wlr-backend + wayland/backend.c + wayland/registry.c +) + +target_link_libraries(wlr-backend + wlr-common + ${WAYLAND_LIBRARIES} +) diff --git a/backend/wayland/CMakeLists.txt b/backend/wayland/CMakeLists.txt deleted file mode 100644 index f185245c..00000000 --- a/backend/wayland/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -include_directories( - ${PROTOCOLS_INCLUDE_DIRS} - ${WAYLAND_INCLUDE_DIR} - . -) - -add_library(wlr-backend-wayland - backend.c -) - -target_link_libraries(wlr-backend-wayland - ${WAYLAND_LIBRARIES} -) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 3564fc12..8ea54058 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -1,13 +1,49 @@ #include #include #include +#include #include "backend/wayland.h" +#include "common/log.h" -struct wlr_wayland_backend *wayland_backend_init(struct wl_display *display, - size_t outputs) { - struct wlr_wayland_backend *backend = calloc( - sizeof(struct wlr_wayland_backend), 1); +void wlr_wl_backend_free(struct wlr_wl_backend *backend) { + if (!backend) { + return; + } + // TODO: free more shit + free(backend); +} + +/* + * Initializes the wayland backend. Opens a connection to a remote wayland + * compositor and creates surfaces for each output, then registers globals on + * the specified display. + */ +struct wlr_wl_backend *wlr_wl_backend_init( + struct wl_display *display, size_t outputs) { + assert(display); + struct wlr_wl_backend *backend; + if (!(backend = calloc(sizeof(struct wlr_wl_backend), 1))) { + wlr_log(L_ERROR, "Could not allocate backend"); + goto error; + } + if (!(backend->outputs = list_create())) { + wlr_log(L_ERROR, "Could not allocate output list"); + goto error; + } backend->local_display = display; - // TODO: obtain reference to remote display + backend->remote_display = wl_display_connect(getenv("_WAYLAND_DISPLAY")); + if (!backend->remote_display) { + wlr_log(L_ERROR, "Could not connect to remote display"); + goto error; + } + if (!(backend->remote_registry = wl_display_get_registry( + backend->remote_display))) { + wlr_log(L_ERROR, "Could not obtain reference to remote registry"); + goto error; + } + wlr_wlb_registry_poll(backend); return backend; +error: + wlr_wl_backend_free(backend); + return NULL; } diff --git a/backend/wayland/registry.c b/backend/wayland/registry.c new file mode 100644 index 00000000..35d386d3 --- /dev/null +++ b/backend/wayland/registry.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include "backend/wayland.h" +#include "common/log.h" + +static void registry_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + //struct wlr_wl_backend *backend = data; + wlr_log(L_DEBUG, "Remote wayland global: %s v%d", interface, version); + // TODO +} + +static void registry_global_remove(void *data, + struct wl_registry *registry, uint32_t name) { + // TODO +} + +static const struct wl_registry_listener registry_listener = { + .global = registry_global, + .global_remove = registry_global_remove +}; + +void wlr_wlb_registry_poll(struct wlr_wl_backend *backend) { + wl_registry_add_listener(backend->remote_registry, + ®istry_listener, backend->remote_registry); + wl_display_dispatch(backend->remote_display); + wl_display_roundtrip(backend->remote_display); +} diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 00000000..d8d52681 --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(wlr-common STATIC + list.c + log.c +) + +target_link_libraries(wlr-common m) diff --git a/common/list.c b/common/list.c new file mode 100644 index 00000000..095fbced --- /dev/null +++ b/common/list.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +list_t *list_create(void) { + list_t *list = malloc(sizeof(list_t)); + list->capacity = 10; + list->length = 0; + list->items = malloc(sizeof(void*) * list->capacity); + return list; +} + +static void list_resize(list_t *list) { + if (list->length == list->capacity) { + list->capacity += 10; + list->items = realloc(list->items, sizeof(void*) * list->capacity); + } +} + +void list_free(list_t *list) { + if (list == NULL) { + return; + } + free(list->items); + free(list); +} + +void list_foreach(list_t *list, void (*callback)(void *item)) { + if (list == NULL || callback == NULL) { + return; + } + for (size_t i = 0; i < list->length; i++) { + callback(list->items[i]); + } +} + +void list_add(list_t *list, void *item) { + list_resize(list); + list->items[list->length++] = item; +} + +void list_push(list_t *list, void *item) { + list_add(list, item); +} + +void list_insert(list_t *list, size_t index, void *item) { + list_resize(list); + memmove(&list->items[index + 1], &list->items[index], sizeof(void*) * (list->length - index)); + list->length++; + list->items[index] = item; +} + +void list_del(list_t *list, size_t index) { + list->length--; + memmove(&list->items[index], &list->items[index + 1], sizeof(void*) * (list->length - index)); +} + +void *list_pop(list_t *list) { + void *_ = list->items[list->length - 1]; + list_del(list, list->length - 1); + return _; +} + +void *list_peek(list_t *list) { + return list->items[list->length - 1]; +} + +void list_cat(list_t *list, list_t *source) { + size_t i; + for (i = 0; i < source->length; ++i) { + list_add(list, source->items[i]); + } +} + +void list_qsort(list_t* list, int compare(const void *left, const void *right)) { + qsort(list->items, list->length, sizeof(void *), compare); +} + +int list_seq_find(list_t *list, + int compare(const void *item, const void *data), + const void *data) { + for (size_t i = 0; i < list->length; i++) { + void *item = list->items[i]; + if (compare(item, data) == 0) { + return i; + } + } + return -1; +} diff --git a/common/log.c b/common/log.c new file mode 100644 index 00000000..7e59fcca --- /dev/null +++ b/common/log.c @@ -0,0 +1,100 @@ +#define _POSIX_C_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include +#include "wlr/common/log.h" +#include "common/log.h" + +static bool colored = true; +static log_callback_t log_callback; + +static const char *verbosity_colors[] = { + [L_SILENT] = "", + [L_ERROR ] = "\x1B[1;31m", + [L_INFO ] = "\x1B[1;34m", + [L_DEBUG ] = "\x1B[1;30m", +}; + +void wlr_log_init(log_callback_t callback) { + log_callback = callback; + // TODO: Use log callback +} + +void _wlr_vlog(const char *filename, int line, log_importance_t verbosity, + const char *format, va_list args) { + // prefix the time to the log message + static struct tm result; + static time_t t; + static struct tm *tm_info; + char buffer[26]; + + // get current time + t = time(NULL); + // convert time to local time (determined by the locale) + tm_info = localtime_r(&t, &result); + // generate time prefix + strftime(buffer, sizeof(buffer), "%x %X - ", tm_info); + fprintf(stderr, "%s", buffer); + + unsigned int c = verbosity; + if (c > sizeof(verbosity_colors) / sizeof(char *) - 1) { + c = sizeof(verbosity_colors) / sizeof(char *) - 1; + } + + if (colored && isatty(STDERR_FILENO)) { + fprintf(stderr, "%s", verbosity_colors[c]); + } + + if (filename && line) { + const char *file = filename + strlen(filename); + while (file != filename && *file != '/') { + --file; + } + if (*file == '/') { + ++file; + } + fprintf(stderr, "[%s:%d] ", file, line); + } + + vfprintf(stderr, format, args); + + if (colored && isatty(STDERR_FILENO)) { + fprintf(stderr, "\x1B[0m"); + } + fprintf(stderr, "\n"); +} + +void _wlr_log(const char *filename, int line, log_importance_t verbosity, const char* format, ...) { + va_list args; + va_start(args, format); + _wlr_vlog(filename, line, verbosity, format, args); + va_end(args); +} + +void wlr_log_errno(log_importance_t verbosity, char* format, ...) { + unsigned int c = verbosity; + if (c > sizeof(verbosity_colors) / sizeof(char *) - 1) { + c = sizeof(verbosity_colors) / sizeof(char *) - 1; + } + + if (isatty(STDERR_FILENO)) { + fprintf(stderr, "%s", verbosity_colors[c]); + } + + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + fprintf(stderr, ": "); + fprintf(stderr, "%s", strerror(errno)); + + if (isatty(STDERR_FILENO)) { + fprintf(stderr, "\x1B[0m"); + } + fprintf(stderr, "\n"); +} diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 00000000..73768393 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(example + main.c +) + +target_link_libraries(example + wlr-backend +) diff --git a/example/main.c b/example/main.c new file mode 100644 index 00000000..4240b9e3 --- /dev/null +++ b/example/main.c @@ -0,0 +1,19 @@ +#define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include + +int main(int argc, char **argv) { + // TODO: Move this stuff to a wlr backend selector function + char *_wl_display = getenv("WAYLAND_DISPLAY"); + if (_wl_display) { + unsetenv("WAYLAND_DISPLAY"); + setenv("_WAYLAND_DISPLAY", _wl_display, 1); + } + struct wl_display *wl_display = wl_display_create(); + struct wlr_wl_backend *backend = wlr_wl_backend_init(wl_display, 1); + wlr_wl_backend_free(backend); + wl_display_destroy(wl_display); + return 0; +} diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 9a445af9..368b0724 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -1,9 +1,24 @@ -#ifndef _WLR_BACKEND_WAYLAND_INTERNAL_H -#define _WLR_BACKEND_WAYLAND_INTERNAL_H +#ifndef _WLR_INTERNAL_BACKEND_WAYLAND_H +#define _WLR_INTERNAL_BACKEND_WAYLAND_H -struct wlr_wayland_backend { +#include +#include +#include +#include + +struct wlr_wl_backend { + /* local state */ struct wl_display *local_display; + /* remote state */ struct wl_display *remote_display; + struct wl_registry *remote_registry; + struct wl_compositor *remote_compositor; + struct wl_shell *shell; + struct wl_shm *shm; + struct wlr_wl_seat *seat; + list_t *outputs; }; +void wlr_wlb_registry_poll(struct wlr_wl_backend *backend); + #endif diff --git a/include/common/log.h b/include/common/log.h new file mode 100644 index 00000000..849f8ef0 --- /dev/null +++ b/include/common/log.h @@ -0,0 +1,18 @@ +#ifndef _WLR_INTERNAL_COMMON_LOG_H +#define _WLR_INTERNAL_COMMON_LOG_H +#include +#include + +void wlr_log_errno(log_importance_t verbosity, char* format, ...) __attribute__((format(printf,2,3))); + +void wlr_log_errno(log_importance_t verbosity, char* format, ...) __attribute__((format(printf,2,3))); + +void _wlr_log(const char *filename, int line, log_importance_t verbosity, const char* format, ...) __attribute__((format(printf,4,5))); + +#define wlr_log(VERBOSITY, FMT, ...) \ + _wlr_log(__FILE__, __LINE__, VERBOSITY, FMT, ##__VA_ARGS__) + +#define wlr_vlog(VERBOSITY, FMT, VA_ARGS) \ + _wlr_vlog(__FILE__, __LINE__, VERBOSITY, FMT, VA_ARGS) + +#endif diff --git a/include/wlr/backend.h b/include/wlr/backend.h new file mode 100644 index 00000000..527efa05 --- /dev/null +++ b/include/wlr/backend.h @@ -0,0 +1,7 @@ +#ifndef _WLR_BACKEND_H +#define _WLR_BACKEND_H + +struct wlr_backend *wlr_backend_init(); +void wlr_backend_free(struct wlr_backend *backend); + +#endif diff --git a/include/wlr/backend/wayland.h b/include/wlr/backend/wayland.h new file mode 100644 index 00000000..4318cc26 --- /dev/null +++ b/include/wlr/backend/wayland.h @@ -0,0 +1,14 @@ +#ifndef _WLR_BACKEND_WAYLAND_INTERNAL_H +#define _WLR_BACKEND_WAYLAND_INTERNAL_H + +#include +#include +#include + +struct wlr_wl_backend; + +void wlr_wl_backend_free(struct wlr_wl_backend *backend); +struct wlr_wl_backend *wlr_wl_backend_init(struct wl_display *display, + size_t outputs); + +#endif diff --git a/include/wlr/common/list.h b/include/wlr/common/list.h new file mode 100644 index 00000000..2bc82570 --- /dev/null +++ b/include/wlr/common/list.h @@ -0,0 +1,31 @@ +#ifndef _WLR_LIST_H +#define _WLR_LIST_H + +#include + +typedef struct { + size_t capacity; + size_t length; + void **items; +} list_t; + +list_t *list_create(void); +void list_free(list_t *list); +void list_foreach(list_t *list, void (*callback)(void* item)); +void list_add(list_t *list, void *item); +void list_push(list_t *list, void *item); +void list_insert(list_t *list, size_t index, void *item); +void list_del(list_t *list, size_t index); +void *list_pop(list_t *list); +void *list_peek(list_t *list); +void list_cat(list_t *list, list_t *source); +// See qsort. Remember to use *_qsort functions as compare functions, +// because they dereference the left and right arguments first! +void list_qsort(list_t *list, int compare(const void *left, const void *right)); +// Return index for first item in list that returns 0 for given compare +// function or -1 if none matches. +int list_seq_find(list_t *list, + int compare(const void *item, const void *cmp_to), + const void *cmp_to); + +#endif diff --git a/include/wlr/common/log.h b/include/wlr/common/log.h new file mode 100644 index 00000000..5b4d5a53 --- /dev/null +++ b/include/wlr/common/log.h @@ -0,0 +1,16 @@ +#ifndef _WLR_COMMON_LOG_H +#define _WLR_COMMON_LOG_H +#include + +typedef enum { + L_SILENT = 0, + L_ERROR = 1, + L_INFO = 2, + L_DEBUG = 3, +} log_importance_t; + +typedef void (*log_callback_t)(log_importance_t importance, const char *fmt, va_list args); + +void init_log(log_callback_t callback); + +#endif diff --git a/include/wlr/wayland.h b/include/wlr/wayland.h new file mode 100644 index 00000000..1c0b30ae --- /dev/null +++ b/include/wlr/wayland.h @@ -0,0 +1,32 @@ +#ifndef _WLR_WAYLAND_H +#define _WLR_WAYLAND_H + +#include +#include + +struct wlr_wl_seat { + struct wl_seat *wl_seat; + uint32_t capabilities; + const char *name; + list_t *outputs; + list_t *pointers; +}; + +struct wlr_wl_output { + struct wl_output *wl_output; + uint32_t flags; + uint32_t width, height; + uint32_t scale; +}; + +struct wlr_wl_keyboard { + struct wl_keyboard *wl_keyboard; +}; + +struct wlr_wl_pointer { + struct wl_pointer *wl_pointer; + struct wl_surface *current_surface; + wl_fixed_t x, y; +}; + +#endif