summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/backend.h4
-rw-r--r--src/common/desktop.c81
-rw-r--r--src/common/desktop.h19
-rw-r--r--src/common/meson.build2
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')