@@ 3,8 3,14 @@
* SPDX-License-Identifier: Artistic-2.0
*/
-#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
#include <signal.h>
+#include <stdatomic.h>
+#include <string.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
#include <d2tk/frontend_wayland.h>
@@ 13,6 19,10 @@ typedef struct _app_t app_t;
struct _app_t {
d2tk_frontend_t *dwayland;
bool vertical;
+ int fd [2];
+ uint64_t counter [2];
+ pthread_t thread [2];
+ atomic_uint idx;
};
static sig_atomic_t done = false;
@@ 23,25 33,97 @@ _sig(int signum __attribute__((unused)))
done = true;
}
-static inline void
+static void *
+_thread(void *data)
+{
+ app_t *app = data;
+ const unsigned i = atomic_fetch_add(&app->idx, 1);
+ uint64_t counter = 0;
+
+ while(!done)
+ {
+ const ssize_t sz = write(app->fd[i], &counter, sizeof(counter));
+ switch(sz)
+ {
+ case -1:
+ if(errno != EAGAIN)
+ {
+ fprintf(stderr, "[%s] write failed: %s\n", __func__, strerror(errno));
+ }
+ break;
+ case sizeof(counter):
+ counter++;
+ break;
+ default:
+ fprintf(stderr, "[%s] write only %zi/8\n", __func__, sz);
+ break;
+ }
+
+ sleep(i + 1);
+ }
+
+ return NULL;
+}
+
+static void
_expose_dock(app_t *app, d2tk_flag_t flag, const d2tk_rect_t *rect)
{
d2tk_base_t *base = d2tk_frontend_get_base(app->dwayland);
+ for(unsigned i = 0; i < 2; i++)
+ {
+ uint64_t counter = 0;
+ const ssize_t sz = read(app->fd[i], &counter, sizeof(counter));
+ switch(sz)
+ {
+ case -1:
+ if(errno != EAGAIN)
+ {
+ fprintf(stderr, "[%s] read failed: %s\n", __func__, strerror(errno));
+ }
+ break;
+ case sizeof(counter):
+ app->counter[i] = counter;
+ break;
+ default:
+ fprintf(stderr, "[%s] read only %zi/8\n", __func__, sz);
+ break;
+ }
+
+ d2tk_base_wake_on_fd(base, D2TK_ID_IDX(i), app->fd[i]);
+ }
+
const d2tk_coord_t frac [8] = { 1, 1, 1, 4, 4, 1, 1, 1 };
D2TK_BASE_LAYOUT(rect, 8, frac, flag, lay)
{
const d2tk_rect_t *lrect = d2tk_layout_get_rect(lay);
const unsigned k = d2tk_layout_get_index(lay);
- if(d2tk_base_button_is_changed(base, D2TK_ID_IDX(k), lrect))
+ if(k == 0)
{
- fprintf(stderr, "press: %u\n", k);
+ char lbl [32];
+ const size_t lbl_len = snprintf(lbl, sizeof(lbl), "%"PRIu64, app->counter[0]);
+
+ d2tk_base_label(base, lbl_len, lbl, 0.7f, lrect, D2TK_ALIGN_CENTERED);
+ }
+ else if(k == 7)
+ {
+ char lbl [32];
+ const size_t lbl_len = snprintf(lbl, sizeof(lbl), "%"PRIu64, app->counter[1]);
+
+ d2tk_base_label(base, lbl_len, lbl, 0.7f, lrect, D2TK_ALIGN_CENTERED);
+ }
+ else
+ {
+ if(d2tk_base_button_is_changed(base, D2TK_ID_IDX(k), lrect))
+ {
+ fprintf(stderr, "press: %u\n", k);
+ }
}
}
}
-static inline int
+static int
_expose(void *data, d2tk_coord_t w, d2tk_coord_t h)
{
app_t *app = data;
@@ 60,6 142,8 @@ main(int argc, char **argv)
{
static app_t app;
+ atomic_init(&app.idx, 0);
+
const char *namespace = "wlroots";
d2tk_coord_t w = 600;
d2tk_coord_t h = 32;
@@ 204,6 288,12 @@ main(int argc, char **argv)
signal(SIGQUIT, _sig);
signal(SIGKILL, _sig);
+ for(unsigned i = 0; i < 2; i++)
+ {
+ app.fd[i] = eventfd(0, EFD_NONBLOCK);
+ pthread_create(&app.thread[i], NULL, _thread, &app);
+ }
+
app.dwayland = d2tk_wayland_new(&config);
if(app.dwayland)
{
@@ 214,5 304,11 @@ main(int argc, char **argv)
return EXIT_SUCCESS;
}
+ for(unsigned i = 0; i < 2; i++)
+ {
+ pthread_join(app.thread[i], NULL);
+ close(app.fd[i]);
+ }
+
return EXIT_FAILURE;
}
@@ 12,6 12,14 @@
#include "base_internal.h"
+typedef struct _d2tk_atom_body_fd_t d2tk_atom_body_fd_t;
+
+struct _d2tk_atom_body_fd_t {
+ int fd;
+};
+
+const size_t d2tk_atom_body_fd_sz = sizeof(d2tk_atom_body_fd_t);
+
static inline d2tk_id_t
_d2tk_flip_get_cur(d2tk_flip_t *flip)
{
@@ 123,10 131,10 @@ _d2tk_base_get_atom(d2tk_base_t *base, d2tk_id_t id, d2tk_atom_type_t type,
len = d2tk_atom_body_lineedit_sz;
} break;
#endif
- case D2TK_ATOM_FLOW_NODE:
- // fall-through
- case D2TK_ATOM_FLOW_ARC:
- // fall-through
+ case D2TK_ATOM_FD:
+ {
+ len = d2tk_atom_body_fd_sz;
+ } break;
default:
{
len = 0;
@@ 163,6 171,47 @@ _d2tk_base_get_atom(d2tk_base_t *base, d2tk_id_t id, d2tk_atom_type_t type,
return NULL; // no space left
}
+static int
+_fd_event(d2tk_atom_event_type_t event, void *data)
+{
+ d2tk_atom_body_fd_t *afd = data;
+
+ switch(event)
+ {
+ case D2TK_ATOM_EVENT_FD:
+ {
+ return afd->fd;
+ } break;
+
+ case D2TK_ATOM_EVENT_DEINIT:
+ // fall-through
+ case D2TK_ATOM_EVENT_NONE:
+ // fall-through
+ default:
+ {
+ // nothing to do
+ } break;
+ }
+
+ return 0;
+}
+
+D2TK_API int
+d2tk_base_wake_on_fd(d2tk_base_t *base, d2tk_id_t id, int fd)
+{
+ d2tk_atom_body_fd_t *afd = _d2tk_base_get_atom(base, id, D2TK_ATOM_FD,
+ _fd_event);
+
+ if(!afd)
+ {
+ return 1;
+ }
+
+ afd->fd = fd;
+
+ return 0;
+}
+
D2TK_API void
d2tk_clip_int32(int32_t min, int32_t *value, int32_t max)
{
@@ 17,8 17,7 @@ typedef enum _d2tk_atom_type_t {
D2TK_ATOM_SCROLL,
D2TK_ATOM_PANE,
D2TK_ATOM_FLOW,
- D2TK_ATOM_FLOW_NODE,
- D2TK_ATOM_FLOW_ARC,
+ D2TK_ATOM_FD,
#if D2TK_VTERM
D2TK_ATOM_PTY,
D2TK_ATOM_LINEEDIT
@@ 110,6 109,7 @@ struct _d2tk_base_t {
extern const size_t d2tk_atom_body_flow_sz;
extern const size_t d2tk_atom_body_pane_sz;
extern const size_t d2tk_atom_body_scroll_sz;
+extern const size_t d2tk_atom_body_fd_sz;
#if D2TK_VTERM
extern const size_t d2tk_atom_body_pty_sz;
extern const size_t d2tk_atom_body_lineedit_sz;