Virtual keyboard + configuration:
- complete implementation of virtual keyboard - support loading user defined virtual keyboard from configuration at $XDG_CONFIG_HOME/xkb/ - support loading user defined CSS theme from $XDG_CONFIG_HOME/themes/
This commit is contained in:
parent
24f47dfd7f
commit
2c5338f4bf
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/dev/iohub/diya/shell">
|
||||
<file alias="login-shell.css">resources/login-shell.css</file>
|
||||
<file alias="dev.iohub.diya.login-shell.css">resources/login-shell.css</file>
|
||||
<file alias="virtual-keyboard.css">resources/virtual-keyboard.css</file>
|
||||
<file alias="default.keymap">resources/default.keymap</file>
|
||||
<!--file alias="virtuail-keyboard.ui">resources/ui/virtual-keyboard.ui</file-->
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/dev/iohub/diya/shell">
|
||||
<file alias="dev.iohub.diya.session-shell.css">resources/session-shell.css</file>
|
||||
<file alias="default.keymap">resources/default.keymap</file>
|
||||
</gresource>
|
||||
</gresources>
|
@ -1,16 +1,21 @@
|
||||
@import url("resource:///dev/iohub/diya/shell/virtual-keyboard.css");
|
||||
/*
|
||||
* {
|
||||
font-family:DejaVuSans;
|
||||
}
|
||||
*/
|
||||
|
||||
.diya-login-header {
|
||||
#diya_login_shell
|
||||
{
|
||||
}
|
||||
|
||||
#diya_login_shell label.diya-login-header {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.diya-login-status {
|
||||
#diya_login_shell label.diya-login-status {
|
||||
font-size: 12px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
#diya_login_shell button.diya-btn-show-vkb
|
||||
{
|
||||
color: gray;
|
||||
min-width: 0px;
|
||||
}
|
11
resources/session-shell.css
Normal file
11
resources/session-shell.css
Normal file
@ -0,0 +1,11 @@
|
||||
@import url("resource:///dev/iohub/diya/shell/virtual-keyboard.css");
|
||||
|
||||
#diya_shell_launcher
|
||||
{
|
||||
background-color: orange;
|
||||
}
|
||||
#diya_shell_background
|
||||
{
|
||||
background-image:url("file:///etc/xdg/labwc/wpp.jpg");
|
||||
background-size: cover;
|
||||
}
|
@ -1,18 +1,25 @@
|
||||
.diya-vkb
|
||||
diya-vkb
|
||||
{
|
||||
background-color: transparent;
|
||||
border: 1px solid orangered;
|
||||
/* border: 1px solid orangered; */
|
||||
}
|
||||
|
||||
.diya-vkb-btn {
|
||||
diya-vkb-button
|
||||
{
|
||||
background-color: white;
|
||||
border: 1px solid #CDC7C2;
|
||||
border-radius: 3px;
|
||||
min-width: 30px;
|
||||
/*min-height: 30px;*/
|
||||
min-height: 30px;
|
||||
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.19);
|
||||
}
|
||||
|
||||
.diya-vkb-btn:hover
|
||||
diya-vkb-button.active
|
||||
{
|
||||
background-color: #E7E6E2;
|
||||
}
|
||||
|
||||
diya-vkb-button:hover
|
||||
{
|
||||
background-color: #E7E6E2;
|
||||
}
|
||||
@ -22,18 +29,19 @@
|
||||
|
||||
}*/
|
||||
|
||||
.diya-vkb-btn-level-1 {
|
||||
diya-vkb-button label.shift-level-1 {
|
||||
color: black;
|
||||
padding-top: 2px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.diya-vkb-btn-level-2 {
|
||||
diya-vkb-button label.shift-level-2 {
|
||||
color: gray;
|
||||
font-size: 9px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.diya-vkb-btn-level-3 {
|
||||
diya-vkb-button label.shift-level-3 {
|
||||
color: gray;
|
||||
font-size: 9px;
|
||||
padding-right: 3px;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "background.h"
|
||||
#include <assert.h>
|
||||
#define NAMESPACE "background"
|
||||
#define NAMESPACE "diya_shell_background"
|
||||
|
||||
static void on_background_destroy(GtkWindow *window, GApplication *_data)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "session-lock.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define NAMESPACE "launcher"
|
||||
#define NAMESPACE "diya_shell_launcher"
|
||||
|
||||
static void on_launcher_destroy(GtkWindow *window, GApplication *_data)
|
||||
{
|
||||
@ -51,8 +51,8 @@ void diya_session_shell_launcher_init(DiyaSessionShell * shell)
|
||||
// anchor window to all edges
|
||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_LEFT, true);
|
||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, true);
|
||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_TOP, true);
|
||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_BOTTOM, false);
|
||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_TOP, false);
|
||||
gtk_layer_set_anchor (gtk_window, GTK_LAYER_SHELL_EDGE_BOTTOM, true);
|
||||
|
||||
// set margin on window
|
||||
for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define DBUS_SERVER_NAME "dev.iohub.diya.SessionManager"
|
||||
#define DBUS_SERVER_PATH "/dev/iohub/diya/SessionManager"
|
||||
#define DBUS_SERVER_ERROR_NAME "dev.iohub.diya.SessionManager.Error"
|
||||
#define NAMESPACE "diya_login_shell"
|
||||
|
||||
struct _DiyaLoginShell
|
||||
{
|
||||
@ -17,7 +18,7 @@ struct _DiyaLoginShell
|
||||
GtkWidget *password;
|
||||
GtkWidget *status;
|
||||
guint bus_watch_id;
|
||||
// GtkWindow *window;
|
||||
GtkWidget *vkb_widget;
|
||||
GList *windows;
|
||||
};
|
||||
|
||||
@ -165,87 +166,92 @@ static void do_login(GtkButton *button, DiyaLoginShell *self)
|
||||
// g_application_quit(G_APPLICATION(self->app));
|
||||
}
|
||||
|
||||
static void open_vkb(GtkButton *button, DiyaLoginShell *self)
|
||||
static void show_vkb(GtkToggleButton *button, DiyaLoginShell *self)
|
||||
{
|
||||
(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);
|
||||
g_usleep(10000);
|
||||
diya_virtual_keyboard_send_key(vkb, 30, VKB_KEY_STATE_RELEASED);
|
||||
g_usleep(10000);
|
||||
gtk_widget_set_visible(GTK_WIDGET(self->vkb_widget), gtk_toggle_button_get_active(button));
|
||||
}
|
||||
|
||||
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))));
|
||||
gtk_session_lock_instance_assign_window_to_monitor(self->lock, window, monitor);
|
||||
gtk_widget_set_name(GTK_WIDGET(window), NAMESPACE);
|
||||
|
||||
GtkWidget *grid = gtk_grid_new();
|
||||
gtk_window_set_child(window, grid);
|
||||
gtk_grid_set_row_homogeneous(GTK_GRID(grid), false);
|
||||
|
||||
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
|
||||
gtk_box_set_spacing(GTK_BOX(box), 10);
|
||||
|
||||
gtk_widget_set_hexpand(box, true);
|
||||
gtk_widget_set_vexpand(box, true);
|
||||
|
||||
GtkWidget *label;
|
||||
|
||||
label = gtk_label_new("Please login");
|
||||
gtk_box_append(GTK_BOX(box), label);
|
||||
gtk_widget_add_css_class(label, "diya-login-header");
|
||||
|
||||
GtkWidget *user_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_valign(user_box, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_halign(user_box, GTK_ALIGN_END);
|
||||
gtk_box_set_spacing(GTK_BOX(user_box), 10);
|
||||
|
||||
GtkWidget *child_grid = gtk_grid_new();
|
||||
gtk_grid_set_row_spacing(GTK_GRID(child_grid),10);
|
||||
gtk_grid_set_column_spacing(GTK_GRID(child_grid),10);
|
||||
label = gtk_label_new("Username");
|
||||
gtk_box_append(GTK_BOX(user_box), label);
|
||||
gtk_grid_attach(GTK_GRID(child_grid), label, 0, 0, 1, 1);
|
||||
|
||||
self->username = gtk_entry_new();
|
||||
gtk_box_append(GTK_BOX(user_box), GTK_WIDGET(self->username));
|
||||
|
||||
gtk_box_append(GTK_BOX(box), user_box);
|
||||
|
||||
GtkWidget *password_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_valign(password_box, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_halign(password_box, GTK_ALIGN_END);
|
||||
gtk_box_set_spacing(GTK_BOX(password_box), 10);
|
||||
gtk_grid_attach(GTK_GRID(child_grid), self->username, 1, 0, 1, 1);
|
||||
|
||||
label = gtk_label_new("Password");
|
||||
gtk_box_append(GTK_BOX(password_box), label);
|
||||
gtk_grid_attach(GTK_GRID(child_grid), label, 0, 1, 1, 1);
|
||||
|
||||
self->password = gtk_password_entry_new();
|
||||
gtk_box_append(GTK_BOX(password_box), GTK_WIDGET(self->password));
|
||||
gtk_grid_attach(GTK_GRID(child_grid), self->password, 1, 1, 1, 1);
|
||||
|
||||
gtk_box_append(GTK_BOX(box), password_box);
|
||||
gtk_box_append(GTK_BOX(box), child_grid);
|
||||
|
||||
g_signal_connect(self->username, "activate", G_CALLBACK(do_login), self);
|
||||
g_signal_connect(self->password, "activate", G_CALLBACK(do_login), self);
|
||||
|
||||
child_grid = gtk_grid_new();
|
||||
gtk_grid_set_column_spacing(GTK_GRID(child_grid),2);
|
||||
|
||||
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_box_append(GTK_BOX(box), button);
|
||||
|
||||
// Not displayed, but allows testing that creating popups doesn't crash GTK
|
||||
gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
||||
gtk_grid_attach(GTK_GRID(child_grid), button, 0, 0, 1, 1);
|
||||
// Not displayed, but allows testing that creating popups doesn't crash GTK
|
||||
gtk_widget_set_tooltip_text(button, "Login");
|
||||
gtk_widget_set_hexpand(button, true);
|
||||
|
||||
button = gtk_toggle_button_new_with_label("⌨");
|
||||
gtk_widget_add_css_class(button, "diya-btn-show-vkb");
|
||||
gtk_grid_attach(GTK_GRID(child_grid), button, 1, 0, 1, 1);
|
||||
gtk_box_append(GTK_BOX(box), child_grid);
|
||||
gtk_widget_set_tooltip_text(button, "Show virtual keyboard");
|
||||
g_signal_connect (button, "toggled",G_CALLBACK (show_vkb),self);
|
||||
gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
||||
|
||||
self->status = gtk_label_new(NULL);
|
||||
gtk_box_append(GTK_BOX(box), self->status);
|
||||
gtk_widget_add_css_class(self->status, "diya-login-status");
|
||||
|
||||
button = gtk_button_new_with_label("Show virtual keyboard");
|
||||
g_signal_connect(button, "clicked", G_CALLBACK(open_vkb), self);
|
||||
gtk_widget_set_can_focus(GTK_WIDGET(button), false);
|
||||
gtk_box_append(GTK_BOX(box), button);
|
||||
gtk_grid_attach(GTK_GRID(grid), box, 0, 0, 1, 1);
|
||||
|
||||
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));
|
||||
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
|
||||
gtk_box_set_spacing(GTK_BOX(box), 10);
|
||||
|
||||
gtk_window_set_child(GTK_WINDOW(window), box);
|
||||
self->vkb_widget = diya_virtual_keyboard_widget_new(diya_shell_get_virtual_keyboard(DIYA_SHELL(self), "fr"));
|
||||
gtk_box_append(GTK_BOX(box), self->vkb_widget);
|
||||
gtk_widget_set_visible(self->vkb_widget, false);
|
||||
|
||||
gtk_grid_attach(GTK_GRID(grid), box, 0, 1, 1, 1);
|
||||
gtk_widget_set_hexpand(box, true);
|
||||
gtk_widget_set_vexpand(box, false);
|
||||
|
||||
gtk_window_present(window);
|
||||
|
||||
@ -287,26 +293,6 @@ static void diya_login_shell_startup(DiyaShell *shell)
|
||||
g_object_unref(self);
|
||||
return;
|
||||
}
|
||||
GError *err = NULL;
|
||||
GBytes *bytes = g_resources_lookup_data("/dev/iohub/diya/shell/login-shell.css", 0, &err);
|
||||
if (err != NULL)
|
||||
{
|
||||
g_critical("Unable to load CSS resource: %s", err->message);
|
||||
g_error_free(err);
|
||||
// continue without stylesheet
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *data = g_bytes_get_data(bytes, NULL);
|
||||
g_debug("CSS resource loaded:\n %s", data);
|
||||
GtkCssProvider *provider = gtk_css_provider_new();
|
||||
gtk_css_provider_load_from_string(provider, data);
|
||||
gtk_style_context_add_provider_for_display(
|
||||
gdk_display_get_default(),
|
||||
GTK_STYLE_PROVIDER(provider),
|
||||
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++)
|
||||
{
|
||||
|
24
src/login.c
24
src/login.c
@ -3,33 +3,9 @@
|
||||
|
||||
#include "login-shell.h"
|
||||
|
||||
static gchar **g_shell_argv;
|
||||
|
||||
static gboolean restart(gpointer d)
|
||||
{
|
||||
(void)d;
|
||||
gint i, fdlimit;
|
||||
|
||||
fdlimit = (int)sysconf(_SC_OPEN_MAX);
|
||||
g_debug("reload: closing fd's %d to %d", STDERR_FILENO + 1, fdlimit);
|
||||
for (i = STDERR_FILENO + 1; i < fdlimit; i++)
|
||||
{
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
g_debug("reload: exec: %s", g_shell_argv[0]);
|
||||
execvp(g_shell_argv[0], g_shell_argv);
|
||||
exit(1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
g_shell_argv = g_malloc0(sizeof(gchar *) * (argc + 1));
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
g_shell_argv[i] = argv[i];
|
||||
}
|
||||
g_unix_signal_add(SIGHUP, (GSourceFunc)restart, NULL);
|
||||
DiyaLoginShell* shell = DIYA_LOGIN_SHELL(g_object_new(DIYA_TYPE_LOGIN_SHELL, "name", "dev.iohub.diya.login-shell", NULL));
|
||||
return diya_shell_run(DIYA_SHELL(shell), argc, argv);
|
||||
}
|
||||
|
@ -99,22 +99,12 @@ static void diya_session_shell_startup(DiyaShell* shell)
|
||||
{
|
||||
diya_session_shell_launcher_init(DIYA_SESSION_SHELL(shell));
|
||||
diya_session_shell_init_background(DIYA_SESSION_SHELL(shell));
|
||||
|
||||
GtkCssProvider *provider = gtk_css_provider_new();
|
||||
const char *css = "#launcher {background-color: red;} #background {background-image:url(\"file:///etc/xdg/labwc/wpp.jpg\");background-size: cover;}";
|
||||
gtk_css_provider_load_from_string(provider, css);
|
||||
gtk_style_context_add_provider_for_display(
|
||||
gdk_display_get_default(), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
// g_signal_connect (win, "destroy", G_CALLBACK (before_destroy), provider);
|
||||
g_object_unref(provider);
|
||||
// CSS support
|
||||
// set color for it
|
||||
// g_timeout_add (100,(GSourceFunc )shell_timer,NULL);
|
||||
}
|
||||
|
||||
static void diya_session_shell_active(DiyaShell* shell)
|
||||
{
|
||||
diya_session_shell_lock(DIYA_SESSION_SHELL(shell));
|
||||
(void) shell;
|
||||
// diya_session_shell_lock(DIYA_SESSION_SHELL(shell));
|
||||
}
|
||||
|
||||
static void diya_session_shell_class_init(DiyaSessionShellClass *class)
|
||||
|
@ -2,26 +2,6 @@
|
||||
#include <assert.h>
|
||||
#include "session-shell.h"
|
||||
|
||||
|
||||
static gchar **g_shell_argv;
|
||||
|
||||
static gboolean restart(gpointer d)
|
||||
{
|
||||
(void)d;
|
||||
gint i, fdlimit;
|
||||
|
||||
fdlimit = (int)sysconf(_SC_OPEN_MAX);
|
||||
g_debug("reload: closing fd's %d to %d", STDERR_FILENO + 1, fdlimit);
|
||||
for (i = STDERR_FILENO + 1; i < fdlimit; i++)
|
||||
{
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
g_debug("reload: exec: %s", g_shell_argv[0]);
|
||||
execvp(g_shell_argv[0], g_shell_argv);
|
||||
exit(1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void session_locked(DiyaSessionShell* shell, void* data)
|
||||
{
|
||||
(void)data;
|
||||
@ -38,12 +18,6 @@ static void session_unlocked(DiyaSessionShell* shell, void* data)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
g_shell_argv = g_malloc0(sizeof(gchar *) * (argc + 1));
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
g_shell_argv[i] = argv[i];
|
||||
}
|
||||
g_unix_signal_add(SIGHUP, (GSourceFunc)restart, NULL);
|
||||
DiyaSessionShell *shell = DIYA_SESSION_SHELL(g_object_new(DIYA_TYPE_SESSION_SHELL, "name","dev.iohub.diya.session-shell", NULL));
|
||||
g_signal_connect(shell, "session-locked", G_CALLBACK(session_locked), NULL);
|
||||
g_signal_connect(shell, "session-unlocked", G_CALLBACK(session_unlocked), NULL);
|
||||
|
141
src/shell.c
141
src/shell.c
@ -19,8 +19,9 @@ typedef struct _DiyaShellPrivate
|
||||
DiyaObject parent;
|
||||
DiyaWayland * wayland;
|
||||
GtkApplication* app;
|
||||
DiyaVirtualKeyboard* vkb;
|
||||
gchar* name;
|
||||
GHashTable* vkbs;
|
||||
GtkCssProvider* css_provider;
|
||||
} DiyaShellPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT);
|
||||
@ -41,10 +42,11 @@ static void diya_shell_dispose(GObject* object)
|
||||
g_free(priv->name);
|
||||
priv->name = NULL;
|
||||
}
|
||||
if(priv->vkb)
|
||||
if(priv->css_provider)
|
||||
{
|
||||
g_object_unref(priv->vkb);
|
||||
g_object_unref(priv->css_provider);
|
||||
}
|
||||
g_hash_table_destroy(priv->vkbs);
|
||||
G_OBJECT_CLASS(diya_shell_parent_class)->dispose(object);
|
||||
if (priv->app)
|
||||
{
|
||||
@ -52,6 +54,62 @@ static void diya_shell_dispose(GObject* object)
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_shell_reload(DiyaShell* shell)
|
||||
{
|
||||
GError *err = NULL;
|
||||
GBytes *bytes = NULL;
|
||||
gchar* css_string = NULL;
|
||||
DiyaShellPrivate* priv = diya_shell_get_instance_private(shell);
|
||||
gchar* css_file = g_strconcat(g_get_user_config_dir(),"/diya/themes/",priv->name,".css", NULL);
|
||||
g_debug("diya_shell_reload: Looking for css file: %s", css_file);
|
||||
g_file_get_contents(css_file,&css_string, NULL, &err);
|
||||
free(css_file);
|
||||
if (err != NULL)
|
||||
{
|
||||
g_warning("diya_shell_reload: Unable to load CSS from file: %s", err->message);
|
||||
g_error_free(err);
|
||||
err = NULL;
|
||||
g_debug("diya_shell_reload: Fallback to default theme");
|
||||
css_file = g_strconcat("/dev/iohub/diya/shell/",priv->name,".css", NULL);
|
||||
bytes = g_resources_lookup_data(css_file, 0, &err);
|
||||
free(css_file);
|
||||
if (err != NULL)
|
||||
{
|
||||
g_critical("diya_shell_reload: Unable to load CSS from resource: %s", err->message);
|
||||
g_error_free(err);
|
||||
css_string = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
css_string = (gchar*)g_bytes_get_data(bytes, NULL);
|
||||
}
|
||||
}
|
||||
if(css_string)
|
||||
{
|
||||
if(priv->css_provider)
|
||||
{
|
||||
gtk_style_context_remove_provider_for_display(gdk_display_get_default(), GTK_STYLE_PROVIDER(priv->css_provider));
|
||||
priv->css_provider = NULL;
|
||||
}
|
||||
|
||||
g_debug("diya_shell_reload: Applying stylesheet:\n %s", css_string);
|
||||
priv->css_provider = gtk_css_provider_new();
|
||||
gtk_css_provider_load_from_string(priv->css_provider, css_string);
|
||||
gtk_style_context_add_provider_for_display(
|
||||
gdk_display_get_default(),
|
||||
GTK_STYLE_PROVIDER(priv->css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
if(!bytes)
|
||||
{
|
||||
free(css_string);
|
||||
}
|
||||
}
|
||||
if(bytes)
|
||||
{
|
||||
g_bytes_unref(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_gtk_app_startup(GtkApplication *app, void *data)
|
||||
{
|
||||
(void)app;
|
||||
@ -59,6 +117,7 @@ static void on_gtk_app_startup(GtkApplication *app, void *data)
|
||||
DiyaShellPrivate* priv = diya_shell_get_instance_private(shell);
|
||||
priv->wayland =diya_wayland_new(DIYA_SHELL(shell));
|
||||
DiyaShellClass* class = DIYA_SHELL_GET_CLASS(shell);
|
||||
diya_shell_reload(shell);
|
||||
if(class->startup_handle)
|
||||
{
|
||||
class->startup_handle(shell);
|
||||
@ -88,6 +147,19 @@ static gboolean diya_shell_sigint_handle(gpointer data)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static gboolean diya_shell_sighub_handle(DiyaShell* self)
|
||||
{
|
||||
// reload css file
|
||||
diya_shell_reload(self);
|
||||
DiyaShellClass* class = DIYA_SHELL_GET_CLASS(self);
|
||||
if(class->reload_handle)
|
||||
{
|
||||
class->reload_handle(self);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init_gtk_application(DiyaShell* self)
|
||||
{
|
||||
DiyaShellPrivate* priv = diya_shell_get_instance_private(self);
|
||||
@ -99,7 +171,7 @@ static void init_gtk_application(DiyaShell* self)
|
||||
g_signal_connect(priv->app, "startup", G_CALLBACK(on_gtk_app_startup), (void *)self);
|
||||
g_signal_connect(priv->app, "activate", G_CALLBACK(on_gtk_app_active), (void *)self);
|
||||
g_unix_signal_add(SIGINT,(GSourceFunc)diya_shell_sigint_handle,(void*)self);
|
||||
// g_signal_connect(priv->app, "shutdown", G_CALLBACK(shutdown), (void*)shell);
|
||||
g_unix_signal_add(SIGHUP, (GSourceFunc)diya_shell_sighub_handle, (void*)self);
|
||||
}
|
||||
|
||||
static void diya_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
@ -151,7 +223,8 @@ static void diya_shell_init(DiyaShell *self)
|
||||
priv->wayland = NULL;
|
||||
priv->app = NULL;
|
||||
priv->name = NULL;
|
||||
priv->vkb = NULL;
|
||||
priv->vkbs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_object_unref);
|
||||
priv->css_provider = NULL;
|
||||
}
|
||||
|
||||
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell)
|
||||
@ -194,6 +267,7 @@ static void diya_shell_class_init(DiyaShellClass *class)
|
||||
class->monitor_changed_handle = NULL;
|
||||
class->startup_handle = NULL;
|
||||
class->active_handle = NULL;
|
||||
class->reload_handle = NULL;
|
||||
|
||||
shell_properties[PROP_SHELL_WAYLAND] = g_param_spec_pointer("wayland", NULL, "Shell wayland", G_PARAM_READABLE); //
|
||||
shell_properties[PROP_SHELL_NAME] = g_param_spec_string("name", NULL, "Shell name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
@ -202,21 +276,54 @@ 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);
|
||||
assert(GTK_IS_APPLICATION(priv->app));
|
||||
int status = g_application_run(G_APPLICATION(priv->app),argc,argv);
|
||||
g_object_unref(priv->app);
|
||||
GtkApplication* app = priv->app;
|
||||
int status = g_application_run(G_APPLICATION(app),argc,argv);
|
||||
g_object_unref(app);
|
||||
return status;
|
||||
}
|
||||
|
||||
DiyaVirtualKeyboard* diya_shell_get_virtual_keyboard(DiyaShell* shell, const gchar* name)
|
||||
{
|
||||
DiyaVirtualKeyboard* vkb = NULL;
|
||||
DiyaShellPrivate* priv = diya_shell_get_instance_private(shell);
|
||||
if(name)
|
||||
{
|
||||
if(g_hash_table_contains(priv->vkbs, name))
|
||||
{
|
||||
g_debug("diya_shell_get_virtual_keyboard: Getting keyboard %s from cache", name);
|
||||
vkb = g_hash_table_lookup(priv->vkbs, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar* keymap_file = g_strconcat(g_get_user_config_dir(),"/diya/xkb/", name,".keymap", NULL);
|
||||
g_debug("diya_shell_get_virtual_keyboard: Looking for keymap file: %s", keymap_file);
|
||||
if(g_file_test(keymap_file, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))
|
||||
{
|
||||
vkb = diya_virtual_keyboard_new(shell, keymap_file);
|
||||
if(vkb)
|
||||
{
|
||||
g_debug("diya_shell_get_virtual_keyboard: add new keyboard %s to cache", name);
|
||||
g_hash_table_insert(priv->vkbs, (gpointer)name, vkb);
|
||||
}
|
||||
}
|
||||
free(keymap_file);
|
||||
}
|
||||
}
|
||||
|
||||
if(!vkb)
|
||||
{
|
||||
g_debug("Fallback to default virtual key board");
|
||||
if(!g_hash_table_contains(priv->vkbs, "default"))
|
||||
{
|
||||
g_debug("Add new keyboard instance to cache");
|
||||
g_hash_table_insert(priv->vkbs,"default", diya_virtual_keyboard_new(shell, NULL));
|
||||
}
|
||||
vkb = g_hash_table_lookup(priv->vkbs, "default");
|
||||
}
|
||||
|
||||
return vkb;
|
||||
}
|
@ -26,13 +26,13 @@ struct _DiyaShellClass
|
||||
void (*monitor_changed_handle)(GListModel* /*list*/,guint /*position*/, guint /*removed*/,guint /*added*/, gpointer);
|
||||
void (*startup_handle)(DiyaShell*);
|
||||
void (*active_handle)(DiyaShell*);
|
||||
void (*reload_handle)(DiyaShell*);
|
||||
};
|
||||
|
||||
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);
|
||||
DiyaVirtualKeyboard* diya_shell_get_virtual_keyboard(DiyaShell* shell, const gchar* name);
|
||||
|
||||
int diya_shell_run(DiyaShell* shell, int argc, char **argv);
|
||||
#endif
|
@ -8,7 +8,8 @@ struct _DiyaVkbButton
|
||||
{
|
||||
GtkWidget super;
|
||||
GtkWidget *labels[3];
|
||||
DiyaVkbKey *key;
|
||||
DiyaVkbKey *key; /*owned by the virtual keyboard*/
|
||||
gulong mod_sig_id;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVkbButton, diya_vkb_button, GTK_TYPE_WIDGET);
|
||||
@ -21,15 +22,21 @@ static void diya_vkb_button_dispose(GObject *object)
|
||||
{
|
||||
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_event(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
|
||||
{
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
const gchar* evt_name = (gchar*) data;
|
||||
GtkEventController *controller = GTK_EVENT_CONTROLLER(gesture);
|
||||
DiyaVkbButton *self = DIYA_VKB_BUTTON(gtk_event_controller_get_widget(controller));
|
||||
g_signal_emit_by_name(self, evt_name);
|
||||
}
|
||||
|
||||
static void diya_vkb_button_init(DiyaVkbButton *self)
|
||||
{
|
||||
gchar class_name[32]; /*diya-vkb-btn-level-%d */
|
||||
@ -38,13 +45,12 @@ static void diya_vkb_button_init(DiyaVkbButton *self)
|
||||
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);
|
||||
g_snprintf(class_name, sizeof(class_name), "shift-level-%d", i + 1);
|
||||
gtk_widget_add_css_class(self->labels[i], class_name);
|
||||
gtk_widget_set_hexpand(self->labels[i], true);
|
||||
|
||||
@ -73,32 +79,53 @@ static void diya_vkb_button_init(DiyaVkbButton *self)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// event handle
|
||||
GtkGesture *controller = gtk_gesture_click_new();
|
||||
g_signal_connect(controller, "pressed", G_CALLBACK(diya_vkb_button_event), "pressed");
|
||||
g_signal_connect(controller, "released", G_CALLBACK(diya_vkb_button_event), "released");
|
||||
gtk_widget_add_controller(GTK_WIDGET(self), GTK_EVENT_CONTROLLER(controller));
|
||||
}
|
||||
|
||||
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_css_name(GTK_WIDGET_CLASS(class), "diya-vkb-button");
|
||||
gtk_widget_class_set_layout_manager_type(GTK_WIDGET_CLASS(class), GTK_TYPE_GRID_LAYOUT);
|
||||
}
|
||||
|
||||
void diya_vkb_button_set_key(DiyaVkbButton* btn, DiyaVkbKey *key)
|
||||
{
|
||||
btn->key = key;
|
||||
for (uint32_t i = 0; i < 3; i++)
|
||||
{
|
||||
if(key)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_label_set_text(GTK_LABEL(btn->labels[i]), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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++)
|
||||
if(key)
|
||||
{
|
||||
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);
|
||||
}
|
||||
diya_vkb_button_set_key(btn, key);
|
||||
}
|
||||
btn->mod_sig_id = 0;
|
||||
return btn;
|
||||
}
|
||||
|
||||
@ -115,7 +142,7 @@ 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,
|
||||
50, 94, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 111, 66,
|
||||
9, 206, 64, 65, 0, 108, 113, 116, 114};
|
||||
|
||||
struct _DiyaVirtualKeyboardWidget
|
||||
@ -129,7 +156,7 @@ struct _DiyaVirtualKeyboardWidget
|
||||
* row 4: 54 - 62
|
||||
*/
|
||||
GList *buttons;
|
||||
DiyaVirtualKeyboard *vkb;
|
||||
DiyaVirtualKeyboard *vkb; /*owned by the widget itself*/
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboardWidget, diya_virtual_keyboard_widget, GTK_TYPE_WIDGET);
|
||||
@ -149,15 +176,18 @@ static void diya_virtual_keyboard_widget_dispose(GObject *object)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if(self->vkb)
|
||||
{
|
||||
g_object_unref(self->vkb);
|
||||
} */
|
||||
// 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);
|
||||
// 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);
|
||||
@ -171,17 +201,100 @@ static void diya_virtual_keyboard_widget_class_init(DiyaVirtualKeyboardWidgetCla
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
gobject_class->dispose = diya_virtual_keyboard_widget_dispose;
|
||||
|
||||
gtk_widget_class_set_css_name(GTK_WIDGET_CLASS(class), "diya-vkb");
|
||||
gtk_widget_class_set_layout_manager_type(GTK_WIDGET_CLASS(class), GTK_TYPE_GRID_LAYOUT);
|
||||
g_signal_new("pressed",
|
||||
DIYA_TYPE_VKB_BUTTON,
|
||||
G_SIGNAL_DETAILED |
|
||||
G_SIGNAL_ACTION |
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
0,
|
||||
NULL);
|
||||
g_signal_new("released",
|
||||
DIYA_TYPE_VKB_BUTTON,
|
||||
G_SIGNAL_DETAILED |
|
||||
G_SIGNAL_ACTION |
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
DiyaVirtualKeyboardWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard *kb)
|
||||
static void diya_vkb_widget_on_key_pressed(DiyaVkbButton* button, DiyaVirtualKeyboardWidget* self)
|
||||
{
|
||||
gtk_widget_add_css_class(GTK_WIDGET(button), "active");
|
||||
diya_virtual_keyboard_send_key(self->vkb, button->key,VKB_KEY_STATE_PRESSED);
|
||||
}
|
||||
|
||||
static void diya_vkb_widget_on_key_released(DiyaVkbButton* button, DiyaVirtualKeyboardWidget* self)
|
||||
{
|
||||
if(!diya_vkb_key_is_modifier(button->key))
|
||||
{
|
||||
gtk_widget_remove_css_class(GTK_WIDGET(button), "active");
|
||||
}
|
||||
diya_virtual_keyboard_send_key(self->vkb, button->key,VKB_KEY_STATE_RELEASED);
|
||||
}
|
||||
|
||||
static void on_kb_modifier_changed(DiyaVirtualKeyboard* kb, DiyaVkbButton* button)
|
||||
{
|
||||
if(!diya_virtual_keyboard_key_modifier_is_active(kb, button->key))
|
||||
{
|
||||
gtk_widget_remove_css_class(GTK_WIDGET(button), "active");
|
||||
}
|
||||
}
|
||||
|
||||
void diya_virtual_keyboard_widget_set_keyboard(DiyaVirtualKeyboardWidget* self, DiyaVirtualKeyboard* keyboard)
|
||||
{
|
||||
self->vkb = keyboard;
|
||||
int index = 0;
|
||||
if (self->buttons)
|
||||
{
|
||||
GList *it = NULL;
|
||||
for (it = self->buttons; it; it = it->next)
|
||||
{
|
||||
if (it->data)
|
||||
{
|
||||
DiyaVkbButton* button = it->data;
|
||||
DiyaVkbKey *key = NULL;
|
||||
if(button->mod_sig_id > 0)
|
||||
{
|
||||
g_signal_handler_disconnect(self->vkb,button->mod_sig_id);
|
||||
button->mod_sig_id = 0;
|
||||
}
|
||||
if(keyboard)
|
||||
{
|
||||
key = diya_virtual_keyboard_get_key(self->vkb, g_vkb_layout[index]);
|
||||
g_debug("set button key: %s", diya_object_to_string(key));
|
||||
if(diya_vkb_key_is_modifier(key))
|
||||
{
|
||||
button->mod_sig_id = g_signal_connect(self->vkb, "modifier-changed", G_CALLBACK(on_kb_modifier_changed), button);
|
||||
}
|
||||
}
|
||||
diya_vkb_button_set_key(button, key);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard* keyboard)
|
||||
{
|
||||
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;
|
||||
self->vkb = keyboard;
|
||||
if(self->vkb == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < VKB_N_CELLS; i++)
|
||||
{
|
||||
gboolean skip = false;
|
||||
@ -199,7 +312,7 @@ DiyaVirtualKeyboardWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard
|
||||
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);
|
||||
skip = (col > 0 && col < 3) || (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);
|
||||
@ -212,15 +325,16 @@ DiyaVirtualKeyboardWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard
|
||||
{
|
||||
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));
|
||||
|
||||
GtkWidget *button = GTK_WIDGET(diya_vkb_button_new(NULL));
|
||||
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));
|
||||
|
||||
g_signal_connect(button, "pressed", G_CALLBACK(diya_vkb_widget_on_key_pressed),self);
|
||||
g_signal_connect(button, "released", G_CALLBACK(diya_vkb_widget_on_key_released),self);
|
||||
|
||||
gtk_grid_layout_child_set_row(grid_child, row);
|
||||
gtk_grid_layout_child_set_column(grid_child, col);
|
||||
|
||||
@ -229,6 +343,7 @@ DiyaVirtualKeyboardWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard
|
||||
case 26:
|
||||
case 29:
|
||||
case 58:
|
||||
case 87:
|
||||
case 116:
|
||||
gtk_grid_layout_child_set_column_span(grid_child, 3);
|
||||
break;
|
||||
@ -236,8 +351,8 @@ DiyaVirtualKeyboardWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard
|
||||
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);
|
||||
/* 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);
|
||||
@ -249,5 +364,9 @@ DiyaVirtualKeyboardWidget *diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard
|
||||
break;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
if(keyboard)
|
||||
{
|
||||
diya_virtual_keyboard_widget_set_keyboard(self, keyboard);
|
||||
}
|
||||
return GTK_WIDGET(self);
|
||||
}
|
||||
|
@ -7,12 +7,14 @@
|
||||
#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();
|
||||
GtkWidget* diya_virtual_keyboard_widget_new(DiyaVirtualKeyboard* keyboard);
|
||||
void diya_virtual_keyboard_widget_set_keyboard(DiyaVirtualKeyboardWidget* widget, DiyaVirtualKeyboard* keyboard);
|
||||
|
||||
|
||||
#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);
|
||||
void diya_vkb_button_set_key(DiyaVkbButton* btn, DiyaVkbKey *key);
|
||||
|
||||
#endif
|
@ -13,6 +13,18 @@
|
||||
#include "virtual-keyboard.h"
|
||||
#include "wayland.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIYA_VKB_KEY_MOD_NONE = 0,
|
||||
DIYA_VKB_KEY_MOD_SHIFT = 1,
|
||||
DIYA_VKB_KEY_MOD_CAPS_LOCK = 2,
|
||||
DIYA_VKB_KEY_MOD_CTRL = 4,
|
||||
DIYA_VKB_KEY_MOD_ALT = 8,
|
||||
DIYA_VKB_KEY_MOD_SUPER = 64,
|
||||
DIYA_VKB_KEY_MOD_ALT_GR = 128,
|
||||
} diya_vkb_key_modifier_t;
|
||||
|
||||
|
||||
struct _DiyaVkbKey
|
||||
{
|
||||
DiyaObject parent;
|
||||
@ -20,6 +32,7 @@ struct _DiyaVkbKey
|
||||
gchar *key_caps[3];
|
||||
uint32_t syms[3];
|
||||
gchar *info;
|
||||
diya_vkb_key_modifier_t mode;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVkbKey, diya_vkb_key, DIYA_TYPE_OBJECT)
|
||||
@ -49,6 +62,7 @@ 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->mode = DIYA_VKB_KEY_MOD_NONE;
|
||||
self->info = NULL;
|
||||
}
|
||||
|
||||
@ -80,6 +94,19 @@ static void diya_vkb_key_class_init(DiyaVkbKeyClass *class)
|
||||
// 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;
|
||||
|
||||
g_signal_new("modifier-changed",
|
||||
DIYA_TYPE_VIRTUAL_KEYBOARD,
|
||||
G_SIGNAL_DETAILED |
|
||||
G_SIGNAL_ACTION |
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
const gchar *diya_vkb_key_get_keycap(DiyaVkbKey *key, uint32_t shift_level)
|
||||
@ -91,16 +118,21 @@ const gchar *diya_vkb_key_get_keycap(DiyaVkbKey *key, uint32_t shift_level)
|
||||
return key->key_caps[shift_level];
|
||||
}
|
||||
|
||||
uint32_t diya_vkb_key_get_code(DiyaVkbKey *key)
|
||||
|
||||
|
||||
/*uint32_t diya_vkb_key_get_code(DiyaVkbKey *key)
|
||||
{
|
||||
return key->code;
|
||||
return key->code - 8;
|
||||
}*/
|
||||
|
||||
gboolean diya_vkb_key_is_alphabet(DiyaVkbKey* self)
|
||||
{
|
||||
return (self->syms[0] >= XKB_KEY_a && self->code <= XKB_KEY_Z);
|
||||
}
|
||||
|
||||
uint32_t diya_vkb_key_is_alphabet(DiyaVkbKey* self)
|
||||
gboolean diya_vkb_key_is_modifier(DiyaVkbKey* self)
|
||||
{
|
||||
return (self->code >= 24 && self->code <= 33) ||
|
||||
(self->code >= 38 && self->code <= 46) ||
|
||||
(self->code >= 52 && self->code <= 58);
|
||||
return self->mode != DIYA_VKB_KEY_MOD_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,6 +148,8 @@ struct _DiyaVirtualKeyboard
|
||||
struct zwp_virtual_keyboard_v1 *keyboard;
|
||||
struct xkb_context *vkb_ctx;
|
||||
struct xkb_keymap *vkb_keymap;
|
||||
GHashTable * keys;
|
||||
guint32 key_mods;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA_TYPE_SHELL_OBJECT);
|
||||
@ -123,18 +157,22 @@ G_DEFINE_FINAL_TYPE(DiyaVirtualKeyboard, diya_virtual_keyboard, DIYA_TYPE_SHELL_
|
||||
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_debug("diya_virtual_keyboard_dispose: %s", diya_object_to_string(object));
|
||||
g_hash_table_destroy(self->keys);
|
||||
if (self->vkb_keymap)
|
||||
{
|
||||
xkb_keymap_unref(self->vkb_keymap);
|
||||
self->vkb_keymap = NULL;
|
||||
}
|
||||
if (self->vkb_ctx)
|
||||
{
|
||||
xkb_context_unref(self->vkb_ctx);
|
||||
self->vkb_ctx = NULL;
|
||||
}
|
||||
if (self->keyboard)
|
||||
{
|
||||
zwp_virtual_keyboard_v1_destroy(self->keyboard);
|
||||
self->keyboard = NULL;
|
||||
}
|
||||
G_OBJECT_CLASS(diya_virtual_keyboard_parent_class)->dispose(object);
|
||||
}
|
||||
@ -144,12 +182,18 @@ static void diya_virtual_keyboard_init(DiyaVirtualKeyboard *self)
|
||||
self->keyboard = NULL;
|
||||
self->vkb_ctx = NULL;
|
||||
self->vkb_keymap = NULL;
|
||||
self->keys = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
||||
self->key_mods = 0;
|
||||
}
|
||||
|
||||
static const gchar *diya_virtual_keyboard_to_string(DiyaObject *object)
|
||||
{
|
||||
(void)object;
|
||||
return "Diya virtual keyboard instance";
|
||||
DiyaVirtualKeyboard* self = DIYA_VIRTUAL_KEYBOARD(object);
|
||||
if(self->vkb_keymap)
|
||||
{
|
||||
return xkb_keymap_layout_get_name(self->vkb_keymap,0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void diya_virtual_keyboard_class_init(DiyaVirtualKeyboardClass *class)
|
||||
@ -291,8 +335,8 @@ DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *ke
|
||||
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);
|
||||
xkb_context_unref(vkb_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -300,8 +344,9 @@ DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *ke
|
||||
if (fd == -1)
|
||||
{
|
||||
g_critical("diya_virtual_keyboard_new: create temp file");
|
||||
xkb_context_unref(vkb_ctx);
|
||||
xkb_keymap_unref(vkb_keymap);
|
||||
xkb_context_unref(vkb_ctx);
|
||||
free(content);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -309,9 +354,10 @@ DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *ke
|
||||
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);
|
||||
xkb_context_unref(vkb_ctx);
|
||||
close(fd);
|
||||
free(content);
|
||||
return NULL;
|
||||
}
|
||||
// g_debug("Using keymap configuration: \n%s", content);
|
||||
@ -335,18 +381,58 @@ void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name,
|
||||
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)
|
||||
void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard *self, DiyaVkbKey* key, diya_vkb_state_t state)
|
||||
{
|
||||
guint32 old_mods = self->key_mods;
|
||||
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);
|
||||
zwp_virtual_keyboard_v1_key(self->keyboard, current_time_ms, key->code - 8, (uint32_t)state);
|
||||
switch (state)
|
||||
{
|
||||
case VKB_KEY_STATE_PRESSED:
|
||||
switch (key->mode)
|
||||
{
|
||||
case DIYA_VKB_KEY_MOD_NONE:
|
||||
break;
|
||||
case DIYA_VKB_KEY_MOD_CAPS_LOCK:
|
||||
self->key_mods = (self->key_mods & DIYA_VKB_KEY_MOD_CAPS_LOCK) ^ key->mode;
|
||||
zwp_virtual_keyboard_v1_modifiers(self->keyboard,0,0,self->key_mods,0);
|
||||
break;
|
||||
default:
|
||||
self->key_mods ^= key->mode;
|
||||
zwp_virtual_keyboard_v1_modifiers(self->keyboard,0,self->key_mods,0,0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case VKB_KEY_STATE_RELEASED:
|
||||
switch (key->mode)
|
||||
{
|
||||
case DIYA_VKB_KEY_MOD_NONE:
|
||||
if(self->key_mods)
|
||||
{
|
||||
self->key_mods = self->key_mods & DIYA_VKB_KEY_MOD_CAPS_LOCK;
|
||||
zwp_virtual_keyboard_v1_modifiers(self->keyboard,0,0,self->key_mods,0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(old_mods != self->key_mods)
|
||||
{
|
||||
g_signal_emit_by_name(self,"modifier-changed", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gchar *diya_virtual_keyboard_get_keycap(const xkb_keysym_t *sym)
|
||||
void diya_virtual_keyboard_init_level(DiyaVkbKey* key, const xkb_keysym_t sym, int level)
|
||||
{
|
||||
char buf[32];
|
||||
switch (*sym)
|
||||
key->syms[level] = sym;
|
||||
diya_vkb_key_modifier_t mod = DIYA_VKB_KEY_MOD_NONE;
|
||||
switch (sym)
|
||||
{
|
||||
case XKB_KEY_Escape:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "Esc");
|
||||
@ -362,19 +448,24 @@ gchar *diya_virtual_keyboard_get_keycap(const xkb_keysym_t *sym)
|
||||
break;
|
||||
case XKB_KEY_Control_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "Ctrl");
|
||||
mod = DIYA_VKB_KEY_MOD_CTRL;
|
||||
break;
|
||||
case XKB_KEY_Shift_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⇧");
|
||||
mod = DIYA_VKB_KEY_MOD_SHIFT;
|
||||
break;
|
||||
case XKB_KEY_Caps_Lock:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⇪");
|
||||
mod = DIYA_VKB_KEY_MOD_CAPS_LOCK;
|
||||
break;
|
||||
case XKB_KEY_Alt_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⎇");
|
||||
mod = DIYA_VKB_KEY_MOD_ALT;
|
||||
break;
|
||||
case XKB_KEY_Alt_R:
|
||||
case XKB_KEY_ISO_Level3_Shift:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⇮");
|
||||
mod = DIYA_VKB_KEY_MOD_ALT_GR;
|
||||
break;
|
||||
case XKB_KEY_space:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⎵");
|
||||
@ -398,7 +489,13 @@ gchar *diya_virtual_keyboard_get_keycap(const xkb_keysym_t *sym)
|
||||
g_snprintf(buf, sizeof(buf), "%s", "⌘");
|
||||
break;
|
||||
case XKB_KEY_Super_L:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "●");
|
||||
g_snprintf(buf, sizeof(buf), "%s", "●");
|
||||
if(level != 0)
|
||||
{
|
||||
key->syms[0] = sym;
|
||||
key->syms[level] = 0;
|
||||
}
|
||||
mod = DIYA_VKB_KEY_MOD_SUPER;
|
||||
break;
|
||||
case XKB_KEY_dead_circumflex:
|
||||
g_snprintf(buf, sizeof(buf), "%s", "^");
|
||||
@ -407,34 +504,58 @@ gchar *diya_virtual_keyboard_get_keycap(const xkb_keysym_t *sym)
|
||||
g_snprintf(buf, sizeof(buf), "%s", "¨");
|
||||
break;
|
||||
default:
|
||||
if (xkb_keysym_to_utf8(*sym, buf, sizeof(buf)) == 0)
|
||||
if (xkb_keysym_to_utf8(sym, buf, sizeof(buf)) == 0)
|
||||
{
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return g_strdup(buf);
|
||||
if(level == 0)
|
||||
{
|
||||
key->mode = mod;
|
||||
}
|
||||
if(sym == XKB_KEY_Super_L && level != 0)
|
||||
{
|
||||
if(key->key_caps[0])
|
||||
{
|
||||
free(key->key_caps[0]);
|
||||
}
|
||||
key->key_caps[0] = g_strdup(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
key->key_caps[level] = 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)
|
||||
if(!g_hash_table_contains(self->keys, GUINT_TO_POINTER(code)))
|
||||
{
|
||||
n_level = n_level > 3 ? 3 : n_level;
|
||||
for (int level = 0; level < n_level; level++)
|
||||
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)
|
||||
{
|
||||
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])
|
||||
n_level = n_level > 3 ? 3 : n_level;
|
||||
for (int level = 0; level < n_level; level++)
|
||||
{
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
diya_virtual_keyboard_init_level(key, syms[0],level);
|
||||
}
|
||||
key->syms[level] = syms[0];
|
||||
key->key_caps[level] = diya_virtual_keyboard_get_keycap(&syms[0]);
|
||||
}
|
||||
g_hash_table_insert(self->keys, GUINT_TO_POINTER(code), key);
|
||||
}
|
||||
return key;
|
||||
|
||||
return g_hash_table_lookup(self->keys, GUINT_TO_POINTER(code));
|
||||
}
|
||||
|
||||
gboolean diya_virtual_keyboard_key_modifier_is_active(DiyaVirtualKeyboard* vkb, DiyaVkbKey* key)
|
||||
{
|
||||
return (key->mode & vkb->key_mods) > 0;
|
||||
}
|
@ -12,14 +12,14 @@ typedef enum
|
||||
#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);
|
||||
|
||||
gboolean diya_vkb_key_is_alphabet(DiyaVkbKey* key);
|
||||
gboolean diya_vkb_key_is_modifier(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);
|
||||
void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard* vkb, DiyaVkbKey* key, diya_vkb_state_t state);
|
||||
|
||||
DiyaVkbKey* diya_virtual_keyboard_get_key(DiyaVirtualKeyboard* vkb, uint32_t key);
|
||||
gboolean diya_virtual_keyboard_key_modifier_is_active(DiyaVirtualKeyboard* vkb, DiyaVkbKey* key);
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user