commit 6f2a50de8c62f625f84bef17a027a0f161425283
parent bc38196909d7b6186fffac43012b7f470104ec6c
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Tue, 15 Jun 2021 11:37:01 -0500
dialer: number entry works
Diffstat:
A | clients/dialer.c | | | 397 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 397 insertions(+), 0 deletions(-)
diff --git a/clients/dialer.c b/clients/dialer.c
@@ -0,0 +1,397 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wld/wayland.h>
+#include <wld/wld.h>
+#include <wayland-client.h>
+#include <xdg-shell-client-protocol.h>
+#include <text-input-unstable-v3-client-protocol.h>
+#include <atd.h>
+#include <encdec.h>
+
+#include "drw.h"
+#include "util.h"
+
+#define LENGTH(x) (sizeof x / sizeof x[0])
+#define STRINGTOKEYSYM(X) (XStringToxkb_keysym_t(X))
+#define TEXTW(X) (drw_fontset_getwidth(drw, (X)))
+
+enum {
+ SchemeNormal,
+ SchemeSetting,
+ SchemeSettingDown,
+ SchemeHangup,
+ SchemeHangupDown,
+ SchemeLast
+};
+
+enum button {
+ ButtonNone,
+ ButtonCall,
+ ButtonClear,
+};
+
+static const char *colors[SchemeLast][2] = {
+ /* fg bg */
+ [SchemeNormal] = { "#ffffff", "#2222cc" },
+ [SchemeSetting] = { "#ffffff", "#22cc22" },
+ [SchemeHangup] = { "#ffffff", "#cc2222" },
+ [SchemeSettingDown] = { "#ffffff", "#008800" },
+ [SchemeHangupDown] = { "#ffffff", "#880000" },
+};
+
+#include "config.h"
+
+static Clr* scheme[SchemeLast];
+
+struct {
+ struct wl_display *dpy;
+ struct wl_compositor *cmp;
+ struct wl_seat *seat;
+ struct wl_touch *touch;
+ struct wl_surface *surface;
+ struct xdg_wm_base *wm;
+ struct xdg_surface *xdgsurface;
+ struct xdg_toplevel *toplevel;
+ struct zwp_text_input_manager_v3 *timanager;
+ struct zwp_text_input_v3 *textinput;
+ char number[PHONE_NUMBER_MAX_LEN + 1];
+ struct {
+ char commitbuf[4000];
+ uint32_t delbefore;
+ uint32_t delafter;
+ } tipending;
+ uint32_t textserial;
+
+ Drw *drw;
+
+ int32_t w, h;
+} wl;
+
+unsigned int tw, th;
+enum button pressed, current;
+
+static void wmping(void *data, struct xdg_wm_base *wm, uint32_t serial);
+static void xdgsurfconfigure(void *data, struct xdg_surface *surf, uint32_t serial);
+static void toplevelconfigure(void *data, struct xdg_toplevel *toplevel, int32_t w, int32_t h, struct wl_array *states);
+static void toplevelclose(void *data, struct xdg_toplevel *toplevel);
+static void regglobal(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version);
+static void regglobalremove(void *data, struct wl_registry *registry, uint32_t name);
+static void draw(void);
+static void touchdown(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y);
+static void touchup(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id);
+static void touchmotion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y);
+static void touchframe(void *data, struct wl_touch *wl_touch);
+static void touchcancel(void *data, struct wl_touch *wl_touch);
+static void tienter(void *data, struct zwp_text_input_v3 *text_input, struct wl_surface *surface);
+static void tileave(void *data, struct zwp_text_input_v3 *text_input, struct wl_surface *surface);
+static void tipreedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, const char *text, int32_t cursor_begin, int32_t cursor_end);
+static void ticommit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, const char *text);
+static void tidelete_surrounding_text(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, uint32_t before_length, uint32_t after_length);
+static void tidone(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, uint32_t serial);
+
+
+static struct wl_registry_listener reglistener = { regglobal, regglobalremove };
+
+static struct xdg_wm_base_listener wmlistener = { wmping };
+static struct xdg_surface_listener xdgsurflistener = { xdgsurfconfigure };
+static struct xdg_toplevel_listener toplevellistener =
+ { toplevelconfigure, toplevelclose };
+static struct wl_touch_listener touchlistener =
+ { touchdown, touchup, touchmotion, touchframe, touchcancel };
+static struct zwp_text_input_v3_listener tilistener = {
+ .enter = tienter,
+ .leave = tileave,
+ .preedit_string = tipreedit_string,
+ .commit_string = ticommit_string,
+ .delete_surrounding_text = tidelete_surrounding_text,
+ .done = tidone
+};
+
+
+void
+wmping(void *data, struct xdg_wm_base *wm, uint32_t serial)
+{
+ xdg_wm_base_pong(wm, serial);
+}
+
+void
+xdgsurfconfigure(void *data, struct xdg_surface *surf, uint32_t serial)
+{
+ xdg_surface_ack_configure(surf, serial);
+}
+
+void
+toplevelconfigure(void *data, struct xdg_toplevel *toplevel, int32_t w, int32_t h,
+ struct wl_array *states)
+{
+ if (w == wl.w && h == wl.h)
+ return;
+ if (w == 0 && h == 0)
+ return;
+
+ wl.w = w;
+ wl.h = h;
+}
+
+void
+toplevelclose(void *data, struct xdg_toplevel *toplevel)
+{
+ exit(0);
+}
+
+void
+regglobal(void *data, struct wl_registry *registry, uint32_t name,
+ const char *interface, uint32_t version)
+{
+ if (strcmp(interface, "wl_compositor") == 0) {
+ wl.cmp = wl_registry_bind(registry, name,
+ &wl_compositor_interface, 3);
+ } else if (strcmp(interface, "xdg_wm_base") == 0) {
+ wl.wm = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
+ xdg_wm_base_add_listener(wl.wm, &wmlistener, NULL);
+ } else if (strcmp(interface, "wl_seat") == 0) {
+ wl.seat = wl_registry_bind(registry, name,
+ &wl_seat_interface, 4);
+ } else if (strcmp(interface, "zwp_text_input_manager_v3") == 0) {
+ wl.timanager = wl_registry_bind(registry, name, &zwp_text_input_manager_v3_interface, 1);
+ }
+}
+
+void
+regglobalremove(void *data, struct wl_registry *registry, uint32_t name)
+{
+}
+
+struct {
+ bool down;
+ uint32_t x, y;
+ int32_t id;
+} touchpoint;
+
+static enum button
+getpressed()
+{
+ if (touchpoint.x < wl.w / 2 && touchpoint.y > 3 * wl.h / 8 && touchpoint.y < wl.h / 2) {
+ return ButtonCall;
+ } else if (touchpoint.x > wl.w / 2 && touchpoint.y > 3 * wl.h / 8 && touchpoint.y < wl.h / 2) {
+ return ButtonClear;
+ }
+
+ return ButtonNone;
+}
+
+void
+touchdown(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
+{
+ if (touchpoint.down)
+ return;
+
+ touchpoint.down = true;
+ touchpoint.x = wl_fixed_to_int(x);
+ touchpoint.y = wl_fixed_to_int(y);
+ touchpoint.id = id;
+ current = pressed = getpressed();
+ draw();
+}
+
+int switchinput() {
+}
+
+void
+touchup(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id)
+{
+ if (touchpoint.id != id)
+ return;
+
+ touchpoint.down = false;
+
+ if (pressed == current) {
+ switch (pressed) {
+ case ButtonCall:
+ fprintf(stderr, "ButtonCall\n");
+ break;
+ case ButtonClear:
+ fprintf(stderr, "ButtonClear\n");
+ break;
+ }
+ }
+
+ current = pressed = ButtonNone;
+ draw();
+}
+
+void
+touchmotion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
+{
+ if (touchpoint.id != id)
+ return;
+
+ touchpoint.x = wl_fixed_to_int(x);
+ touchpoint.y = wl_fixed_to_int(y);
+ current = getpressed();
+ draw();
+}
+
+void
+touchframe(void *data, struct wl_touch *wl_touch)
+{
+}
+
+void touchcancel(void *data, struct wl_touch *wl_touch)
+{
+ touchpoint.down = false;
+}
+void
+tienter(void *data, struct zwp_text_input_v3 *text_input, struct wl_surface *surface)
+{
+ fprintf(stderr, "tienter\n");
+ zwp_text_input_v3_enable(text_input);
+ zwp_text_input_v3_set_content_type(text_input, ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE);
+ wl.textserial++;
+ zwp_text_input_v3_commit(text_input);
+}
+
+void
+tileave(void *data, struct zwp_text_input_v3 *text_input, struct wl_surface *surface)
+{
+ zwp_text_input_v3_disable(text_input);
+}
+
+void
+tipreedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, const char *text, int32_t cursor_begin, int32_t cursor_end)
+{
+}
+
+void
+ticommit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, const char *text)
+{
+ fprintf(stderr, "TICOMMIT_STRING\n");
+ strcpy(wl.tipending.commitbuf, text);
+}
+
+void
+tidelete_surrounding_text(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, uint32_t before_length, uint32_t after_length)
+{
+ wl.tipending.delbefore = before_length;
+ wl.tipending.delafter = after_length;
+}
+
+void
+tidone(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, uint32_t serial)
+{
+ fprintf(stderr, "TIDONE\n");
+ if (serial != wl.textserial)
+ return;
+
+ /* 2. Delete requested surrounding text */
+ size_t len = strlen(wl.number);
+ if (len > wl.tipending.delbefore)
+ wl.number[len - wl.tipending.delbefore] = 0;
+ else
+ wl.number[0] = 0;
+
+ /* 3. Insert commit string with the cursor at its end */
+ char *next = wl.tipending.commitbuf;
+ for (int i = 0; i < PHONE_NUMBER_MAX_LEN - len && *next != '\0'; i++, next++) {
+ /* we only accept characters that are valid in a phone number */
+ if (strchr(DIALING_DIGITS, *next) != NULL) {
+ wl.number[len+i] = *next;
+ wl.number[len+i+1] = '\0';
+ }
+ }
+
+ fprintf(stderr, "number: %s\n", wl.number);
+
+ zwp_text_input_v3_commit(wl.textinput);
+ wl.textserial++;
+ wl.tipending.delbefore = 0;
+ wl.tipending.delafter = 0;
+ wl.tipending.commitbuf[0] = 0;
+
+ draw();
+}
+
+void
+draw()
+{
+ int height = wl.h / 8;
+ wld_set_target_surface(wl.drw->renderer, wl.drw->surface);
+
+ drw_setscheme(wl.drw, scheme[SchemeNormal]);
+ drw_rect(wl.drw, 0, 0, wl.w, wl.h - height, 1, 1);
+ drw_setfontset(wl.drw, &wl.drw->fonts[0]);
+ drw_font_getexts(&wl.drw->fonts[0], wl.number, strlen(wl.number), &tw, &th);
+ drw_text(wl.drw, wl.w / 2 - tw / 2, height, tw, th, 0, wl.number, 0);
+
+ drw_map(wl.drw, wl.surface, 0, 0, wl.w, wl.h);
+}
+
+void
+wlinit(void)
+{
+ struct wl_registry *registry;
+ int j;
+
+ wl.w = wl.h = 500;
+
+ if (!(wl.dpy = wl_display_connect(NULL)))
+ die("Can't open display\n");
+
+ registry = wl_display_get_registry(wl.dpy);
+ wl_registry_add_listener(registry, ®listener, NULL);
+
+ wl_display_roundtrip(wl.dpy);
+
+ wl.drw = drw_create(wl.dpy);
+
+ if (!wl.seat)
+ die("Display has no seat\n");
+ if (!wl.wm)
+ die("Display has no window manager\n");
+ if (!wl.timanager)
+ die("Display has no text input manager\n");
+
+ if (!drw_fontset_create(wl.drw, (const char **) fonts, LENGTH(fonts)))
+ die("no fonts could be loaded");
+
+ wl.touch = wl_seat_get_touch(wl.seat);
+ wl_touch_add_listener(wl.touch, &touchlistener, NULL);
+ wl.textinput = zwp_text_input_manager_v3_get_text_input(wl.timanager, wl.seat);
+ zwp_text_input_v3_add_listener(wl.textinput, &tilistener, NULL);
+
+ wl_display_roundtrip(wl.dpy);
+
+ if (!wl.touch)
+ die("seat has no touch support\n");
+
+ /* init appearance */
+ for (j = 0; j < SchemeLast; j++)
+ scheme[j] = drw_scm_create(wl.drw, (const char **) colors[j], 2);
+
+ wl.surface = wl_compositor_create_surface(wl.cmp);
+ wl.xdgsurface = xdg_wm_base_get_xdg_surface(wl.wm, wl.surface);
+ xdg_surface_add_listener(wl.xdgsurface, &xdgsurflistener, NULL);
+ wl.toplevel = xdg_surface_get_toplevel(wl.xdgsurface);
+ xdg_toplevel_add_listener(wl.toplevel, &toplevellistener, NULL);
+ xdg_toplevel_set_app_id(wl.toplevel, "answer");
+
+ wl_display_roundtrip(wl.dpy);
+
+ if (wl.w == 0 || wl.h == 0) {
+ die("window has 0 dimension\n");
+ }
+
+ drw_resize(wl.drw, wl.surface, wl.w, wl.h);
+ draw();
+}
+
+int
+main(int argc, char *argv[])
+{
+ wlinit();
+ while (wl_display_dispatch(wl.dpy) != -1);
+ return 0;
+}