diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/backend.h | 4 | ||||
| -rw-r--r-- | src/common/desktop.c | 81 | ||||
| -rw-r--r-- | src/common/desktop.h | 19 | ||||
| -rw-r--r-- | src/common/meson.build | 2 |
4 files changed, 105 insertions, 1 deletions
diff --git a/src/common/backend.h b/src/common/backend.h index f0fae03..fd60418 100644 --- a/src/common/backend.h +++ b/src/common/backend.h @@ -15,6 +15,8 @@ struct yasl_display { struct yasl_display_cbs callbacks; struct yasl_loop *loop; void *app_runner; + /* Backend's copy of yasl_display_spec.app_id, or NULL; for desktop services. */ + const char *app_id; }; struct yasl_surface { @@ -89,6 +91,8 @@ struct yasl_backend_ops { bool (*surface_show_window_menu)(struct yasl_surface *s, struct yasl_vector2i pos); bool (*surface_drag_carry)(struct yasl_surface *s, struct yasl_vector2i offset); bool (*surface_place_under_pointer)(struct yasl_surface *s, struct yasl_vector2i at); + /* Optional; NULL means the bell is unsupported. */ + bool (*surface_bell)(struct yasl_surface *s); void *(*display_get_native_handle)(struct yasl_display *d); void *(*surface_get_native_handle)(struct yasl_surface *s); bool (*surface_get_native_frame)(struct yasl_surface *s, diff --git a/src/common/desktop.c b/src/common/desktop.c new file mode 100644 index 0000000..23c62d7 --- /dev/null +++ b/src/common/desktop.c @@ -0,0 +1,81 @@ +#include "yasl/desktop.h" +#include "common/backend.h" +#include "common/desktop.h" + +#include <string.h> + +/* Large enough for any path the platform APIs return. */ +#define DESKTOP_STR_MAX 4096 + +/* An RFC 3986 scheme, then ':', and no control characters anywhere. */ +static bool uri_valid(const char *uri) +{ + unsigned char c = (unsigned char)uri[0]; + if ((unsigned)((c | 32) - 'a') >= 26) return false; + const char *p = uri + 1; + for (; *p != ':'; p++) { + c = (unsigned char)*p; + bool alpha = (unsigned)((c | 32) - 'a') < 26; + bool digit = (unsigned)(c - '0') < 10; + if (!alpha && !digit && c != '+' && c != '-' && c != '.') return false; + } + for (; *p; p++) { + c = (unsigned char)*p; + if (c < 0x20 || c == 0x7f) return false; + } + return true; +} + +/* Copy len bytes and a NUL when they fit, and report the full length. */ +static size_t copy_out(char *out, size_t cap, const char *s, size_t len) +{ + if (len && len < cap) { + memcpy(out, s, len); + out[len] = '\0'; + } + return len; +} + +bool yasl_display_open_uri(struct yasl_display *d, const char *uri) +{ + if (!d || !uri || !uri_valid(uri)) return false; + return desktop_open_uri(uri); +} + +bool yasl_display_notify(struct yasl_display *d, const char *title, const char *body) +{ + if (!d || !title) return false; + return desktop_notify(d->app_id, title, body ? body : ""); +} + +uint32_t yasl_display_appearance(struct yasl_display *d) +{ + return d ? desktop_appearance() : 0; +} + +bool yasl_surface_bell(struct yasl_surface *s) +{ + if (!s || !s->display->ops->surface_bell) return false; + return s->display->ops->surface_bell(s); +} + +size_t yasl_executable_path(char *out, size_t cap) +{ + if (!out && cap) return 0; + char buf[DESKTOP_STR_MAX]; + return copy_out(out, cap, buf, desktop_executable_path(buf, sizeof(buf))); +} + +size_t yasl_resource_dir(char *out, size_t cap) +{ + if (!out && cap) return 0; + char buf[DESKTOP_STR_MAX]; + return copy_out(out, cap, buf, desktop_resource_dir(buf, sizeof(buf))); +} + +size_t yasl_default_locale(char *out, size_t cap) +{ + if (!out && cap) return 0; + char buf[DESKTOP_STR_MAX]; + return copy_out(out, cap, buf, desktop_default_locale(buf, sizeof(buf))); +} diff --git a/src/common/desktop.h b/src/common/desktop.h new file mode 100644 index 0000000..9af5952 --- /dev/null +++ b/src/common/desktop.h @@ -0,0 +1,19 @@ +#ifndef YASL_COMMON_DESKTOP_H +#define YASL_COMMON_DESKTOP_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +/* Operating-system desktop services behind yasl/desktop.h. Common code + * validates arguments first. Path and locale functions write a NUL-terminated + * string to buf and return its length, or zero on failure or when it does not + * fit in cap. */ +bool desktop_open_uri(const char *uri); +bool desktop_notify(const char *app_id, const char *title, const char *body); +uint32_t desktop_appearance(void); +size_t desktop_executable_path(char *buf, size_t cap); +size_t desktop_resource_dir(char *buf, size_t cap); +size_t desktop_default_locale(char *buf, size_t cap); + +#endif diff --git a/src/common/meson.build b/src/common/meson.build index 015c61c..26565ee 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -1 +1 @@ -sources += files('app.c', 'backend.c', 'input.c', 'native.c', 'timing.c', 'utf8.c') +sources += files('app.c', 'backend.c', 'desktop.c', 'input.c', 'native.c', 'timing.c', 'utf8.c') |
