tools

various tools I have been using throughout the years
Log | Files | Refs | README | LICENSE

commit 1e631b46b0575ff95e1d8cb091abe7a0e8e15ecd
parent 82cb7d852e77800c94cc577e793a11ef1e8f9d49
Author: mtmn <miro@haravara.org>
Date:   Wed,  6 May 2026 22:00:18 +0200

feat: add monofetch

Diffstat:
Amonofetch/BUILD | 27+++++++++++++++++++++++++++
Amonofetch/monofetch.sh | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amonofetch/wlr-river-title/BUILD | 34++++++++++++++++++++++++++++++++++
Amonofetch/wlr-river-title/river-status.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amonofetch/wlr-river-title/river-status.h | 438+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amonofetch/wlr-river-title/wlr-river-title.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 748 insertions(+), 0 deletions(-)

diff --git a/monofetch/BUILD b/monofetch/BUILD @@ -0,0 +1,27 @@ +load("@rules_cc//cc:defs.bzl", "cc_binary") +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +load("@rules_shell//shell:sh_library.bzl", "sh_library") +load("//bazel:local-deploy.bzl", "local_deploy") + +package(default_visibility = ["//visibility:public"]) + +# sh_library( +# name = "saturn", +# data = [ +# ":saturn_common", +# ":saturn_fetch_tracks", +# ":saturn_make_cover", +# ], +# ) + +sh_binary( + name = "monofetch", + srcs = ["monofetch.sh"], +) + +local_deploy( + name = "deploy", + srcs = [ + ":monofetch", + ], +) diff --git a/monofetch/monofetch.sh b/monofetch/monofetch.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +if [[ -n "$1" ]]; then + url="$1" +else + wl_focused_title="$(wlr-river-title)" + if [[ "$wl_focused_title" == *"Mozilla Firefox"* ]]; then + /usr/bin/wtype "yy" && sleep 0.5 + url=$(wl-paste 2>/dev/null) + else + notify-send -u critical "Error" "Focused window is not a web browser ($wl_focused_title)" + exit 1 + fi +fi + +if [[ -z "$url" ]]; then + notify-send "No URL found" + exit 1 +fi + +if [[ ! "$url" =~ ^https?:// ]]; then + notify-send "Invalid URL format" "$url" + exit 1 +fi + +domain=$(echo "$url" | sed -e 's|^https\?://||' -e 's|/.*||' -e 's|^www\.||') +path_part=$(echo "$url" | sed -e 's|^https\?://||' -e 's|[?#].*||') + +if [[ "$path_part" == */ ]] || [[ "$path_part" != */* ]]; then + if [[ "$path_part" != */* ]]; then + full_rel_path="$path_part/index.html" + else + full_rel_path="${path_part}index.html" + fi +else + full_rel_path="$path_part" +fi + +target_file_path="$HOME/misc/www/$full_rel_path" +target_dir=$(dirname "$target_file_path") + +md_slug=$(echo "$path_part" | tr '/' '-' | sed 's/^-//;s/-$//') +if [[ -z "$md_slug" ]] || [[ "$md_slug" == "index.html" ]]; then + md_slug="index" +fi + +md_filename="${domain}-${md_slug%.html}.md" +target_md_path="$HOME/misc/notes/www/$md_filename" + +mkdir -p "$target_dir" || { + notify-send -u critical "Error" "Failed to create directory" + exit 1 +} +if monolith -o "$target_file_path" "$url"; then + notify-send "Saved" "$url" +else + notify-send -u critical "Error" "Failed to download $url" + exit 1 +fi + +cat "$target_file_path" | html2markdown >"$target_md_path" + +if [[ ! -s "$target_md_path" ]]; then + notify-send -u critical "Error" "Conversion failed" +fi + diff --git a/monofetch/wlr-river-title/BUILD b/monofetch/wlr-river-title/BUILD @@ -0,0 +1,34 @@ +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", + ], +) diff --git a/monofetch/wlr-river-title/river-status.c b/monofetch/wlr-river-title/river-status.c @@ -0,0 +1,95 @@ +/* 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 <stdbool.h> +#include <stdlib.h> +#include <stdint.h> +#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, +}; + diff --git a/monofetch/wlr-river-title/river-status.h b/monofetch/wlr-river-title/river-status.h @@ -0,0 +1,438 @@ +/* Generated by wayland-scanner 1.24.0 */ + +#ifndef RIVER_STATUS_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define RIVER_STATUS_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#include <stdint.h> +#include <stddef.h> +#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 + * <pre> + * + * 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. + * </pre> + */ +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 diff --git a/monofetch/wlr-river-title/wlr-river-title.c b/monofetch/wlr-river-title/wlr-river-title.c @@ -0,0 +1,88 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wayland-client.h> +#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, &registry_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; +}