220 lines
5.8 KiB
C
220 lines
5.8 KiB
C
#include <xkbcommon/xkbcommon.h>
|
|
#include <sys/socket.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <gio/gio.h>
|
|
#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);
|
|
} |