Load keyboard key caps from key map
This commit is contained in:
parent
8020954fed
commit
24f47dfd7f
13
meson.build
13
meson.build
@ -52,11 +52,16 @@ endforeach
|
||||
|
||||
gnome=import('gnome')
|
||||
|
||||
incdir = include_directories([
|
||||
'src'
|
||||
])
|
||||
|
||||
base = [
|
||||
'src/base.c',
|
||||
'src/shell.c',
|
||||
'src/wayland.c',
|
||||
'src/virtual-keyboard.c',
|
||||
'src/vkb/virtual-keyboard.c',
|
||||
'src/vkb/virtual-keyboard-widgets.c',
|
||||
wayland_targets
|
||||
]
|
||||
|
||||
@ -77,7 +82,8 @@ executable(
|
||||
'diya-shell',
|
||||
dm_src,
|
||||
session_resource,
|
||||
dependencies: buil_dep)
|
||||
dependencies: buil_dep,
|
||||
include_directories : incdir)
|
||||
|
||||
login_src = [
|
||||
base,
|
||||
@ -91,4 +97,5 @@ executable(
|
||||
'diya-login-shell',
|
||||
login_src,
|
||||
login_resource,
|
||||
dependencies: buil_dep)
|
||||
dependencies: buil_dep,
|
||||
include_directories : incdir)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,9 @@
|
||||
@import url("resource:///dev/iohub/diya/shell/virtual-keyboard.css");
|
||||
/*
|
||||
* {
|
||||
font-family:DejaVuSans;
|
||||
}
|
||||
*/
|
||||
|
||||
.diya-login-header {
|
||||
font-size: 16px;
|
||||
|
7
resources/tpl.keymap
Normal file
7
resources/tpl.keymap
Normal file
@ -0,0 +1,7 @@
|
||||
xkb_keymap {
|
||||
xkb_keycodes { include "evdev+aliases(azerty)" };
|
||||
xkb_types { include "complete" };
|
||||
xkb_compat { include "complete" };
|
||||
xkb_symbols { include "pc+fr+inet(evdev)" };
|
||||
xkb_geometry { include "pc(pc105)" };
|
||||
};
|
@ -8,7 +8,7 @@
|
||||
background-color: white;
|
||||
border: 1px solid #CDC7C2;
|
||||
border-radius: 3px;
|
||||
min-width: 20px;
|
||||
min-width: 30px;
|
||||
/*min-height: 30px;*/
|
||||
}
|
||||
|
||||
@ -19,20 +19,22 @@
|
||||
/*
|
||||
.diya-vkb-btn label {
|
||||
border: 1px solid #b81f2b;
|
||||
|
||||
}*/
|
||||
|
||||
.diya-vkb-btn-level-1 {
|
||||
color: black;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.diya-vkb-btn-level-2 {
|
||||
color: gray;
|
||||
font-size: 10px;
|
||||
font-size: 9px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.diya-vkb-btn-level-3 {
|
||||
color: gray;
|
||||
font-size: 10px;
|
||||
font-size: 9px;
|
||||
padding-right: 3px;
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "login-shell.h"
|
||||
#include "virtual-keyboard.h"
|
||||
#include "vkb/virtual-keyboard-widgets.h"
|
||||
|
||||
#define DBUS_SERVER_NAME "dev.iohub.diya.SessionManager"
|
||||
#define DBUS_SERVER_PATH "/dev/iohub/diya/SessionManager"
|
||||
@ -17,8 +17,8 @@ struct _DiyaLoginShell
|
||||
GtkWidget *password;
|
||||
GtkWidget *status;
|
||||
guint bus_watch_id;
|
||||
//GtkWindow *window;
|
||||
GList * windows;
|
||||
// GtkWindow *window;
|
||||
GList *windows;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA_TYPE_SHELL);
|
||||
@ -35,13 +35,13 @@ static void diya_login_shell_dispose(GObject *object)
|
||||
}
|
||||
g_object_unref(self->lock);
|
||||
}
|
||||
if(self->windows)
|
||||
if (self->windows)
|
||||
{
|
||||
// destroyed all windows and free list
|
||||
GList * it = NULL;
|
||||
for(it = self->windows; it; it = it->next)
|
||||
GList *it = NULL;
|
||||
for (it = self->windows; it; it = it->next)
|
||||
{
|
||||
if(it->data)
|
||||
if (it->data)
|
||||
{
|
||||
gtk_window_destroy(GTK_WINDOW(it->data));
|
||||
}
|
||||
@ -66,7 +66,6 @@ static void diya_login_shell_init(DiyaLoginShell *self)
|
||||
self->bus_watch_id = 0;
|
||||
}
|
||||
|
||||
|
||||
static void on_method_call_return(GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
(void)source_object;
|
||||
@ -102,7 +101,7 @@ static void on_method_call_return(GObject *source_object, GAsyncResult *res, gpo
|
||||
gtk_label_set_text(GTK_LABEL(self->status), "Login failed! Please try again.");
|
||||
}
|
||||
g_variant_unref(result);
|
||||
//g_object_unref(reply);
|
||||
// g_object_unref(reply);
|
||||
}
|
||||
|
||||
static void on_name_appeared(GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data)
|
||||
@ -123,7 +122,7 @@ static void on_name_appeared(GDBusConnection *connection, const gchar *name, con
|
||||
g_dbus_message_set_body(request, g_variant_new("(ss)", username, password));
|
||||
g_dbus_connection_send_message_with_reply(connection, request, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, on_method_call_return, self);
|
||||
g_object_unref(request);
|
||||
g_bus_unwatch_name (self->bus_watch_id);
|
||||
g_bus_unwatch_name(self->bus_watch_id);
|
||||
self->bus_watch_id = 0;
|
||||
}
|
||||
|
||||
@ -168,25 +167,22 @@ static void do_login(GtkButton *button, DiyaLoginShell *self)
|
||||
|
||||
static void open_vkb(GtkButton *button, DiyaLoginShell *self)
|
||||
{
|
||||
(void) button;
|
||||
DiyaVirtualKeyboard* vkb = diya_virtual_keyboard_new(DIYA_SHELL(self), NULL);
|
||||
if(!vkb)
|
||||
(void)button;
|
||||
DiyaVirtualKeyboard *vkb = diya_shell_get_virtual_keyboard(DIYA_SHELL(self));
|
||||
if (!vkb)
|
||||
{
|
||||
return;
|
||||
}
|
||||
g_warning("Sending A to: %s", diya_object_to_string(DIYA_OBJECT(vkb)));
|
||||
diya_virtual_keyboard_send_key(vkb,30, VKB_KEY_STATE_PRESSED);
|
||||
diya_virtual_keyboard_send_key(vkb, 30, VKB_KEY_STATE_PRESSED);
|
||||
g_usleep(10000);
|
||||
diya_virtual_keyboard_send_key(vkb,30, VKB_KEY_STATE_RELEASED);
|
||||
diya_virtual_keyboard_send_key(vkb, 30, VKB_KEY_STATE_RELEASED);
|
||||
g_usleep(10000);
|
||||
// send example key
|
||||
g_object_unref(vkb);
|
||||
}
|
||||
|
||||
|
||||
static void add_new_monitor(DiyaLoginShell* self, GdkMonitor* monitor, gint position)
|
||||
static void add_new_monitor(DiyaLoginShell *self, GdkMonitor *monitor, gint position)
|
||||
{
|
||||
GtkWindow* window = GTK_WINDOW(gtk_application_window_new(diya_shell_get_application(DIYA_SHELL(self))));
|
||||
GtkWindow *window = GTK_WINDOW(gtk_application_window_new(diya_shell_get_application(DIYA_SHELL(self))));
|
||||
gtk_session_lock_instance_assign_window_to_monitor(self->lock, window, monitor);
|
||||
|
||||
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
@ -231,7 +227,7 @@ static void add_new_monitor(DiyaLoginShell* self, GdkMonitor* monitor, gint posi
|
||||
|
||||
GtkWidget *button = gtk_button_new_with_label("Login");
|
||||
g_signal_connect(button, "clicked", G_CALLBACK(do_login), self);
|
||||
//gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
||||
// gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
||||
gtk_box_append(GTK_BOX(box), button);
|
||||
|
||||
// Not displayed, but allows testing that creating popups doesn't crash GTK
|
||||
@ -246,46 +242,45 @@ static void add_new_monitor(DiyaLoginShell* self, GdkMonitor* monitor, gint posi
|
||||
gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
||||
gtk_box_append(GTK_BOX(box), button);
|
||||
|
||||
DiyaVirtualKeyboardWidget* vkb_widget = diya_virtual_keyboard_widget_new();
|
||||
DiyaVirtualKeyboardWidget *vkb_widget = diya_virtual_keyboard_widget_new(diya_shell_get_virtual_keyboard(DIYA_SHELL(self)));
|
||||
gtk_box_append(GTK_BOX(box), GTK_WIDGET(vkb_widget));
|
||||
|
||||
gtk_window_set_child(GTK_WINDOW(window), box);
|
||||
|
||||
gtk_window_present(window);
|
||||
|
||||
self->windows = g_list_insert(self->windows,window, position);
|
||||
self->windows = g_list_insert(self->windows, window, position);
|
||||
}
|
||||
|
||||
static void on_monitor_changed(GListModel* monitor_lists,guint position, guint removed,guint added, gpointer object)
|
||||
static void on_monitor_changed(GListModel *monitor_lists, guint position, guint removed, guint added, gpointer object)
|
||||
{
|
||||
g_debug("Monitor list changed at %d: added %d, removed %d", position, added, removed);
|
||||
DiyaLoginShell* self = DIYA_LOGIN_SHELL(object);
|
||||
if(removed > 0)
|
||||
DiyaLoginShell *self = DIYA_LOGIN_SHELL(object);
|
||||
if (removed > 0)
|
||||
{
|
||||
for (guint i = 0; i < removed; i++)
|
||||
{
|
||||
GtkWindow* win = GTK_WINDOW(g_list_nth(self->windows, position));
|
||||
if(win)
|
||||
GtkWindow *win = GTK_WINDOW(g_list_nth(self->windows, position));
|
||||
if (win)
|
||||
{
|
||||
gtk_window_destroy(win);
|
||||
self->windows = g_list_remove(self->windows, win);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(added > 0)
|
||||
if (added > 0)
|
||||
{
|
||||
for (guint i = 0; i < added; i++)
|
||||
{
|
||||
GdkMonitor * monitor = g_list_model_get_item(monitor_lists,position + i);
|
||||
GdkMonitor *monitor = g_list_model_get_item(monitor_lists, position + i);
|
||||
add_new_monitor(self, monitor, position + i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_login_shell_startup(DiyaShell* shell)
|
||||
static void diya_login_shell_startup(DiyaShell *shell)
|
||||
{
|
||||
DiyaLoginShell* self = DIYA_LOGIN_SHELL(shell);
|
||||
DiyaLoginShell *self = DIYA_LOGIN_SHELL(shell);
|
||||
if (!gtk_session_lock_instance_lock(self->lock))
|
||||
{
|
||||
g_error("gtk_session_lock_instance_lock: Unable to lock the display");
|
||||
@ -312,10 +307,10 @@ static void diya_login_shell_startup(DiyaShell* shell)
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
g_bytes_unref(bytes);
|
||||
}
|
||||
GListModel * list = gdk_display_get_monitors(gdk_display_get_default());
|
||||
for(guint i = 0; i < g_list_model_get_n_items(list); i++)
|
||||
GListModel *list = gdk_display_get_monitors(gdk_display_get_default());
|
||||
for (guint i = 0; i < g_list_model_get_n_items(list); i++)
|
||||
{
|
||||
GdkMonitor * monitor = g_list_model_get_item(list,i);
|
||||
GdkMonitor *monitor = g_list_model_get_item(list, i);
|
||||
add_new_monitor(self, monitor, -1);
|
||||
}
|
||||
}
|
||||
@ -330,6 +325,5 @@ static void diya_login_shell_class_init(DiyaLoginShellClass *class)
|
||||
DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class);
|
||||
base_shell_class->monitor_changed_handle = on_monitor_changed;
|
||||
base_shell_class->startup_handle = diya_login_shell_startup;
|
||||
//base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
|
||||
|
||||
// base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
|
||||
}
|
17
src/shell.c
17
src/shell.c
@ -1,7 +1,7 @@
|
||||
#include <glib-unix.h>
|
||||
#include "shell.h"
|
||||
#include "wayland.h"
|
||||
#include "virtual-keyboard.h"
|
||||
#include "vkb/virtual-keyboard.h"
|
||||
enum
|
||||
{
|
||||
NO_PROP,
|
||||
@ -41,6 +41,10 @@ static void diya_shell_dispose(GObject* object)
|
||||
g_free(priv->name);
|
||||
priv->name = NULL;
|
||||
}
|
||||
if(priv->vkb)
|
||||
{
|
||||
g_object_unref(priv->vkb);
|
||||
}
|
||||
G_OBJECT_CLASS(diya_shell_parent_class)->dispose(object);
|
||||
if (priv->app)
|
||||
{
|
||||
@ -147,6 +151,7 @@ static void diya_shell_init(DiyaShell *self)
|
||||
priv->wayland = NULL;
|
||||
priv->app = NULL;
|
||||
priv->name = NULL;
|
||||
priv->vkb = NULL;
|
||||
}
|
||||
|
||||
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell)
|
||||
@ -197,6 +202,16 @@ static void diya_shell_class_init(DiyaShellClass *class)
|
||||
g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties);
|
||||
}
|
||||
|
||||
DiyaVirtualKeyboard* diya_shell_get_virtual_keyboard(DiyaShell* self)
|
||||
{
|
||||
DiyaShellPrivate* priv = diya_shell_get_instance_private(self);
|
||||
if(!priv->vkb)
|
||||
{
|
||||
priv->vkb = diya_virtual_keyboard_new(self, "/home/diya/tpl.keymap");
|
||||
}
|
||||
return priv->vkb;
|
||||
}
|
||||
|
||||
int diya_shell_run(DiyaShell* shell, int argc, char **argv)
|
||||
{
|
||||
DiyaShellPrivate* priv = diya_shell_get_instance_private(shell);
|
||||
|
@ -11,6 +11,9 @@ G_DECLARE_DERIVABLE_TYPE(DiyaShell, diya_shell, DIYA, SHELL, DiyaObject)
|
||||
#define DIYA_TYPE_WAYLAND (diya_wayland_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaWayland, diya_wayland, DIYA, WAYLAND, DiyaShellObject)
|
||||
|
||||
#define DIYA_TYPE_VIRTUAL_KEYBOARD (diya_virtual_keyboard_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA, VIRTUAL_KEYBOARD, DiyaShellObject)
|
||||
|
||||
struct wl_registry;
|
||||
|
||||
typedef void (*wl_protocol_manager_register_t)(struct wl_registry*, uint32_t,DiyaShell*);
|
||||
@ -29,5 +32,7 @@ DiyaWayland * diya_shell_get_wayland(DiyaShell* shell);
|
||||
GtkApplication* diya_shell_get_application(DiyaShell* shell);
|
||||
const char* diya_shell_get_name(DiyaShell* shell);
|
||||
|
||||
DiyaVirtualKeyboard* diya_shell_get_virtual_keyboard(DiyaShell* shell);
|
||||
|
||||
int diya_shell_run(DiyaShell* shell, int argc, char **argv);
|
||||
#endif
|
@ -1,443 +0,0 @@
|
||||
#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"
|
||||
|
||||
/**
|
||||
* @brief DiyaVkbButton: virtual keyboard button
|
||||
*/
|
||||
|
||||
struct _DiyaVkbButton
|
||||
{
|
||||
GtkWidget super;
|
||||
GtkWidget *labels[3];
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVkbButton, diya_vkb_button, GTK_TYPE_WIDGET);
|
||||
|
||||
static void diya_vkb_button_dispose(GObject *object)
|
||||
{
|
||||
DiyaVkbButton *self = DIYA_VKB_BUTTON(object);
|
||||
g_debug("diya_vkb_button_dispose");
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
g_clear_pointer(&self->labels[i], gtk_widget_unparent);
|
||||
}
|
||||
// g_clear_pointer (&demo->label, gtk_widget_unparent);
|
||||
G_OBJECT_CLASS(diya_vkb_button_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_vkb_button_init(DiyaVkbButton *self)
|
||||
{
|
||||
gchar class_name[32]; /*diya-vkb-btn-level-%d */
|
||||
GtkLayoutManager *grid_layout;
|
||||
grid_layout = gtk_widget_get_layout_manager(GTK_WIDGET(self));
|
||||
//gtk_orientable_set_orientation(GTK_ORIENTABLE(box_layout), GTK_ORIENTATION_VERTICAL);
|
||||
// gtk_box_layout_set_spacing (GTK_BOX_LAYOUT (box_layout), 3);
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self),"diya-vkb-btn");
|
||||
gtk_widget_set_can_focus(GTK_WIDGET(self), false);
|
||||
// init labels
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
self->labels[i] = gtk_label_new(i==0?"X":"x");
|
||||
g_snprintf(class_name, sizeof(class_name),"diya-vkb-btn-level-%d",i + 1);
|
||||
gtk_widget_add_css_class(self->labels[i], class_name);
|
||||
gtk_widget_set_hexpand(self->labels[i], true);
|
||||
|
||||
gtk_widget_set_parent(self->labels[i], GTK_WIDGET(self));
|
||||
|
||||
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(grid_layout,self->labels[i]));
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
/* code */
|
||||
gtk_grid_layout_child_set_row(grid_child,0);
|
||||
gtk_grid_layout_child_set_column(grid_child,0);
|
||||
gtk_grid_layout_child_set_column_span (grid_child,2);
|
||||
break;
|
||||
case 1:
|
||||
gtk_grid_layout_child_set_row(grid_child,1);
|
||||
gtk_grid_layout_child_set_column(grid_child,0);
|
||||
gtk_widget_set_halign(self->labels[i],GTK_ALIGN_START);
|
||||
break;
|
||||
case 2:
|
||||
gtk_grid_layout_child_set_row(grid_child,1);
|
||||
gtk_grid_layout_child_set_column(grid_child,1);
|
||||
gtk_widget_set_halign(self->labels[i],GTK_ALIGN_END);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void diya_vkb_button_class_init(DiyaVkbButtonClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
gobject_class->dispose = diya_vkb_button_dispose;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type(GTK_WIDGET_CLASS(class), GTK_TYPE_GRID_LAYOUT);
|
||||
}
|
||||
|
||||
DiyaVkbButton* diya_vkb_button_new(/**with prameter */)
|
||||
{
|
||||
return DIYA_VKB_BUTTON(g_object_new(DIYA_TYPE_VKB_BUTTON, NULL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief DiyaVirtualKeyboardWidget: Virtual keyboard GTK widget
|
||||
*
|
||||
*/
|
||||
|
||||
#define VKB_N_CELLS 145
|
||||
#define VKB_ROW_NUM(i) (i/29)
|
||||
#define VKB_COL_NUM(i) (i % 29)
|
||||
|
||||
struct _DiyaVirtualKeyboardWidget
|
||||
{
|
||||
GtkWidget super;
|
||||
/**
|
||||
* row 0: 00 - 13
|
||||
* row 1: 14 - 27
|
||||
* row 2: 28 - 40
|
||||
* row 3: 41 - 53
|
||||
* row 4: 54 - 62
|
||||
*/
|
||||
GList *buttons;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboardWidget, diya_virtual_keyboard_widget, GTK_TYPE_WIDGET);
|
||||
|
||||
static void diya_virtual_keyboard_widget_dispose(GObject *object)
|
||||
{
|
||||
DiyaVirtualKeyboardWidget *self = DIYA_VIRTUAL_KEYBOARD_WIDGET(object);
|
||||
g_debug("diya_virtual_keyboard_widget_dispose");
|
||||
if(self->buttons)
|
||||
{
|
||||
GList * it = NULL;
|
||||
for(it = self->buttons; it; it = it->next)
|
||||
{
|
||||
if(it->data)
|
||||
{
|
||||
g_clear_pointer(&it->data, gtk_widget_unparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
// g_clear_pointer (&demo->label, gtk_widget_unparent);
|
||||
G_OBJECT_CLASS(diya_virtual_keyboard_widget_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_virtual_keyboard_widget_init(DiyaVirtualKeyboardWidget *self)
|
||||
{
|
||||
// gtk_widget_set_size_request(GTK_WIDGET(self), 600, 400);
|
||||
g_debug("diya_virtual_keyboard_widget_init: Create new widget");
|
||||
GtkLayoutManager *grid_layout;
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self),"diya-vkb");
|
||||
grid_layout = gtk_widget_get_layout_manager(GTK_WIDGET(self));
|
||||
// gtk_orientable_set_orientation(GTK_ORIENTABLE(grid_layout), GTK_ORIENTATION_VERTICAL);
|
||||
gtk_grid_layout_set_row_spacing(GTK_GRID_LAYOUT(grid_layout), 2);
|
||||
gtk_grid_layout_set_column_spacing(GTK_GRID_LAYOUT(grid_layout), 2);
|
||||
//gtk_grid_layout_set_baseline_row(GTK_GRID_LAYOUT(grid_layout), 4);
|
||||
// init buttons
|
||||
for (int i = 0; i < VKB_N_CELLS; i++)
|
||||
{
|
||||
gboolean skip = false;
|
||||
int row = VKB_ROW_NUM(i);
|
||||
int col = VKB_COL_NUM(i);
|
||||
switch (row)
|
||||
{
|
||||
case 0:
|
||||
skip = (col %2 != 0) || (col > 26);
|
||||
break;
|
||||
case 1:
|
||||
skip = (col == 1) || (col == 2) || (col != 0 && col % 2 == 0);
|
||||
break;
|
||||
case 2:
|
||||
skip = (col == 1) || (col == 2) || (col != 0 && col%2 == 0) || (col > 25);
|
||||
break;
|
||||
case 3:
|
||||
skip = (col > 0 && col < 5) || (col != 0 && col % 2 == 0);
|
||||
break;
|
||||
case 4:
|
||||
skip = (col > 0 && col < 3) || (col == 4) || (col==6) || (col>7 && col < 19) || (col > 19 && col %2 == 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(skip)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GtkWidget* button = GTK_WIDGET(diya_vkb_button_new());
|
||||
self->buttons = g_list_append(self->buttons, button);
|
||||
gtk_widget_set_parent(button, GTK_WIDGET(self));
|
||||
gtk_widget_set_hexpand(button, true);
|
||||
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(grid_layout,button));
|
||||
|
||||
gtk_grid_layout_child_set_row(grid_child,row);
|
||||
gtk_grid_layout_child_set_column(grid_child,col);
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 26:
|
||||
case 29:
|
||||
case 58:
|
||||
case 116:
|
||||
gtk_grid_layout_child_set_column_span (grid_child,3);
|
||||
break;
|
||||
|
||||
case 83:
|
||||
gtk_grid_layout_child_set_column_span (grid_child,4);
|
||||
break;
|
||||
case 87:
|
||||
gtk_grid_layout_child_set_column_span (grid_child,5);
|
||||
break;
|
||||
case 123:
|
||||
gtk_grid_layout_child_set_column_span (grid_child,12);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(i > 0)
|
||||
gtk_grid_layout_child_set_column_span (grid_child,2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_virtual_keyboard_widget_class_init(DiyaVirtualKeyboardWidgetClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
gobject_class->dispose = diya_virtual_keyboard_widget_dispose;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type(GTK_WIDGET_CLASS(class), GTK_TYPE_GRID_LAYOUT);
|
||||
}
|
||||
|
||||
DiyaVirtualKeyboardWidget *diya_virtual_keyboard_widget_new()
|
||||
{
|
||||
DiyaVirtualKeyboardWidget *vkb_widget = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD_WIDGET, NULL);
|
||||
return vkb_widget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DiyaVirtualKeyboard class: lowlevel wayland virtual keyboard handle
|
||||
*
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
g_debug("Using default keymap configuration: \n%s", content);
|
||||
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);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef DIYA_VIRTUAL_KEYBOARD_H
|
||||
#define DIYA_VIRTUAL_KEYBOARD_H
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VKB_KEY_STATE_RELEASED = 0 /*WL_KEYBOARD_KEY_STATE_RELEASED*/,
|
||||
VKB_KEY_STATE_PRESSED = 1 /*WL_KEYBOARD_KEY_STATE_PRESSED*/,
|
||||
} diya_vkb_state_t;
|
||||
|
||||
#define DIYA_TYPE_VIRTUAL_KEYBOARD (diya_virtual_keyboard_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA, VIRTUAL_KEYBOARD, DiyaShellObject)
|
||||
|
||||
DiyaVirtualKeyboard* diya_virtual_keyboard_new(DiyaShell* shell, const gchar* keymap_file);
|
||||
|
||||
void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell);
|
||||
void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard* vkb, uint32_t key, diya_vkb_state_t state);
|
||||
|
||||
#define DIYA_TYPE_VIRTUAL_KEYBOARD_WIDGET (diya_virtual_keyboard_widget_get_type())
|
||||
G_DECLARE_FINAL_TYPE (DiyaVirtualKeyboardWidget, diya_virtual_keyboard_widget, DIYA, VIRTUAL_KEYBOARD_WIDGET, GtkWidget)
|
||||
|
||||
DiyaVirtualKeyboardWidget* diya_virtual_keyboard_widget_new();
|
||||
|
||||
|
||||
#define DIYA_TYPE_VKB_BUTTON (diya_vkb_button_get_type())
|
||||
G_DECLARE_FINAL_TYPE (DiyaVkbButton, diya_vkb_button, DIYA, VKB_BUTTON, GtkWidget)
|
||||
|
||||
DiyaVkbButton* diya_vkb_button_new(/**with prameter */);
|
||||
|
||||
#endif
|
253
src/vkb/virtual-keyboard-widgets.c
Normal file
253
src/vkb/virtual-keyboard-widgets.c
Normal file
@ -0,0 +1,253 @@
|
||||
#include "virtual-keyboard-widgets.h"
|
||||
|
||||
/**
|
||||
* @brief DiyaVkbButton: virtual keyboard button
|
||||
*/
|
||||
|
||||
struct _DiyaVkbButton
|
||||
{
|
||||
GtkWidget super;
|
||||
GtkWidget *labels[3];
|
||||
DiyaVkbKey *key;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVkbButton, diya_vkb_button, GTK_TYPE_WIDGET);
|
||||
|
||||
static void diya_vkb_button_dispose(GObject *object)
|
||||
{
|
||||
DiyaVkbButton *self = DIYA_VKB_BUTTON(object);
|
||||
g_debug("diya_vkb_button_dispose");
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
g_clear_pointer(&self->labels[i], gtk_widget_unparent);
|
||||
}
|
||||
if (self->key)
|
||||
{
|
||||
g_object_unref(self->key);
|
||||
self->key = NULL;
|
||||
}
|
||||
// g_clear_pointer (&demo->label, gtk_widget_unparent);
|
||||
G_OBJECT_CLASS(diya_vkb_button_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_vkb_button_init(DiyaVkbButton *self)
|
||||
{
|
||||
gchar class_name[32]; /*diya-vkb-btn-level-%d */
|
||||
GtkLayoutManager *grid_layout;
|
||||
self->key = NULL;
|
||||
grid_layout = gtk_widget_get_layout_manager(GTK_WIDGET(self));
|
||||
// gtk_orientable_set_orientation(GTK_ORIENTABLE(box_layout), GTK_ORIENTATION_VERTICAL);
|
||||
// gtk_box_layout_set_spacing (GTK_BOX_LAYOUT (box_layout), 3);
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self), "diya-vkb-btn");
|
||||
gtk_widget_set_can_focus(GTK_WIDGET(self), false);
|
||||
// init labels
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
self->labels[i] = gtk_label_new(NULL);
|
||||
g_snprintf(class_name, sizeof(class_name), "diya-vkb-btn-level-%d", i + 1);
|
||||
gtk_widget_add_css_class(self->labels[i], class_name);
|
||||
gtk_widget_set_hexpand(self->labels[i], true);
|
||||
|
||||
gtk_widget_set_parent(self->labels[i], GTK_WIDGET(self));
|
||||
|
||||
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(grid_layout, self->labels[i]));
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
/* code */
|
||||
gtk_grid_layout_child_set_row(grid_child, 0);
|
||||
gtk_grid_layout_child_set_column(grid_child, 0);
|
||||
gtk_grid_layout_child_set_column_span(grid_child, 2);
|
||||
break;
|
||||
case 1:
|
||||
gtk_grid_layout_child_set_row(grid_child, 1);
|
||||
gtk_grid_layout_child_set_column(grid_child, 0);
|
||||
gtk_widget_set_halign(self->labels[i], GTK_ALIGN_START);
|
||||
break;
|
||||
case 2:
|
||||
gtk_grid_layout_child_set_row(grid_child, 1);
|
||||
gtk_grid_layout_child_set_column(grid_child, 1);
|
||||
gtk_widget_set_halign(self->labels[i], GTK_ALIGN_END);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_vkb_button_class_init(DiyaVkbButtonClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
gobject_class->dispose = diya_vkb_button_dispose;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type(GTK_WIDGET_CLASS(class), GTK_TYPE_GRID_LAYOUT);
|
||||
}
|
||||
|
||||
DiyaVkbButton *diya_vkb_button_new(DiyaVkbKey *key)
|
||||
{
|
||||
DiyaVkbButton *btn = DIYA_VKB_BUTTON(g_object_new(DIYA_TYPE_VKB_BUTTON, NULL));
|
||||
btn->key = key;
|
||||
for (uint32_t i = 0; i < 3; i++)
|
||||
{
|
||||
const char *cap = diya_vkb_key_get_keycap(key, i);
|
||||
if (cap)
|
||||
{
|
||||
if(i == 1 && diya_vkb_key_is_alphabet(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
gtk_label_set_text(GTK_LABEL(btn->labels[i]), cap);
|
||||
}
|
||||
}
|
||||
return btn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DiyaVirtualKeyboardWidget: Virtual keyboard GTK widget
|
||||
*
|
||||
*/
|
||||
|
||||
#define VKB_N_CELLS 145
|
||||
#define VKB_ROW_NUM(i) (i / 29)
|
||||
#define VKB_COL_NUM(i) (i % 29)
|
||||
|
||||
static uint32_t g_vkb_layout[] = {
|
||||
49, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 51,
|
||||
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 36,
|
||||
50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 111, 66,
|
||||
9, 206, 64, 65, 0, 108, 113, 116, 114};
|
||||
|
||||
struct _DiyaVirtualKeyboardWidget
|
||||
{
|
||||
GtkWidget super;
|
||||
/**
|
||||
* row 0: 00 - 13
|
||||
* row 1: 14 - 27
|
||||
* row 2: 28 - 40
|
||||
* row 3: 41 - 53
|
||||
* row 4: 54 - 62
|
||||
*/
|
||||
GList *buttons;
|
||||
DiyaVirtualKeyboard *vkb;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboardWidget, diya_virtual_keyboard_widget, GTK_TYPE_WIDGET);
|
||||
|
||||
static void diya_virtual_keyboard_widget_dispose(GObject *object)
|
||||
{
|
||||
DiyaVirtualKeyboardWidget *self = DIYA_VIRTUAL_KEYBOARD_WIDGET(object);
|
||||
g_debug("diya_virtual_keyboard_widget_dispose");
|
||||
if (self->buttons)
|
||||
{
|
||||
GList *it = NULL;
|
||||
for (it = self->buttons; it; it = it->next)
|
||||
{
|
||||
if (it->data)
|
||||
{
|
||||
g_clear_pointer(&it->data, gtk_widget_unparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
// g_clear_pointer (&demo->label, gtk_widget_unparent);
|
||||
G_OBJECT_CLASS(diya_virtual_keyboard_widget_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_virtual_keyboard_widget_init(DiyaVirtualKeyboardWidget *self)
|
||||
{
|
||||
//gtk_widget_set_size_request(GTK_WIDGET(self), 600, 400);
|
||||
g_debug("diya_virtual_keyboard_widget_init: Create new widget");
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self), "diya-vkb");
|
||||
GtkLayoutManager *grid_layout = gtk_widget_get_layout_manager(GTK_WIDGET(self));
|
||||
// gtk_orientable_set_orientation(GTK_ORIENTABLE(grid_layout), GTK_ORIENTATION_VERTICAL);
|
||||
gtk_grid_layout_set_row_spacing(GTK_GRID_LAYOUT(grid_layout), 2);
|
||||
gtk_grid_layout_set_column_spacing(GTK_GRID_LAYOUT(grid_layout), 2);
|
||||
// gtk_grid_layout_set_baseline_row(GTK_GRID_LAYOUT(grid_layout), 4);
|
||||
// init buttons
|
||||
self->vkb = NULL;
|
||||
}
|
||||
|
||||
static void diya_virtual_keyboard_widget_class_init(DiyaVirtualKeyboardWidgetClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
gobject_class->dispose = diya_virtual_keyboard_widget_dispose;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type(GTK_WIDGET_CLASS(class), GTK_TYPE_GRID_LAYOUT);
|
||||
}
|
||||
|
||||
DiyaVirtualKeyboardWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard *kb)
|
||||
{
|
||||
DiyaVirtualKeyboardWidget *self = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD_WIDGET, NULL);
|
||||
GtkLayoutManager *grid_layout = gtk_widget_get_layout_manager(GTK_WIDGET(self));
|
||||
self->vkb = kb;
|
||||
|
||||
int btn_index = 0;
|
||||
for (int i = 0; i < VKB_N_CELLS; i++)
|
||||
{
|
||||
gboolean skip = false;
|
||||
int row = VKB_ROW_NUM(i);
|
||||
int col = VKB_COL_NUM(i);
|
||||
switch (row)
|
||||
{
|
||||
case 0:
|
||||
skip = (col % 2 != 0) || (col > 26);
|
||||
break;
|
||||
case 1:
|
||||
skip = (col == 1) || (col == 2) || (col != 0 && col % 2 == 0);
|
||||
break;
|
||||
case 2:
|
||||
skip = (col == 1) || (col == 2) || (col != 0 && col % 2 == 0) || (col > 25);
|
||||
break;
|
||||
case 3:
|
||||
skip = (col > 0 && col < 5) || (col != 0 && col % 2 == 0);
|
||||
break;
|
||||
case 4:
|
||||
skip = (col > 0 && col < 3) || (col == 4) || (col == 6) || (col > 7 && col < 19) || (col > 19 && col % 2 == 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (skip)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
DiyaVkbKey *key = diya_virtual_keyboard_get_key(self->vkb, g_vkb_layout[btn_index]);
|
||||
g_debug("add: %s", diya_object_to_string(key));
|
||||
btn_index++;
|
||||
GtkWidget *button = GTK_WIDGET(diya_vkb_button_new(key));
|
||||
self->buttons = g_list_append(self->buttons, button);
|
||||
gtk_widget_set_parent(button, GTK_WIDGET(self));
|
||||
gtk_widget_set_hexpand(button, true);
|
||||
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(grid_layout, button));
|
||||
|
||||
gtk_grid_layout_child_set_row(grid_child, row);
|
||||
gtk_grid_layout_child_set_column(grid_child, col);
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 26:
|
||||
case 29:
|
||||
case 58:
|
||||
case 116:
|
||||
gtk_grid_layout_child_set_column_span(grid_child, 3);
|
||||
break;
|
||||
|
||||
case 83:
|
||||
gtk_grid_layout_child_set_column_span(grid_child, 4);
|
||||
break;
|
||||
case 87:
|
||||
gtk_grid_layout_child_set_column_span(grid_child, 5);
|
||||
break;
|
||||
case 123:
|
||||
gtk_grid_layout_child_set_column_span(grid_child, 12);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (i > 0)
|
||||
gtk_grid_layout_child_set_column_span(grid_child, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
18
src/vkb/virtual-keyboard-widgets.h
Normal file
18
src/vkb/virtual-keyboard-widgets.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef DIYA_VIRTUAL_KEYBOARD_WIDGETS_H
|
||||
#define DIYA_VIRTUAL_KEYBOARD_WIDGETS_H
|
||||
|
||||
#include "shell.h"
|
||||
#include "virtual-keyboard.h"
|
||||
|
||||
#define DIYA_TYPE_VIRTUAL_KEYBOARD_WIDGET (diya_virtual_keyboard_widget_get_type())
|
||||
G_DECLARE_FINAL_TYPE (DiyaVirtualKeyboardWidget, diya_virtual_keyboard_widget, DIYA, VIRTUAL_KEYBOARD_WIDGET, GtkWidget)
|
||||
|
||||
DiyaVirtualKeyboardWidget* diya_virtual_keyboard_widget_new();
|
||||
|
||||
|
||||
#define DIYA_TYPE_VKB_BUTTON (diya_vkb_button_get_type())
|
||||
G_DECLARE_FINAL_TYPE (DiyaVkbButton, diya_vkb_button, DIYA, VKB_BUTTON, GtkWidget)
|
||||
|
||||
DiyaVkbButton* diya_vkb_button_new(DiyaVkbKey* key);
|
||||
|
||||
#endif
|
440
src/vkb/virtual-keyboard.c
Normal file
440
src/vkb/virtual-keyboard.c
Normal file
@ -0,0 +1,440 @@
|
||||
#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"
|
||||
|
||||
struct _DiyaVkbKey
|
||||
{
|
||||
DiyaObject parent;
|
||||
uint32_t code;
|
||||
gchar *key_caps[3];
|
||||
uint32_t syms[3];
|
||||
gchar *info;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVkbKey, diya_vkb_key, DIYA_TYPE_OBJECT)
|
||||
|
||||
static void diya_vkb_key_dispose(GObject *object)
|
||||
{
|
||||
DiyaVkbKey *self = DIYA_VKB_KEY(object);
|
||||
g_debug("diya_vkb_key_dispose: %s", diya_object_to_string(object));
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (self->key_caps[i])
|
||||
{
|
||||
free(self->key_caps[i]);
|
||||
}
|
||||
}
|
||||
self->code = 0;
|
||||
if (self->info)
|
||||
{
|
||||
free(self->info);
|
||||
self->info = NULL;
|
||||
}
|
||||
G_OBJECT_CLASS(diya_vkb_key_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_vkb_key_init(DiyaVkbKey *self)
|
||||
{
|
||||
self->code = 0;
|
||||
memset(self->key_caps, 0, sizeof(self->key_caps));
|
||||
memset(self->syms, 0, sizeof(self->syms));
|
||||
self->info = NULL;
|
||||
}
|
||||
|
||||
static const gchar *diya_vkb_key_to_string(DiyaObject *object)
|
||||
{
|
||||
DiyaVkbKey *self = DIYA_VKB_KEY(object);
|
||||
if (!self->info && self->code != 0)
|
||||
{
|
||||
self->info = (char *)malloc(128);
|
||||
g_snprintf(self->info, 128,
|
||||
"DiyaVkbKey: %d (0x%.4x: %s, 0x%.4x: %s, 0x%.4x: %s)",
|
||||
self->code,
|
||||
self->syms[0],
|
||||
self->key_caps[0],
|
||||
self->syms[1],
|
||||
self->key_caps[1],
|
||||
self->syms[2],
|
||||
self->key_caps[2]);
|
||||
}
|
||||
return self->info;
|
||||
}
|
||||
|
||||
static void diya_vkb_key_class_init(DiyaVkbKeyClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||
|
||||
gobject_class->dispose = diya_vkb_key_dispose;
|
||||
// gobject_class->set_property = diya_lock_session_set_property;
|
||||
// gobject_class->get_property = diya_lock_session_get_property;
|
||||
base_class->to_string = diya_vkb_key_to_string;
|
||||
}
|
||||
|
||||
const gchar *diya_vkb_key_get_keycap(DiyaVkbKey *key, uint32_t shift_level)
|
||||
{
|
||||
if (shift_level > 2)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return key->key_caps[shift_level];
|
||||
}
|
||||
|
||||
uint32_t diya_vkb_key_get_code(DiyaVkbKey *key)
|
||||
{
|
||||
return key->code;
|
||||
}
|
||||
|
||||
uint32_t diya_vkb_key_is_alphabet(DiyaVkbKey* self)
|
||||
{
|
||||
return (self->code >= 24 && self->code <= 33) ||
|
||||
(self->code >= 38 && self->code <= 46) ||
|
||||
(self->code >= 52 && self->code <= 58);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DiyaVirtualKeyboard class: lowlevel wayland virtual keyboard handle
|
||||
*
|
||||
*/
|
||||
|
||||
static struct zwp_virtual_keyboard_manager_v1 *g_virtual_keyboard_manager = NULL;
|
||||
|
||||
struct _DiyaVirtualKeyboard
|
||||
{
|
||||
DiyaShellObject parent;
|
||||
struct zwp_virtual_keyboard_v1 *keyboard;
|
||||
struct xkb_context *vkb_ctx;
|
||||
struct xkb_keymap *vkb_keymap;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
if (self->vkb_keymap)
|
||||
{
|
||||
xkb_keymap_unref(self->vkb_keymap);
|
||||
}
|
||||
if (self->vkb_ctx)
|
||||
{
|
||||
xkb_context_unref(self->vkb_ctx);
|
||||
}
|
||||
G_OBJECT_CLASS(diya_virtual_keyboard_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_virtual_keyboard_init(DiyaVirtualKeyboard *self)
|
||||
{
|
||||
self->keyboard = NULL;
|
||||
self->vkb_ctx = NULL;
|
||||
self->vkb_keymap = 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)
|
||||
{
|
||||
struct xkb_context *vkb_ctx = NULL;
|
||||
struct xkb_keymap *vkb_keymap = NULL;
|
||||
gsize len = 0;
|
||||
vkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!vkb_ctx)
|
||||
{
|
||||
g_critical("diya_virtual_keyboard_new: Failed to create XKB context: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (keymap_file)
|
||||
{
|
||||
g_debug("diya_virtual_keyboard_new: Load keymap from file: %s", keymap_file);
|
||||
FILE *fp = fopen(keymap_file, "r");
|
||||
if (!fp)
|
||||
{
|
||||
g_critical("diya_virtual_keyboard_new: Failed to open file %s: %s", keymap_file, strerror(errno));
|
||||
xkb_context_unref(vkb_ctx);
|
||||
return NULL;
|
||||
}
|
||||
vkb_keymap = xkb_keymap_new_from_file(vkb_ctx, fp, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
GError *error = NULL;
|
||||
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);
|
||||
xkb_context_unref(vkb_ctx);
|
||||
return NULL;
|
||||
}
|
||||
vkb_keymap = xkb_keymap_new_from_string(vkb_ctx, (gchar *)g_bytes_get_data(bytes, &len), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
g_bytes_unref(bytes);
|
||||
}
|
||||
|
||||
if (!vkb_keymap)
|
||||
{
|
||||
g_critical("diya_virtual_keyboard_new: Unable to load keymap: %s", strerror(errno));
|
||||
xkb_context_unref(vkb_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *content = xkb_keymap_get_as_string(vkb_keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
len = strlen(content);
|
||||
if (!content)
|
||||
{
|
||||
g_critical("diya_virtual_keyboard_new: xkb_keymap_get_as_string: %s", strerror(errno));
|
||||
xkb_context_unref(vkb_ctx);
|
||||
xkb_keymap_unref(vkb_keymap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fd = create_keymap_fd(len);
|
||||
if (fd == -1)
|
||||
{
|
||||
g_critical("diya_virtual_keyboard_new: create temp file");
|
||||
xkb_context_unref(vkb_ctx);
|
||||
xkb_keymap_unref(vkb_keymap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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));
|
||||
xkb_context_unref(vkb_ctx);
|
||||
xkb_keymap_unref(vkb_keymap);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
// g_debug("Using keymap configuration: \n%s", content);
|
||||
strcpy((char *)ptr, content);
|
||||
free(content);
|
||||
|
||||
DiyaVirtualKeyboard *vkb = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD, "shell", shell, NULL);
|
||||
vkb->vkb_ctx = vkb_ctx;
|
||||
vkb->vkb_keymap = vkb_keymap;
|
||||
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);
|
||||
}
|
||||
|
||||
gchar *diya_virtual_keyboard_get_keycap(const xkb_keysym_t *sym)
|
||||
{
|
||||
char buf[32];
|
||||
switch (*sym)
|
||||
{
|
||||
case XKB_KEY_Escape:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "Esc");
|
||||
break;
|
||||
case XKB_KEY_BackSpace:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⌫");
|
||||
break;
|
||||
case XKB_KEY_Tab:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⇥");
|
||||
break;
|
||||
case XKB_KEY_Return:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⏎");
|
||||
break;
|
||||
case XKB_KEY_Control_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "Ctrl");
|
||||
break;
|
||||
case XKB_KEY_Shift_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⇧");
|
||||
break;
|
||||
case XKB_KEY_Caps_Lock:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⇪");
|
||||
break;
|
||||
case XKB_KEY_Alt_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⎇");
|
||||
break;
|
||||
case XKB_KEY_Alt_R:
|
||||
case XKB_KEY_ISO_Level3_Shift:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⇮");
|
||||
break;
|
||||
case XKB_KEY_space:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⎵");
|
||||
break;
|
||||
case XKB_KEY_Up:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "↑");
|
||||
break;
|
||||
case XKB_KEY_Down:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "↓");
|
||||
break;
|
||||
case XKB_KEY_Left:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "←");
|
||||
break;
|
||||
case XKB_KEY_Right:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "→");
|
||||
break;
|
||||
case XKB_KEY_function:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "Fn");
|
||||
break;
|
||||
case XKB_KEY_Meta_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⌘");
|
||||
break;
|
||||
case XKB_KEY_Super_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "●");
|
||||
break;
|
||||
case XKB_KEY_dead_circumflex:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "^");
|
||||
break;
|
||||
case XKB_KEY_dead_diaeresis:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "¨");
|
||||
break;
|
||||
default:
|
||||
if (xkb_keysym_to_utf8(*sym, buf, sizeof(buf)) == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return g_strdup(buf);
|
||||
}
|
||||
|
||||
DiyaVkbKey *diya_virtual_keyboard_get_key(DiyaVirtualKeyboard *self, uint32_t code)
|
||||
{
|
||||
DiyaVkbKey *key = g_object_new(DIYA_TYPE_VKB_KEY, NULL);
|
||||
key->code = code;
|
||||
int n_level = xkb_keymap_num_levels_for_key(self->vkb_keymap, code, 0);
|
||||
if (n_level > 0)
|
||||
{
|
||||
n_level = n_level > 3 ? 3 : n_level;
|
||||
for (int level = 0; level < n_level; level++)
|
||||
{
|
||||
const xkb_keysym_t *syms = NULL;
|
||||
int n_sym = xkb_keymap_key_get_syms_by_level(self->vkb_keymap, code, 0, level, &syms);
|
||||
if (n_sym <= 0 || syms[0] == key->syms[0] || syms[0] == key->syms[1])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
key->syms[level] = syms[0];
|
||||
key->key_caps[level] = diya_virtual_keyboard_get_keycap(&syms[0]);
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
25
src/vkb/virtual-keyboard.h
Normal file
25
src/vkb/virtual-keyboard.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef DIYA_VIRTUAL_KEYBOARD_H
|
||||
#define DIYA_VIRTUAL_KEYBOARD_H
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VKB_KEY_STATE_RELEASED = 0 /*WL_KEYBOARD_KEY_STATE_RELEASED*/,
|
||||
VKB_KEY_STATE_PRESSED = 1 /*WL_KEYBOARD_KEY_STATE_PRESSED*/,
|
||||
} diya_vkb_state_t;
|
||||
|
||||
#define DIYA_TYPE_VKB_KEY (diya_vkb_key_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaVkbKey, diya_vkb_key, DIYA, VKB_KEY, DiyaObject)
|
||||
const gchar* diya_vkb_key_get_keycap(DiyaVkbKey* key, uint32_t shift_level);
|
||||
uint32_t diya_vkb_key_get_code(DiyaVkbKey* key);
|
||||
uint32_t diya_vkb_key_is_alphabet(DiyaVkbKey* key);
|
||||
|
||||
|
||||
DiyaVirtualKeyboard* diya_virtual_keyboard_new(DiyaShell* shell, const gchar* keymap_file);
|
||||
|
||||
void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell);
|
||||
void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard* vkb, uint32_t key, diya_vkb_state_t state);
|
||||
|
||||
DiyaVkbKey* diya_virtual_keyboard_get_key(DiyaVirtualKeyboard* vkb, uint32_t key);
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user