#include #include #include #include #include #include #include #include #include #include #include #include "virtual-keyboard-unstable-v1.h" #include "virtual-keyboard.h" #include "wayland.h" static struct zwp_virtual_keyboard_manager_v1 *g_virtual_keyboard_manager = NULL; struct _DiyaVirtualKeyboard { DiyaShellObject parent; struct zwp_virtual_keyboard_v1 *keyboard; }; G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA_TYPE_SHELL_OBJECT); static void diya_virtual_keyboard_dispose(GObject *object) { DiyaVirtualKeyboard *self = DIYA_VIRTUAL_KEYBOARD(object); g_debug("diya_virtual_keyboard_dispose"); if (self->keyboard) { zwp_virtual_keyboard_v1_destroy(self->keyboard); } G_OBJECT_CLASS(diya_virtual_keyboard_parent_class)->dispose(object); } static void diya_virtual_keyboard_init(DiyaVirtualKeyboard *self) { self->keyboard = NULL; } static const gchar *diya_virtual_keyboard_to_string(DiyaObject *object) { (void)object; return "Diya virtual keyboard instance"; } static void diya_virtual_keyboard_class_init(DiyaVirtualKeyboardClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); gobject_class->dispose = diya_virtual_keyboard_dispose; // gobject_class->set_property = diya_lock_session_set_property; // gobject_class->get_property = diya_lock_session_get_property; base_class->to_string = diya_virtual_keyboard_to_string; } /* static void randname(char *buf) { struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); long r = ts.tv_nsec; for (int i = 0; i < 6; ++i) { buf[i] = 'A' + (r & 15) + (r & 16) * 2; r >>= 5; } } */ static int create_keymap_fd(off_t size) { static const char name[] = "/diya-shell-keymap-XXXXXX"; const char *base; char *path; int fd; int ret; // randname(name + sizeof(name) - 7); base = getenv("XDG_RUNTIME_DIR"); if (!base) { errno = ENOENT; return -1; } path = malloc(strlen(base) + sizeof(name) + 1); if (!path) return -1; strcpy(path, base); strcat(path, name); g_debug("Create temp file for keymap: %s", path); fd = mkstemp(path); if (fd >= 0) { long flags; flags = fcntl(fd, F_GETFD); if (flags == -1) { g_critical("fcntl Unable to F_GETFD: %s", strerror(errno)); close(fd); fd = -1; } else if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { g_critical("fcntl Unable to F_SETFD(FD_CLOEXEC): %s", strerror(errno)); close(fd); fd = -1; } unlink(path); } else { g_critical("mkstemp Unable to create temp file %s: %s", path, strerror(errno)); } free(path); if (fd < 0) return -1; do { ret = ftruncate(fd, size); } while (ret < 0 && errno == EINTR); if (ret < 0) { close(fd); return -1; } return fd; } DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *keymap_file) { gchar *content = NULL; GError *error = NULL; GBytes *bytes = NULL; gsize len = 0; if (keymap_file) { g_file_get_contents(keymap_file, &content, &len, &error); if (error != NULL) { g_critical("diya_virtual_keyboard_new: Unable to read file %s: %s", keymap_file, error->message); g_error_free(error); return NULL; } } else { g_warning("No keymap file specified.Loading default keymap from resource"); GBytes *bytes = g_resources_lookup_data("/dev/iohub/diya/shell/default.keymap", 0, &error); if (error != NULL) { g_critical("Unable to read keymap file from resource %s", error->message); g_error_free(error); return NULL; } content = (gchar*)g_bytes_get_data(bytes, &len); } int fd = create_keymap_fd(len); if (fd == -1) { g_critical("diya_virtual_keyboard_new: create temp file"); if(bytes) { g_bytes_unref(bytes); content = NULL; } if(content) { g_free(content); } } void *ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == (void *)-1) { g_critical("diya_virtual_keyboard_new: error mmap: %s", strerror(errno)); close(fd); if(bytes) { g_bytes_unref(bytes); content = NULL; } if(content) { g_free(content); } } strcpy((char *)ptr, content); DiyaVirtualKeyboard *vkb = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD, "shell", shell, NULL); DiyaWayland *wayland = diya_shell_get_wayland(shell); struct wl_seat *seat = diya_wayland_get_seat(wayland); vkb->keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(g_virtual_keyboard_manager, seat); zwp_virtual_keyboard_v1_keymap(vkb->keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, len); return vkb; } void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell) { (void)shell; g_virtual_keyboard_manager = wl_registry_bind(registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1); } void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard *self, uint32_t key, diya_vkb_state_t state) { GDateTime *now = g_date_time_new_now_local(); uint32_t current_time_ms = g_date_time_get_microsecond(now) / 1000; g_date_time_unref(now); zwp_virtual_keyboard_v1_key(self->keyboard, current_time_ms, key, (uint32_t)state); }