commit 1cedf543a975599fba27b9c7cc6dc73be3a537c7 from: mtmn date: Sat Jul 11 22:07:33 2026 UTC remove wlr-river-title and wlr-sway-title commit - c9f58cc425e8d08c91679f896b60cfb04aadd6b2 commit + 1cedf543a975599fba27b9c7cc6dc73be3a537c7 blob - 1572e329fa24a84dbeb3a808663fc79c745bb3ca blob + 997ee1d7afad073789c784bd318fe8dc62226b04 --- README.md +++ README.md @@ -18,8 +18,6 @@ Various tools I have been using throughout the years. | [shuffle](shuffle/) | random album picker for MPD | | [speediness](speediness/) | network speed test | | [tempfox](tempfox/) | Firefox user.js preference overrides | -| [wlr-river-title](wlr-river-title/) | River/Wayland focused view title printer | -| [wlr-sway-title](wlr-sway-title/) | Sway/Wayland focused view title printer | | [wrd](wrd/) | full-text search and reader for an offline web archive | | [plants](plants/) | bluetooth battery monitoring for linux | blob - 781486535b09078f7bc2f689ad2d32d950de7e69 (mode 644) blob + /dev/null --- wlr-river-title/BUILD +++ /dev/null @@ -1,34 +0,0 @@ -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") -load("//bazel:local-deploy.bzl", "local_deploy") - -package(default_visibility = ["//visibility:public"]) - -COMMON_COPTS = [ - "-Wall", - "-Wextra", - "-O2", - "-fanalyzer", - "-Wshadow", -] - -cc_library( - name = "river-status", - srcs = ["river-status.c"], - hdrs = ["river-status.h"], - copts = COMMON_COPTS, - linkopts = ["-lwayland-client"], -) - -cc_binary( - name = "wlr-river-title", - srcs = ["wlr-river-title.c"], - copts = COMMON_COPTS, - deps = [":river-status"], -) - -local_deploy( - name = "deploy", - srcs = [ - ":wlr-river-title", - ], -) blob - 7a5e4388b3b9ce0d2e06e9b1ed6d5349febc96c1 (mode 644) blob + /dev/null --- wlr-river-title/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# wlr-river-title - -Prints the title of the currently focused view in the [River](https://codeberg.org/river/river) Wayland compositor and exits. Useful for feeding into status bars. - -## Building - -```sh -make -# or -cc wlr-river-title.c river-status.c -o wlr-river-title $(pkg-config --cflags --libs wayland-client) -``` - -## Usage - -```sh -wlr-river-title -``` - -Prints one line to stdout and exits. Exits with status 1 if the Wayland display cannot be connected to or the river-status protocol is unavailable. blob - 7b0a2250a13f5fa99906f3f783d0d74e223856ec (mode 644) blob + /dev/null --- wlr-river-title/river-status.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Generated by wayland-scanner 1.24.0 */ - -/* - * Copyright 2020 The River Developers - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include "wayland-util.h" - -#ifndef __has_attribute -# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ -#endif - -#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) -#define WL_PRIVATE __attribute__ ((visibility("hidden"))) -#else -#define WL_PRIVATE -#endif - -extern const struct wl_interface wl_output_interface; -extern const struct wl_interface wl_seat_interface; -extern const struct wl_interface zriver_output_status_v1_interface; -extern const struct wl_interface zriver_seat_status_v1_interface; - -static const struct wl_interface *river_status_unstable_v1_types[] = { - NULL, - &zriver_output_status_v1_interface, - &wl_output_interface, - &zriver_seat_status_v1_interface, - &wl_seat_interface, - &wl_output_interface, - &wl_output_interface, -}; - -static const struct wl_message zriver_status_manager_v1_requests[] = { - { "destroy", "", river_status_unstable_v1_types + 0 }, - { "get_river_output_status", "no", river_status_unstable_v1_types + 1 }, - { "get_river_seat_status", "no", river_status_unstable_v1_types + 3 }, -}; - -WL_PRIVATE const struct wl_interface zriver_status_manager_v1_interface = { - "zriver_status_manager_v1", 4, - 3, zriver_status_manager_v1_requests, - 0, NULL, -}; - -static const struct wl_message zriver_output_status_v1_requests[] = { - { "destroy", "", river_status_unstable_v1_types + 0 }, -}; - -static const struct wl_message zriver_output_status_v1_events[] = { - { "focused_tags", "u", river_status_unstable_v1_types + 0 }, - { "view_tags", "a", river_status_unstable_v1_types + 0 }, - { "urgent_tags", "2u", river_status_unstable_v1_types + 0 }, - { "layout_name", "4s", river_status_unstable_v1_types + 0 }, - { "layout_name_clear", "4", river_status_unstable_v1_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface zriver_output_status_v1_interface = { - "zriver_output_status_v1", 4, - 1, zriver_output_status_v1_requests, - 5, zriver_output_status_v1_events, -}; - -static const struct wl_message zriver_seat_status_v1_requests[] = { - { "destroy", "", river_status_unstable_v1_types + 0 }, -}; - -static const struct wl_message zriver_seat_status_v1_events[] = { - { "focused_output", "o", river_status_unstable_v1_types + 5 }, - { "unfocused_output", "o", river_status_unstable_v1_types + 6 }, - { "focused_view", "s", river_status_unstable_v1_types + 0 }, - { "mode", "3s", river_status_unstable_v1_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface zriver_seat_status_v1_interface = { - "zriver_seat_status_v1", 3, - 1, zriver_seat_status_v1_requests, - 4, zriver_seat_status_v1_events, -}; - blob - 4f26facf98d3474e16969cd1b5841ccdad1d1da7 (mode 644) blob + /dev/null --- wlr-river-title/river-status.h +++ /dev/null @@ -1,438 +0,0 @@ -/* Generated by wayland-scanner 1.24.0 */ - -#ifndef RIVER_STATUS_UNSTABLE_V1_CLIENT_PROTOCOL_H -#define RIVER_STATUS_UNSTABLE_V1_CLIENT_PROTOCOL_H - -#include -#include -#include "wayland-client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @page page_river_status_unstable_v1 The river_status_unstable_v1 protocol - * @section page_ifaces_river_status_unstable_v1 Interfaces - * - @subpage page_iface_zriver_status_manager_v1 - manage river status objects - * - @subpage page_iface_zriver_output_status_v1 - track output tags and focus - * - @subpage page_iface_zriver_seat_status_v1 - track seat focus - * @section page_copyright_river_status_unstable_v1 Copyright - *
- *
- * Copyright 2020 The River Developers
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- * 
- */ -struct wl_output; -struct wl_seat; -struct zriver_output_status_v1; -struct zriver_seat_status_v1; -struct zriver_status_manager_v1; - -#ifndef ZRIVER_STATUS_MANAGER_V1_INTERFACE -#define ZRIVER_STATUS_MANAGER_V1_INTERFACE -/** - * @page page_iface_zriver_status_manager_v1 zriver_status_manager_v1 - * @section page_iface_zriver_status_manager_v1_desc Description - * - * A global factory for objects that receive status information specific - * to river. It could be used to implement, for example, a status bar. - * @section page_iface_zriver_status_manager_v1_api API - * See @ref iface_zriver_status_manager_v1. - */ -/** - * @defgroup iface_zriver_status_manager_v1 The zriver_status_manager_v1 interface - * - * A global factory for objects that receive status information specific - * to river. It could be used to implement, for example, a status bar. - */ -extern const struct wl_interface zriver_status_manager_v1_interface; -#endif -#ifndef ZRIVER_OUTPUT_STATUS_V1_INTERFACE -#define ZRIVER_OUTPUT_STATUS_V1_INTERFACE -/** - * @page page_iface_zriver_output_status_v1 zriver_output_status_v1 - * @section page_iface_zriver_output_status_v1_desc Description - * - * This interface allows clients to receive information about the current - * windowing state of an output. - * @section page_iface_zriver_output_status_v1_api API - * See @ref iface_zriver_output_status_v1. - */ -/** - * @defgroup iface_zriver_output_status_v1 The zriver_output_status_v1 interface - * - * This interface allows clients to receive information about the current - * windowing state of an output. - */ -extern const struct wl_interface zriver_output_status_v1_interface; -#endif -#ifndef ZRIVER_SEAT_STATUS_V1_INTERFACE -#define ZRIVER_SEAT_STATUS_V1_INTERFACE -/** - * @page page_iface_zriver_seat_status_v1 zriver_seat_status_v1 - * @section page_iface_zriver_seat_status_v1_desc Description - * - * This interface allows clients to receive information about the current - * focus of a seat. Note that (un)focused_output events will only be sent - * if the client has bound the relevant wl_output globals. - * @section page_iface_zriver_seat_status_v1_api API - * See @ref iface_zriver_seat_status_v1. - */ -/** - * @defgroup iface_zriver_seat_status_v1 The zriver_seat_status_v1 interface - * - * This interface allows clients to receive information about the current - * focus of a seat. Note that (un)focused_output events will only be sent - * if the client has bound the relevant wl_output globals. - */ -extern const struct wl_interface zriver_seat_status_v1_interface; -#endif - -#define ZRIVER_STATUS_MANAGER_V1_DESTROY 0 -#define ZRIVER_STATUS_MANAGER_V1_GET_RIVER_OUTPUT_STATUS 1 -#define ZRIVER_STATUS_MANAGER_V1_GET_RIVER_SEAT_STATUS 2 - - -/** - * @ingroup iface_zriver_status_manager_v1 - */ -#define ZRIVER_STATUS_MANAGER_V1_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_zriver_status_manager_v1 - */ -#define ZRIVER_STATUS_MANAGER_V1_GET_RIVER_OUTPUT_STATUS_SINCE_VERSION 1 -/** - * @ingroup iface_zriver_status_manager_v1 - */ -#define ZRIVER_STATUS_MANAGER_V1_GET_RIVER_SEAT_STATUS_SINCE_VERSION 1 - -/** @ingroup iface_zriver_status_manager_v1 */ -static inline void -zriver_status_manager_v1_set_user_data(struct zriver_status_manager_v1 *zriver_status_manager_v1, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) zriver_status_manager_v1, user_data); -} - -/** @ingroup iface_zriver_status_manager_v1 */ -static inline void * -zriver_status_manager_v1_get_user_data(struct zriver_status_manager_v1 *zriver_status_manager_v1) -{ - return wl_proxy_get_user_data((struct wl_proxy *) zriver_status_manager_v1); -} - -static inline uint32_t -zriver_status_manager_v1_get_version(struct zriver_status_manager_v1 *zriver_status_manager_v1) -{ - return wl_proxy_get_version((struct wl_proxy *) zriver_status_manager_v1); -} - -/** - * @ingroup iface_zriver_status_manager_v1 - * - * This request indicates that the client will not use the - * river_status_manager object any more. Objects that have been created - * through this instance are not affected. - */ -static inline void -zriver_status_manager_v1_destroy(struct zriver_status_manager_v1 *zriver_status_manager_v1) -{ - wl_proxy_marshal_flags((struct wl_proxy *) zriver_status_manager_v1, - ZRIVER_STATUS_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zriver_status_manager_v1), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_zriver_status_manager_v1 - * - * This creates a new river_output_status object for the given wl_output. - */ -static inline struct zriver_output_status_v1 * -zriver_status_manager_v1_get_river_output_status(struct zriver_status_manager_v1 *zriver_status_manager_v1, struct wl_output *output) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) zriver_status_manager_v1, - ZRIVER_STATUS_MANAGER_V1_GET_RIVER_OUTPUT_STATUS, &zriver_output_status_v1_interface, wl_proxy_get_version((struct wl_proxy *) zriver_status_manager_v1), 0, NULL, output); - - return (struct zriver_output_status_v1 *) id; -} - -/** - * @ingroup iface_zriver_status_manager_v1 - * - * This creates a new river_seat_status object for the given wl_seat. - */ -static inline struct zriver_seat_status_v1 * -zriver_status_manager_v1_get_river_seat_status(struct zriver_status_manager_v1 *zriver_status_manager_v1, struct wl_seat *seat) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) zriver_status_manager_v1, - ZRIVER_STATUS_MANAGER_V1_GET_RIVER_SEAT_STATUS, &zriver_seat_status_v1_interface, wl_proxy_get_version((struct wl_proxy *) zriver_status_manager_v1), 0, NULL, seat); - - return (struct zriver_seat_status_v1 *) id; -} - -/** - * @ingroup iface_zriver_output_status_v1 - * @struct zriver_output_status_v1_listener - */ -struct zriver_output_status_v1_listener { - /** - * focused tags of the output - * - * Sent once binding the interface and again whenever the tag - * focus of the output changes. - * @param tags 32-bit bitfield - */ - void (*focused_tags)(void *data, - struct zriver_output_status_v1 *zriver_output_status_v1, - uint32_t tags); - /** - * tag state of an output's views - * - * Sent once on binding the interface and again whenever the tag - * state of the output changes. - * @param tags array of 32-bit bitfields - */ - void (*view_tags)(void *data, - struct zriver_output_status_v1 *zriver_output_status_v1, - struct wl_array *tags); - /** - * tags of the output with an urgent view - * - * Sent once on binding the interface and again whenever the set - * of tags with at least one urgent view changes. - * @param tags 32-bit bitfield - * @since 2 - */ - void (*urgent_tags)(void *data, - struct zriver_output_status_v1 *zriver_output_status_v1, - uint32_t tags); - /** - * name of the layout - * - * Sent once on binding the interface should a layout name exist - * and again whenever the name changes. - * @param name layout name - * @since 4 - */ - void (*layout_name)(void *data, - struct zriver_output_status_v1 *zriver_output_status_v1, - const char *name); - /** - * name of the layout - * - * Sent when the current layout name has been removed without a - * new one being set, for example when the active layout generator - * disconnects. - * @since 4 - */ - void (*layout_name_clear)(void *data, - struct zriver_output_status_v1 *zriver_output_status_v1); -}; - -/** - * @ingroup iface_zriver_output_status_v1 - */ -static inline int -zriver_output_status_v1_add_listener(struct zriver_output_status_v1 *zriver_output_status_v1, - const struct zriver_output_status_v1_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) zriver_output_status_v1, - (void (**)(void)) listener, data); -} - -#define ZRIVER_OUTPUT_STATUS_V1_DESTROY 0 - -/** - * @ingroup iface_zriver_output_status_v1 - */ -#define ZRIVER_OUTPUT_STATUS_V1_FOCUSED_TAGS_SINCE_VERSION 1 -/** - * @ingroup iface_zriver_output_status_v1 - */ -#define ZRIVER_OUTPUT_STATUS_V1_VIEW_TAGS_SINCE_VERSION 1 -/** - * @ingroup iface_zriver_output_status_v1 - */ -#define ZRIVER_OUTPUT_STATUS_V1_URGENT_TAGS_SINCE_VERSION 2 -/** - * @ingroup iface_zriver_output_status_v1 - */ -#define ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_SINCE_VERSION 4 -/** - * @ingroup iface_zriver_output_status_v1 - */ -#define ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_CLEAR_SINCE_VERSION 4 - -/** - * @ingroup iface_zriver_output_status_v1 - */ -#define ZRIVER_OUTPUT_STATUS_V1_DESTROY_SINCE_VERSION 1 - -/** @ingroup iface_zriver_output_status_v1 */ -static inline void -zriver_output_status_v1_set_user_data(struct zriver_output_status_v1 *zriver_output_status_v1, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) zriver_output_status_v1, user_data); -} - -/** @ingroup iface_zriver_output_status_v1 */ -static inline void * -zriver_output_status_v1_get_user_data(struct zriver_output_status_v1 *zriver_output_status_v1) -{ - return wl_proxy_get_user_data((struct wl_proxy *) zriver_output_status_v1); -} - -static inline uint32_t -zriver_output_status_v1_get_version(struct zriver_output_status_v1 *zriver_output_status_v1) -{ - return wl_proxy_get_version((struct wl_proxy *) zriver_output_status_v1); -} - -/** - * @ingroup iface_zriver_output_status_v1 - * - * This request indicates that the client will not use the - * river_output_status object any more. - */ -static inline void -zriver_output_status_v1_destroy(struct zriver_output_status_v1 *zriver_output_status_v1) -{ - wl_proxy_marshal_flags((struct wl_proxy *) zriver_output_status_v1, - ZRIVER_OUTPUT_STATUS_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zriver_output_status_v1), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_zriver_seat_status_v1 - * @struct zriver_seat_status_v1_listener - */ -struct zriver_seat_status_v1_listener { - /** - * the seat focused an output - * - * Sent on binding the interface and again whenever an output - * gains focus. - */ - void (*focused_output)(void *data, - struct zriver_seat_status_v1 *zriver_seat_status_v1, - struct wl_output *output); - /** - * the seat unfocused an output - * - * Sent whenever an output loses focus. - */ - void (*unfocused_output)(void *data, - struct zriver_seat_status_v1 *zriver_seat_status_v1, - struct wl_output *output); - /** - * information on the focused view - * - * Sent once on binding the interface and again whenever the - * focused view or a property thereof changes. The title may be an - * empty string if no view is focused or the focused view did not - * set a title. - * @param title title of the focused view - */ - void (*focused_view)(void *data, - struct zriver_seat_status_v1 *zriver_seat_status_v1, - const char *title); - /** - * the active mode changed - * - * Sent once on binding the interface and again whenever a new - * mode is entered (e.g. with riverctl enter-mode foobar). - * @param name name of the mode - * @since 3 - */ - void (*mode)(void *data, - struct zriver_seat_status_v1 *zriver_seat_status_v1, - const char *name); -}; - -/** - * @ingroup iface_zriver_seat_status_v1 - */ -static inline int -zriver_seat_status_v1_add_listener(struct zriver_seat_status_v1 *zriver_seat_status_v1, - const struct zriver_seat_status_v1_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) zriver_seat_status_v1, - (void (**)(void)) listener, data); -} - -#define ZRIVER_SEAT_STATUS_V1_DESTROY 0 - -/** - * @ingroup iface_zriver_seat_status_v1 - */ -#define ZRIVER_SEAT_STATUS_V1_FOCUSED_OUTPUT_SINCE_VERSION 1 -/** - * @ingroup iface_zriver_seat_status_v1 - */ -#define ZRIVER_SEAT_STATUS_V1_UNFOCUSED_OUTPUT_SINCE_VERSION 1 -/** - * @ingroup iface_zriver_seat_status_v1 - */ -#define ZRIVER_SEAT_STATUS_V1_FOCUSED_VIEW_SINCE_VERSION 1 -/** - * @ingroup iface_zriver_seat_status_v1 - */ -#define ZRIVER_SEAT_STATUS_V1_MODE_SINCE_VERSION 3 - -/** - * @ingroup iface_zriver_seat_status_v1 - */ -#define ZRIVER_SEAT_STATUS_V1_DESTROY_SINCE_VERSION 1 - -/** @ingroup iface_zriver_seat_status_v1 */ -static inline void -zriver_seat_status_v1_set_user_data(struct zriver_seat_status_v1 *zriver_seat_status_v1, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) zriver_seat_status_v1, user_data); -} - -/** @ingroup iface_zriver_seat_status_v1 */ -static inline void * -zriver_seat_status_v1_get_user_data(struct zriver_seat_status_v1 *zriver_seat_status_v1) -{ - return wl_proxy_get_user_data((struct wl_proxy *) zriver_seat_status_v1); -} - -static inline uint32_t -zriver_seat_status_v1_get_version(struct zriver_seat_status_v1 *zriver_seat_status_v1) -{ - return wl_proxy_get_version((struct wl_proxy *) zriver_seat_status_v1); -} - -/** - * @ingroup iface_zriver_seat_status_v1 - * - * This request indicates that the client will not use the - * river_seat_status object any more. - */ -static inline void -zriver_seat_status_v1_destroy(struct zriver_seat_status_v1 *zriver_seat_status_v1) -{ - wl_proxy_marshal_flags((struct wl_proxy *) zriver_seat_status_v1, - ZRIVER_SEAT_STATUS_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zriver_seat_status_v1), WL_MARSHAL_FLAG_DESTROY); -} - -#ifdef __cplusplus -} -#endif - -#endif blob - d6d6dd2c0bafc54d592cb5d77e179a663cd4d8ff (mode 644) blob + /dev/null --- wlr-river-title/wlr-river-title.c +++ /dev/null @@ -1,88 +0,0 @@ - -#include -#include -#include -#include -#include "river-status.h" - -struct river_status_data { - struct zriver_status_manager_v1 *manager; - struct zriver_seat_status_v1 *seat_status; - struct wl_seat *seat; - char *focused_title; - int done; -}; - -static void seat_status_focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, struct wl_output *output) {} -static void seat_status_unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, struct wl_output *output) {} -static void seat_status_mode(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, const char *name) {} - -static void seat_status_focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, const char *title) { - struct river_status_data *d = data; - if (d->focused_title) free(d->focused_title); - d->focused_title = strdup(title); - d->done = 1; -} - -static const struct zriver_seat_status_v1_listener seat_status_listener = { - .focused_output = seat_status_focused_output, - .unfocused_output = seat_status_unfocused_output, - .focused_view = seat_status_focused_view, - .mode = seat_status_mode, -}; - -static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { - struct river_status_data *d = data; - if (strcmp(interface, zriver_status_manager_v1_interface.name) == 0) { - d->manager = wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, 1); - } else if (strcmp(interface, "wl_seat") == 0) { - d->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); - } -} - -static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {} - -static const struct wl_registry_listener registry_listener = { - .global = registry_handle_global, - .global_remove = registry_handle_global_remove, -}; - -int main() { - struct wl_display *display = wl_display_connect(NULL); - if (!display) { - fprintf(stderr, "Failed to connect to wayland display\n"); - return 1; - } - - struct river_status_data data = {0}; - struct wl_registry *registry = wl_display_get_registry(display); - wl_registry_add_listener(registry, ®istry_listener, &data); - - // Initial roundtrip to find all globals - wl_display_roundtrip(display); - - if (!data.manager || !data.seat) { - fprintf(stderr, "Could not find river_status_manager or wl_seat\n"); - return 1; - } - - // Now bind the seat status - data.seat_status = zriver_status_manager_v1_get_river_seat_status(data.manager, data.seat); - zriver_seat_status_v1_add_listener(data.seat_status, &seat_status_listener, &data); - - // Wait for events - while (!data.done && wl_display_dispatch(display) != -1); - - if (data.focused_title) { - printf("%s\n", data.focused_title); - free(data.focused_title); - } - - if (data.seat_status) zriver_seat_status_v1_destroy(data.seat_status); - if (data.manager) zriver_status_manager_v1_destroy(data.manager); - if (data.seat) wl_seat_destroy(data.seat); - wl_registry_destroy(registry); - wl_display_disconnect(display); - - return 0; -} blob - fa745fcd808bb68617018cc69c1f10d868c797ea (mode 644) blob + /dev/null --- wlr-sway-title/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -load("@rules_cc//cc:defs.bzl", "cc_binary") -load("//bazel:local-deploy.bzl", "local_deploy") - -package(default_visibility = ["//visibility:public"]) - -COMMON_COPTS = [ - "-Wall", - "-Wextra", - "-O2", - "-fanalyzer", - "-Wshadow", -] - -cc_binary( - name = "wlr-sway-title", - srcs = ["wlr-sway-title.c"], - copts = COMMON_COPTS, -) - -local_deploy( - name = "deploy", - srcs = [ - ":wlr-sway-title", - ], -) \ No newline at end of file blob - 7117821834ef5b0692672f7d3a8f38a1727325d9 (mode 644) blob + /dev/null --- wlr-sway-title/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# wlr-sway-title - -Prints the title of the currently focused view in a [sway](https://github.com/swaywm/sway)-compatible Wayland compositor (sway, swayfx, volare, …) via the i3 IPC protocol and exits. Useful for feeding into status bars or scripts like `monofetch`. - -## Building - -```sh -make -# or -cc wlr-sway-title.c -o wlr-sway-title -``` - -## Usage - -```sh -wlr-sway-title -``` - -Prints one line to stdout and exits. Reads the IPC socket from `SWAYSOCK`. Exits with status 1 if `SWAYSOCK` is unset, the socket cannot be connected to, or the IPC reply is malformed. \ No newline at end of file blob - b6d9a4421664864d534397c417ecc54ed0ae8f1f (mode 644) blob + /dev/null --- wlr-sway-title/wlr-sway-title.c +++ /dev/null @@ -1,446 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define I3_IPC_MAGIC "i3-ipc" -#define I3_IPC_MAGIC_LEN 6 -#define I3_IPC_MESSAGE_TYPE_GET_TREE 4 - -static int send_request(int sock, uint32_t type, const char *payload) { - size_t payload_len = payload ? strlen(payload) : 0; - char header[I3_IPC_MAGIC_LEN + sizeof(uint32_t) * 2]; - memcpy(header, I3_IPC_MAGIC, I3_IPC_MAGIC_LEN); - uint32_t len_field = (uint32_t)payload_len; - uint32_t type_field = type; - memcpy(header + I3_IPC_MAGIC_LEN, &len_field, sizeof(len_field)); - memcpy(header + I3_IPC_MAGIC_LEN + sizeof(uint32_t), &type_field, - sizeof(type_field)); - - size_t total = sizeof(header) + payload_len; - char *buf = malloc(total); - if (!buf) - return -1; - memcpy(buf, header, sizeof(header)); - if (payload_len) - memcpy(buf + sizeof(header), payload, payload_len); - - size_t sent = 0; - while (sent < total) { - ssize_t n = send(sock, buf + sent, total - sent, 0); - if (n < 0) { - free(buf); - return -1; - } - sent += (size_t)n; - } - free(buf); - return 0; -} - -static int recv_exact(int sock, char *buf, size_t need) { - size_t got = 0; - while (got < need) { - ssize_t n = recv(sock, buf + got, need - got, 0); - if (n < 0) - return -1; - if (n == 0) - return -1; - got += (size_t)n; - } - return 0; -} - -/* - * Reads one full IPC message from the socket. The server keeps the connection - * open after replying, so we must parse the header to know the payload length - * rather than waiting for EOF. Returns a malloc'd buffer containing the whole - * message (magic + length + type + payload, NUL-terminated) and points - * *out_payload at the payload start. - */ -static char *recv_message(int sock, char **out_payload, - size_t *out_payload_len) { - char header[I3_IPC_MAGIC_LEN + sizeof(uint32_t) * 2]; - if (recv_exact(sock, header, sizeof(header)) < 0) - return NULL; - if (memcmp(header, I3_IPC_MAGIC, I3_IPC_MAGIC_LEN) != 0) - return NULL; - - uint32_t payload_len; - memcpy(&payload_len, header + I3_IPC_MAGIC_LEN, sizeof(uint32_t)); - - size_t total = sizeof(header) + payload_len; - char *buf = malloc(total + 1); - if (!buf) - return NULL; - memcpy(buf, header, sizeof(header)); - if (payload_len > 0) { - if (recv_exact(sock, buf + sizeof(header), payload_len) < 0) { - free(buf); - return NULL; - } - } - buf[total] = '\0'; - *out_payload = buf + sizeof(header); - if (out_payload_len) - *out_payload_len = payload_len; - return buf; -} - -/* - * Minimal recursive JSON search: find the first object with a "focused":true - * member and return a malloc'd copy of its "name" string value. - * - * This is a tiny purpose-built parser; it is not a general JSON library. - * It walks the tree tracking object nesting and recognises the two keys - * we care about. - */ -struct search_ctx { - int focused_found; - char *name; -}; - -static void skip_ws(const char **p) { - while (**p && isspace((unsigned char)**p)) - (*p)++; -} - -static int match_key(const char **p, const char *key) { - skip_ws(p); - const char *start = *p; - if (**p != '"') - return 0; - (*p)++; - const char *k = key; - while (**p && *k) { - if (**p != *k) { - *p = start; - return 0; - } - (*p)++; - k++; - } - if (**p != '"') { - *p = start; - return 0; - } - (*p)++; - return 1; -} - -static char *parse_string(const char **p) { - skip_ws(p); - if (**p != '"') - return NULL; - (*p)++; - size_t cap = 64; - size_t len = 0; - char *out = malloc(cap); - if (!out) - return NULL; - while (**p && **p != '"') { - char c = **p; - if (c == '\\') { - (*p)++; - c = **p; - switch (c) { - case 'n': - c = '\n'; - break; - case 't': - c = '\t'; - break; - case 'r': - c = '\r'; - break; - case '"': - c = '"'; - break; - case '\\': - c = '\\'; - break; - case '/': - c = '/'; - break; - case 'b': - c = '\b'; - break; - case 'f': - c = '\f'; - break; - case 'u': { - /* skip 4 hex digits, substitute with '?' for simplicity */ - (*p)++; - for (int i = 0; i < 4 && isxdigit((unsigned char)**p); i++) - (*p)++; - c = '?'; - break; - } - default: - break; - } - } - if (len + 1 >= cap) { - cap *= 2; - char *nb = realloc(out, cap); - if (!nb) { - free(out); - return NULL; - } - out = nb; - } - out[len++] = c; - (*p)++; - } - if (**p == '"') - (*p)++; - out[len] = '\0'; - return out; -} - -static void walk_node(const char **p, struct search_ctx *ctx); - -static void skip_value(const char **p); - -static void skip_string(const char **p) { - if (**p != '"') - return; - (*p)++; - while (**p && **p != '"') { - if (**p == '\\') { - (*p)++; - if (!**p) - return; - } - (*p)++; - } - if (**p) - (*p)++; -} - -static void skip_object(const char **p) { - if (**p != '{') - return; - (*p)++; - for (;;) { - skip_ws(p); - if (**p == '}') { - (*p)++; - return; - } - if (**p == ',') { - (*p)++; - continue; - } - skip_string(p); - skip_ws(p); - if (**p == ':') - (*p)++; - skip_value(p); - } -} - -static void skip_array(const char **p) { - if (**p != '[') - return; - (*p)++; - for (;;) { - skip_ws(p); - if (**p == ']') { - (*p)++; - return; - } - if (**p == ',') { - (*p)++; - continue; - } - skip_value(p); - } -} - -static void skip_value(const char **p) { - skip_ws(p); - if (**p == '"') { - skip_string(p); - return; - } - if (**p == '{') { - skip_object(p); - return; - } - if (**p == '[') { - skip_array(p); - return; - } - while (**p && !isspace((unsigned char)**p) && **p != ',' && **p != '}' && - **p != ']') - (*p)++; -} - -static void walk_node(const char **p, struct search_ctx *ctx) { - skip_ws(p); - if (**p != '{') { - skip_value(p); - return; - } - (*p)++; - - int this_focused = 0; - char *this_name = NULL; - - for (;;) { - skip_ws(p); - if (**p == '}') { - (*p)++; - break; - } - if (**p == ',') { - (*p)++; - continue; - } - - if (match_key(p, "focused")) { - skip_ws(p); - if (**p == ':') - (*p)++; - skip_ws(p); - if (strncmp(*p, "true", 4) == 0) { - this_focused = 1; - *p += 4; - } else if (strncmp(*p, "false", 5) == 0) { - *p += 5; - } else { - skip_value(p); - } - continue; - } - - if (match_key(p, "name")) { - skip_ws(p); - if (**p == ':') - (*p)++; - char *s = parse_string(p); - if (s) { - free(this_name); - this_name = s; - } - continue; - } - - if (match_key(p, "nodes") || match_key(p, "floating_nodes")) { - skip_ws(p); - if (**p == ':') - (*p)++; - skip_ws(p); - if (**p != '[') { - skip_value(p); - continue; - } - (*p)++; - for (;;) { - skip_ws(p); - if (**p == ']') { - (*p)++; - break; - } - if (**p == ',') { - (*p)++; - continue; - } - walk_node(p, ctx); - if (ctx->name) { - free(this_name); - this_name = NULL; - this_focused = 0; - goto done; - } - } - continue; - } - - skip_ws(p); - if (**p == '"') { - skip_string(p); - skip_ws(p); - if (**p == ':') - (*p)++; - skip_value(p); - } else { - skip_value(p); - } - } - -done: - if (this_focused) { - ctx->focused_found = 1; - if (!ctx->name && this_name) { - ctx->name = this_name; - this_name = NULL; - } - } - free(this_name); -} - -static char *find_focused_name(char *json) { - const char *p = json; - struct search_ctx ctx = {0}; - walk_node(&p, &ctx); - if (ctx.focused_found && ctx.name) - return ctx.name; - free(ctx.name); - return NULL; -} - -int main(void) { - const char *sock_path = getenv("SWAYSOCK"); - if (!sock_path || !*sock_path) { - fprintf(stderr, "SWAYSOCK is not set\n"); - return 1; - } - - int sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - perror("socket"); - return 1; - } - - struct sockaddr_un addr; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1); - - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("connect"); - close(sock); - return 1; - } - - if (send_request(sock, I3_IPC_MESSAGE_TYPE_GET_TREE, NULL) < 0) { - fprintf(stderr, "failed to send IPC request\n"); - close(sock); - return 1; - } - - char *payload = NULL; - size_t payload_len = 0; - char *data = recv_message(sock, &payload, &payload_len); - close(sock); - if (!data) { - fprintf(stderr, "failed to read IPC reply\n"); - return 1; - } - - char *title = find_focused_name(payload); - if (title) { - printf("%s\n", title); - free(title); - } - - free(data); - return 0; -} \ No newline at end of file