Add base support to virtual keyboard wayland extension protocol

This commit is contained in:
DanyLE
2025-03-11 00:00:28 +01:00
parent 0e8bb9027f
commit 4da1db3bd4
26 changed files with 2320 additions and 326 deletions

View File

@@ -9,7 +9,7 @@ static void on_background_destroy(GtkWindow *window, GApplication *_data)
//g_application_quit (G_APPLICATION (gtk_window_get_application (window)));
}
void diya_shell_init_background(DiyaShell * shell)
void diya_session_shell_init_background(DiyaSessionShell * shell)
{
GtkApplication * app;
g_object_get(shell, "application", &app, NULL);

View File

@@ -1,8 +1,8 @@
#ifndef DIYA_SHELL_BACKGROUND_H
#define DIYA_SHELL_BACKGROUND_H
#include "shell.h"
#include "session-shell.h"
void diya_shell_init_background(DiyaShell * shell);
void diya_session_shell_init_background(DiyaSessionShell * shell);
#endif

View File

@@ -2,6 +2,7 @@
#define DIYA_OBJECT_H
#include <glib-object.h>
#include <assert.h>
/**
* Base class object

View File

@@ -1,5 +1,6 @@
#include <assert.h>
#include <inttypes.h>
#include "wlr-foreign-toplevel-management-unstable-v1.h"
#include "foreign.h"
/**
@@ -19,7 +20,7 @@ enum
static GParamSpec *win_properties[N_PROPERTIES] = {0};
struct _DiyaForeignWindow
{
DiyaObject parent;
DiyaShellObject parent;
gchar * appid;
gpointer handle;
gchar* title;
@@ -155,9 +156,9 @@ static void toplevel_handle_title(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle,
const char *title)
{
DiyaShell *shell = (DiyaShell *)data;
DiyaSessionShell *shell = (DiyaSessionShell *)data;
assert(shell);
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
assert(win);
g_object_set(win, "title", title, NULL);
g_debug("New title for: %s", diya_object_to_string(win));
@@ -166,9 +167,9 @@ static void toplevel_handle_app_id(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle,
const char *app_id)
{
DiyaShell *shell = (DiyaShell *)data;
DiyaSessionShell *shell = (DiyaSessionShell *)data;
assert(shell);
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
assert(win);
g_object_set(win, "appid", app_id, NULL);
g_debug("New appid for: %s", diya_object_to_string(win));
@@ -186,9 +187,9 @@ static void toplevel_handle_state(void *data,
struct wl_array *state)
{
uint32_t *entry;
DiyaShell *shell = (DiyaShell *)data;
DiyaSessionShell *shell = (DiyaSessionShell *)data;
assert(shell);
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
assert(win);
enum diya_win_state wstate = DIYA_WIN_STATE_NONE;
wl_array_for_each(entry, state) switch (*entry)
@@ -211,21 +212,21 @@ static void toplevel_handle_state(void *data,
static void toplevel_handle_done(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle)
{
DiyaShell *shell = (DiyaShell *)data;
DiyaSessionShell *shell = (DiyaSessionShell *)data;
assert(shell);
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
assert(win);
g_signal_emit_by_name(shell, "foreign-window-changed", (void *)win);
}
static void toplevel_handle_closed(void *data,
struct zwlr_foreign_toplevel_handle_v1 *handle)
{
DiyaShell *shell = (DiyaShell *)data;
DiyaSessionShell *shell = (DiyaSessionShell *)data;
assert(shell);
DiyaForeignWindow *win = diya_shell_get_window(shell, handle);
DiyaForeignWindow *win = diya_session_shell_get_window(shell, handle);
assert(win);
g_signal_emit_by_name(shell, "foreign-window-removed", (void *)win);
diya_shell_remove_window(shell, win);
diya_session_shell_remove_window(shell, win);
zwlr_foreign_toplevel_handle_v1_destroy(handle);
}
static void toplevel_handle_parent(void *data,
@@ -237,10 +238,10 @@ static void toplevel_handle_parent(void *data,
return;
}
assert(handle != parent);
DiyaShell *shell = (DiyaShell *)data;
DiyaSessionShell *shell = (DiyaSessionShell *)data;
assert(shell);
DiyaForeignWindow *child_win = diya_shell_get_window(shell, handle);
DiyaForeignWindow *parent_win = diya_shell_get_window(shell, parent);
DiyaForeignWindow *child_win = diya_session_shell_get_window(shell, handle);
DiyaForeignWindow *parent_win = diya_session_shell_get_window(shell, parent);
assert(child_win);
assert(parent_win);
assert(child_win != parent_win);
@@ -260,11 +261,11 @@ static const struct zwlr_foreign_toplevel_handle_v1_listener g_toplevel_impl = {
.parent = toplevel_handle_parent
};
static DiyaForeignWindow * diya_shell_foreign_window_new(DiyaShell* shell, gpointer handle)
static DiyaForeignWindow * diya_session_shell_foreign_window_new(DiyaSessionShell* shell, gpointer handle)
{
DiyaForeignWindow *win = DIYA_FOREIGN_WINDOW(g_object_new(DIYA_TYPE_FOREIGN_WINDOW,"handle", handle, "shell", shell, NULL));
//g_object_set(win, "shell", shell, NULL);
diya_shell_add_window(shell, win);
diya_session_shell_add_window(shell, win);
g_debug("Add new window 0x%" PRIXPTR, (uintptr_t)handle);
return win;
}
@@ -272,9 +273,9 @@ static DiyaForeignWindow * diya_shell_foreign_window_new(DiyaShell* shell, gpoin
static void toplevel_manager_handle_toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager, struct zwlr_foreign_toplevel_handle_v1 *tl)
{
(void) toplevel_manager;
DiyaShell *shell = (DiyaShell *)data;
DiyaSessionShell *shell = (DiyaSessionShell *)data;
assert(shell);
DiyaForeignWindow *win = diya_shell_get_window(shell, tl);
DiyaForeignWindow *win = diya_session_shell_get_window(shell, tl);
if (win)
{
@@ -282,15 +283,15 @@ static void toplevel_manager_handle_toplevel(void *data, struct zwlr_foreign_top
return;
}
// TODO: different between windows
win = diya_shell_foreign_window_new(shell, tl);
win = diya_session_shell_foreign_window_new(shell, tl);
zwlr_foreign_toplevel_handle_v1_add_listener(tl, &g_toplevel_impl, data);
}
static void toplevel_manager_handle_finished(void *data,
struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager)
{
DiyaShell *shell = (DiyaShell *)data;
diya_shell_remove_all_windows(shell);
DiyaSessionShell *shell = (DiyaSessionShell *)data;
diya_session_shell_remove_all_windows(shell);
// remove table entry
zwlr_foreign_toplevel_manager_v1_destroy(toplevel_manager);
}
@@ -301,8 +302,9 @@ static const struct zwlr_foreign_toplevel_manager_v1_listener g_toplevel_manager
.finished = toplevel_manager_handle_finished,
};
void diya_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell)
void diya_session_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell)
{
DiyaSessionShell* session_shell = DIYA_SESSION_SHELL(shell);
g_toplevel_manager = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 3);
zwlr_foreign_toplevel_manager_v1_add_listener(g_toplevel_manager, &g_toplevel_manager_impl, (void *)shell);
zwlr_foreign_toplevel_manager_v1_add_listener(g_toplevel_manager, &g_toplevel_manager_impl, (void *)session_shell);
}

View File

@@ -1,7 +1,16 @@
#ifndef DIYA_SHELL_FOREIGN_H
#define DIYA_SHELL_FOREIGN_H
#include "wlr-foreign-toplevel-management-unstable-v1.h"
#include "shell.h"
#include "session-shell.h"
enum diya_win_state
{
DIYA_WIN_STATE_NONE = 0,
DIYA_WIN_STATE_MINIMIZE = 1 << 0,
DIYA_WIN_STATE_MAXIMIZE = 1 << 1,
DIYA_WIN_STATE_FULLSCREEN = 1 << 2,
DIYA_WIN_STATE_FOCUS = 1 << 3,
};
void diya_session_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell * shell);
void diya_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell * shell);
#endif

View File

@@ -12,7 +12,7 @@ static void on_launcher_destroy(GtkWindow *window, GApplication *_data)
//g_application_quit (G_APPLICATION (gtk_window_get_application (window)));
}
static void on_foreign_window_change(DiyaShell* shell, DiyaForeignWindow * win, gpointer data)
static void on_foreign_window_change(DiyaSessionShell* shell, DiyaForeignWindow * win, gpointer data)
{
(void) data;
assert(win);
@@ -20,7 +20,7 @@ static void on_foreign_window_change(DiyaShell* shell, DiyaForeignWindow * win,
g_warning("on_foreign_window_change: WINDOW CHANGE %s, shell %s", diya_object_to_string(DIYA_OBJECT(win)), diya_object_to_string(DIYA_OBJECT(shell)));
}
static void on_foreign_window_removed(DiyaShell* shell, DiyaForeignWindow * win, gpointer data)
static void on_foreign_window_removed(DiyaSessionShell* shell, DiyaForeignWindow * win, gpointer data)
{
(void) data;
assert(win);
@@ -32,10 +32,10 @@ static void session_lock(GtkWidget *widget,gpointer data)
{
(void) widget;
g_warning("Enter session lock");
diya_shell_lock(data);
diya_session_shell_lock(data);
}
void diya_shell_launcher_init(DiyaShell * shell)
void diya_session_shell_launcher_init(DiyaSessionShell * shell)
{
assert(shell);
GtkApplication * app;

View File

@@ -1,9 +1,9 @@
#ifndef DIYA_SHELL_LAUNCHER_H
#define DIYA_SHELL_LAUNCHER_H
#include "shell.h"
#include "session-shell.h"
void diya_shell_launcher_init(DiyaShell * shell);
void diya_session_shell_launcher_init(DiyaSessionShell * shell);
#endif

View File

@@ -1,17 +1,17 @@
#include "login-shell.h"
#include <gtk4-layer-shell.h>
#include <gtk4-session-lock.h>
#include <gio/gio.h>
#include "login-shell.h"
#include "virtual-keyboard.h"
#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"
struct _DiyaLoginShell
{
DiyaObject parent_object;
DiyaShell parent_object;
GtkApplication *app;
GtkSessionLockInstance *lock;
GtkWidget *username;
@@ -20,7 +20,7 @@ struct _DiyaLoginShell
guint bus_watch_id;
};
G_DEFINE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA_TYPE_OBJECT);
G_DEFINE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA_TYPE_SHELL);
static void diya_login_shell_dispose(GObject *object)
{
@@ -67,6 +67,11 @@ static void diya_login_shell_class_init(DiyaLoginShellClass *class)
gobject_class->dispose = diya_login_shell_dispose;
// gobject_class->set_property = diya_lock_session_set_property;
// gobject_class->get_property = diya_lock_session_get_property;
//DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class)
//base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
base_class->to_string = diya_login_shell_to_string;
}
@@ -169,6 +174,23 @@ static void do_login(GtkButton *button, DiyaLoginShell *self)
// g_application_quit(G_APPLICATION(self->app));
}
static void open_vkb(GtkButton *button, DiyaLoginShell *self)
{
(void) button;
DiyaVirtualKeyboard* vkb = diya_virtual_keyboard_new(DIYA_SHELL(self), NULL);
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);
// send example key
g_object_unref(vkb);
}
DiyaLoginShell *diya_login_shell_new()
{
return g_object_new(DIYA_TYPE_LOGIN_SHELL, NULL);
@@ -232,10 +254,12 @@ void diya_login_shell_attach(DiyaLoginShell *self, GtkApplication *app)
gtk_box_append(GTK_BOX(box), password_box);
GtkWidget *button = gtk_button_new_with_label("Login");
g_signal_connect(self->username, "activate", G_CALLBACK(do_login), self);
g_signal_connect(self->password, "activate", G_CALLBACK(do_login), self);
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
@@ -245,6 +269,11 @@ void diya_login_shell_attach(DiyaLoginShell *self, GtkApplication *app)
gtk_box_append(GTK_BOX(box), self->status);
gtk_widget_add_css_class(self->status, "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_window_set_child(GTK_WINDOW(gtk_window), box);
gtk_window_present(gtk_window);

View File

@@ -3,9 +3,10 @@
#include <gtk/gtk.h>
#include "base.h"
#include "shell.h"
#define DIYA_TYPE_LOGIN_SHELL (diya_login_shell_get_type())
G_DECLARE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA, LOGIN_SHELL, DiyaObject);
G_DECLARE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA, LOGIN_SHELL, DiyaShell);
DiyaLoginShell *diya_login_shell_new();

View File

@@ -2,6 +2,7 @@
#include <assert.h>
#include "login-shell.h"
#include "wayland.h"
static gchar **g_shell_argv;
@@ -31,6 +32,7 @@ static gboolean restart(gpointer d)
static void startup(GtkApplication *app, DiyaLoginShell* shell)
{
diya_shell_wayland_init(DIYA_SHELL(shell));
g_unix_signal_add(SIGHUP, (GSourceFunc)restart, NULL);
g_unix_signal_add(SIGINT,(GSourceFunc)g_application_quit,(void*)app);
diya_login_shell_attach(shell, app);

View File

@@ -3,14 +3,14 @@
#include <gtk/gtk.h>
#include "session-lock.h"
static void unlock_session(GtkButton *button, DiyaShell *shell)
static void unlock_session(GtkButton *button, DiyaSessionShell *shell)
{
(void)button;
assert(shell);
diya_shell_unlock(shell);
diya_session_shell_unlock(shell);
}
void diya_shell_lock(DiyaShell* shell)
void diya_session_shell_lock(DiyaSessionShell* shell)
{
assert(shell);
GtkSessionLockInstance * lock;
@@ -60,7 +60,7 @@ void diya_shell_lock(DiyaShell* shell)
gtk_window_present(gtk_window);
}
}
void diya_shell_unlock(DiyaShell* shell)
void diya_session_shell_unlock(DiyaSessionShell* shell)
{
assert(shell);
GtkSessionLockInstance * lock;

View File

@@ -1,9 +1,9 @@
#ifndef DIYA_SESSION_LOCK_H
#define DIYA_SESSION_LOCK_H
#include "shell.h"
#include "session-shell.h"
void diya_shell_lock(DiyaShell* shell);
void diya_shell_unlock(DiyaShell* shell);
void diya_session_shell_lock(DiyaSessionShell* shell);
void diya_session_shell_unlock(DiyaSessionShell* shell);
#endif

273
src/session-shell.c Normal file
View File

@@ -0,0 +1,273 @@
#include "session-shell.h"
#include <assert.h>
#include <gtk4-session-lock.h>
#include "shell.h"
#include "foreign.h"
#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)"
enum
{
NO_PROP,
SHELL_APP,
SHELL_BACKGROUND_WIDGET,
SHELL_LAUNCHPAD_WIDGET,
SHELL_LOCK_SESSION,
SHELL_WINDOWS,
N_PROPERTIES
};
static GParamSpec *shell_properties[N_PROPERTIES] = {0};
struct _DiyaSessionShell
{
DiyaShell parent;
GtkApplication* app;
GtkWindow* background;
GtkWindow* launcher;
GHashTable* windows;
GtkSessionLockInstance* lock;
};
G_DEFINE_FINAL_TYPE(DiyaSessionShell, diya_session_shell, DIYA_TYPE_SHELL)
static void diya_session_shell_dispose(GObject* object)
{
DiyaSessionShell * self = DIYA_SESSION_SHELL(object);
g_hash_table_destroy(self->windows);
g_debug("diya_session_shell_dispose");
if(self->lock)
{
g_object_unref(self->lock);
}
G_OBJECT_CLASS(diya_session_shell_parent_class)->dispose(object);
}
static void diya_session_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaSessionShell * self = DIYA_SESSION_SHELL(object);
switch (property_id)
{
case SHELL_APP:
self->app = g_value_get_pointer(value);
assert(self->app);
break;
case SHELL_BACKGROUND_WIDGET:
self->background = g_value_get_pointer(value);
break;
case SHELL_LAUNCHPAD_WIDGET:
self->launcher = g_value_get_pointer(value);
break;
case SHELL_WINDOWS:
//self->windows = g_value_get_pointer(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void diya_session_shell_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaSessionShell * self = DIYA_SESSION_SHELL(object);
switch (property_id)
{
case SHELL_APP:
g_value_set_pointer(value, self->app);
break;
case SHELL_BACKGROUND_WIDGET:
g_value_set_pointer(value, self->background);
break;
case SHELL_LAUNCHPAD_WIDGET:
assert(self->launcher);
g_value_set_pointer(value, self->launcher);
break;
case SHELL_LOCK_SESSION:
assert(self->lock);
g_value_set_pointer(value, self->lock);
break;
case SHELL_WINDOWS:
g_value_set_pointer(value, self->windows);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static const gchar* diya_session_shell_to_string(DiyaObject* object)
{
(void) object;
return SHELL_DESCRIPTION;
}
static void diya_session_shell_class_init(DiyaSessionShellClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class);
base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
base_class->to_string = diya_session_shell_to_string;
gobject_class->dispose = diya_session_shell_dispose;
gobject_class->set_property = diya_session_shell_set_property;
gobject_class->get_property = diya_session_shell_get_property;
shell_properties[SHELL_APP] = g_param_spec_pointer("application", NULL, "Shell application", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
shell_properties[SHELL_BACKGROUND_WIDGET] = g_param_spec_pointer("background", NULL, "Shell background widget", G_PARAM_READWRITE );
shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer("launchpad", NULL, "Shell launchpad", G_PARAM_READWRITE );
shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer("session-lock", NULL, "Shell lock session", G_PARAM_READABLE );
shell_properties[SHELL_WINDOWS] = g_param_spec_pointer("windows", NULL, "Shell foreign windows", G_PARAM_READABLE);
g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties);
g_signal_new("foreign-window-changed",
DIYA_TYPE_SESSION_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
g_signal_new("foreign-window-removed",
DIYA_TYPE_SESSION_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
g_signal_new("session-locked",
DIYA_TYPE_SESSION_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
g_signal_new("session-unlocked",
DIYA_TYPE_SESSION_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
}
static void on_session_locked(GtkSessionLockInstance *lock, DiyaSessionShell *shell) {
(void)lock;
assert(shell);
g_message("Session locked successfully");
g_signal_emit_by_name(shell, "session-locked");
}
/*
static void failed(GtkSessionLockInstance *lock, void *data) {
(void)lock;
(void)data;
g_critical("The session could not be locked");
g_application_quit(G_APPLICATION(app));
}
*/
static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaSessionShell *shell) {
(void)lock;
assert(shell);
g_message("Session unlocked");
g_signal_emit_by_name(shell, "session-unlocked");
}
static void diya_session_shell_init(DiyaSessionShell *self)
{
//self->app = NULL;
self->background = NULL;
self->launcher = NULL;
self->lock = gtk_session_lock_instance_new();
g_signal_connect(self->lock, "locked", G_CALLBACK(on_session_locked), self);
// g_signal_connect(lock, "failed", G_CALLBACK(failed), NULL);
g_signal_connect(self->lock, "unlocked", G_CALLBACK(on_session_unlocked), self);
self->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
}
DiyaForeignWindow* diya_session_shell_get_window(DiyaSessionShell * shell, gpointer handle)
{
return g_hash_table_lookup(shell->windows, handle);
}
gboolean diya_session_shell_add_window(DiyaSessionShell * shell, DiyaForeignWindow * win)
{
gpointer handle;
g_object_get(win, "handle", &handle, NULL);
assert(handle);
return g_hash_table_insert(shell->windows,handle, win);
}
gboolean diya_session_shell_remove_window(DiyaSessionShell * shell, DiyaForeignWindow * win)
{
gpointer handle;
g_object_get(win, "handle", &handle, NULL);
assert(handle);
return g_hash_table_remove(shell->windows,handle);
}
void diya_session_shell_remove_all_windows(DiyaSessionShell * shell)
{
g_hash_table_destroy(shell->windows);
shell->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
}
DiyaSessionShell * diya_session_shell_new(GtkApplication * app)
{
return DIYA_SESSION_SHELL(g_object_new(DIYA_TYPE_SESSION_SHELL,"application",app, NULL));
}
/*
static void on_orientation_changed (GtkWindow *window, WindowOrientation orientation, ToplevelData *data)
{
(void)window;
GtkOrientation orient_toplevel, orient_sub;
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
switch (orientation) {
case WINDOW_ORIENTATION_HORIZONTAL:
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_HORIZONTAL;
break;
case WINDOW_ORIENTATION_VERTICAL:
orient_toplevel = GTK_ORIENTATION_VERTICAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
break;
case WINDOW_ORIENTATION_NONE:
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
break;
}
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->toplevel_box), orient_toplevel);
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->first_box), orient_sub);
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->second_box), orient_sub);
//gtk_window_resize (window, 1, 1); // force the window to shrink to the smallest size it can
}
*/
/*
static void before_destroy (GtkWidget *win, GtkCssProvider *provider) {
GdkDisplay *display = gdk_display_get_default ();
gtk_style_context_remove_provider_for_display (display, GTK_STYLE_PROVIDER (provider));
}
*/

20
src/session-shell.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef DIYA_SESSION_SHELL_H
#define DIYA_SESSION_SHELL_H
#include <gtk4-layer-shell.h>
#include "shell.h"
#include "base.h"
#define DIYA_TYPE_SESSION_SHELL (diya_session_shell_get_type ())
G_DECLARE_FINAL_TYPE (DiyaSessionShell, diya_session_shell, DIYA, SESSION_SHELL, DiyaShell)
#define DIYA_TYPE_FOREIGN_WINDOW (diya_foreign_window_get_type ())
G_DECLARE_FINAL_TYPE (DiyaForeignWindow, diya_foreign_window, DIYA, FOREIGN_WINDOW, DiyaShellObject)
DiyaForeignWindow* diya_session_shell_get_window(DiyaSessionShell * shell, gpointer handle);
gboolean diya_session_shell_add_window(DiyaSessionShell * shell, DiyaForeignWindow * win);
gboolean diya_session_shell_remove_window(DiyaSessionShell * shell, DiyaForeignWindow * win);
void diya_session_shell_remove_all_windows(DiyaSessionShell * shell);
DiyaSessionShell * diya_session_shell_new(GtkApplication * app);
#endif

View File

@@ -14,8 +14,8 @@ static void activate(GtkApplication *app, void *data)
(void)app;
(void)data;
DiyaShell *shell = data;
diya_shell_lock(shell);
DiyaSessionShell *shell = data;
diya_session_shell_lock(shell);
}
static gboolean restart(gpointer d)
@@ -37,11 +37,11 @@ static gboolean restart(gpointer d)
static void startup(GtkApplication *app, void *data)
{
DiyaShell *shell = data;
DiyaSessionShell *shell = data;
diya_shell_launcher_init(shell);
diya_shell_wayland_init(shell);
diya_shell_init_background(shell);
diya_session_shell_launcher_init(shell);
diya_session_shell_init_background(shell);
diya_shell_wayland_init(DIYA_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;}";
@@ -57,14 +57,14 @@ static void startup(GtkApplication *app, void *data)
g_unix_signal_add(SIGINT,(GSourceFunc)g_application_quit,(void*)app);
}
static void session_locked(DiyaShell* shell, void* data)
static void session_locked(DiyaSessionShell* shell, void* data)
{
(void)data;
assert(shell);
g_warning("session_locked callback triggered");
}
static void session_unlocked(DiyaShell* shell, void* data)
static void session_unlocked(DiyaSessionShell* shell, void* data)
{
(void)data;
assert(shell);
@@ -79,7 +79,7 @@ int main(int argc, char *argv[])
g_shell_argv[i] = argv[i];
}
GtkApplication *app = gtk_application_new("dev.iohub.diya.shell", G_APPLICATION_DEFAULT_FLAGS);
DiyaShell *shell = diya_shell_new(app);
DiyaSessionShell *shell = diya_session_shell_new(app);
g_signal_connect(app, "startup", G_CALLBACK(startup), (void *)shell);
g_signal_connect(app, "activate", G_CALLBACK(activate), (void *)shell);
g_signal_connect(shell, "session-locked", G_CALLBACK(session_locked), NULL);

View File

@@ -1,47 +1,35 @@
#include <assert.h>
#include <gtk4-session-lock.h>
#include "shell.h"
#define SHELL_DESCRIPTION "Diya GTK shell for wayland (diyac)"
#include "wayland.h"
#include "virtual-keyboard.h"
enum
{
NO_PROP,
SHELL_APP,
SHELL_BACKGROUND_WIDGET,
SHELL_LAUNCHPAD_WIDGET,
SHELL_LOCK_SESSION,
SHELL_WINDOWS,
SHELL_WAYLAND,
PROP_SHELL_WAYLAND,
N_PROPERTIES
};
static GParamSpec *shell_properties[N_PROPERTIES] = {0};
struct _DiyaShell
typedef struct _DiyaShellPrivate
{
DiyaObject parent;
GtkApplication* app;
GtkWindow* background;
GtkWindow* launcher;
GHashTable* windows;
GtkSessionLockInstance* lock;
DiyaObject parent;
DiyaWayland * wayland;
};
G_DEFINE_FINAL_TYPE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT)
DiyaVirtualKeyboard* vkb;
} DiyaShellPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT);
static void diya_shell_dispose(GObject* object)
{
g_debug("diya_shell_dispose: %s", diya_object_to_string(object));
DiyaShell * self = DIYA_SHELL(object);
g_hash_table_destroy(self->windows);
g_debug("diya_shell_dispose");
if(self->wayland)
DiyaShellPrivate* priv = diya_shell_get_instance_private(self);
if(priv->wayland)
{
g_object_unref(self->wayland);
}
if(self->lock)
{
g_object_unref(self->lock);
g_object_unref(priv->wayland);
}
G_OBJECT_CLASS(diya_shell_parent_class)->dispose(object);
}
@@ -49,23 +37,12 @@ static void diya_shell_dispose(GObject* object)
static void diya_shell_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
DiyaShell * self = DIYA_SHELL(object);
DiyaShellPrivate* priv = diya_shell_get_instance_private(self);
switch (property_id)
{
case SHELL_APP:
self->app = g_value_get_pointer(value);
assert(self->app);
break;
case SHELL_BACKGROUND_WIDGET:
self->background = g_value_get_pointer(value);
break;
case SHELL_LAUNCHPAD_WIDGET:
self->launcher = g_value_get_pointer(value);
break;
case SHELL_WAYLAND:
self->wayland = g_value_get_pointer(value);
break;
case SHELL_WINDOWS:
//self->windows = g_value_get_pointer(value);
case PROP_SHELL_WAYLAND:
priv->wayland = g_value_get_pointer(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -76,27 +53,11 @@ static void diya_shell_set_property(GObject *object, guint property_id, const GV
static void diya_shell_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
DiyaShell * self = DIYA_SHELL(object);
DiyaShellPrivate* priv = diya_shell_get_instance_private(self);
switch (property_id)
{
case SHELL_APP:
g_value_set_pointer(value, self->app);
break;
case SHELL_BACKGROUND_WIDGET:
g_value_set_pointer(value, self->background);
break;
case SHELL_LAUNCHPAD_WIDGET:
assert(self->launcher);
g_value_set_pointer(value, self->launcher);
break;
case SHELL_LOCK_SESSION:
assert(self->lock);
g_value_set_pointer(value, self->lock);
break;
case SHELL_WAYLAND:
g_value_set_pointer(value, self->wayland);
break;
case SHELL_WINDOWS:
g_value_set_pointer(value, self->windows);
case PROP_SHELL_WAYLAND:
g_value_set_pointer(value, priv->wayland);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -104,145 +65,11 @@ static void diya_shell_get_property(GObject *object, guint property_id, GValue *
}
}
static const gchar* diya_shell_to_string(DiyaObject* object)
{
(void) object;
return SHELL_DESCRIPTION;
}
static void diya_shell_class_init(DiyaShellClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
base_class->to_string = diya_shell_to_string;
gobject_class->dispose = diya_shell_dispose;
gobject_class->set_property = diya_shell_set_property;
gobject_class->get_property = diya_shell_get_property;
shell_properties[SHELL_APP] = g_param_spec_pointer("application", NULL, "Shell application", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
shell_properties[SHELL_BACKGROUND_WIDGET] = g_param_spec_pointer("background", NULL, "Shell background widget", G_PARAM_READWRITE );
shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer("launchpad", NULL, "Shell launchpad", G_PARAM_READWRITE );
shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer("session-lock", NULL, "Shell lock session", G_PARAM_READABLE );
shell_properties[SHELL_WINDOWS] = g_param_spec_pointer("windows", NULL, "Shell foreign windows", G_PARAM_READABLE);
shell_properties[SHELL_WAYLAND] = g_param_spec_pointer("wayland", NULL, "Shell wayland", G_PARAM_READWRITE );
g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties);
g_signal_new("foreign-window-changed",
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
g_signal_new("foreign-window-removed",
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
g_signal_new("session-locked",
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
g_signal_new("session-unlocked",
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
}
static void on_session_locked(GtkSessionLockInstance *lock, DiyaShell *shell) {
(void)lock;
assert(shell);
g_message("Session locked successfully");
g_signal_emit_by_name(shell, "session-locked");
}
/*
static void failed(GtkSessionLockInstance *lock, void *data) {
(void)lock;
(void)data;
g_critical("The session could not be locked");
g_application_quit(G_APPLICATION(app));
}
*/
static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaShell *shell) {
(void)lock;
assert(shell);
g_message("Session unlocked");
g_signal_emit_by_name(shell, "session-unlocked");
}
static void diya_shell_init(DiyaShell *self)
{
//self->app = NULL;
self->background = NULL;
self->launcher = NULL;
self->wayland = NULL;
self->lock = gtk_session_lock_instance_new();
g_signal_connect(self->lock, "locked", G_CALLBACK(on_session_locked), self);
// g_signal_connect(lock, "failed", G_CALLBACK(failed), NULL);
g_signal_connect(self->lock, "unlocked", G_CALLBACK(on_session_unlocked), self);
self->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
}
DiyaForeignWindow* diya_shell_get_window(DiyaShell * shell, gpointer handle)
{
return g_hash_table_lookup(shell->windows, handle);
}
gboolean diya_shell_add_window(DiyaShell * shell, DiyaForeignWindow * win)
{
gpointer handle;
g_object_get(win, "handle", &handle, NULL);
assert(handle);
return g_hash_table_insert(shell->windows,handle, win);
}
gboolean diya_shell_remove_window(DiyaShell * shell, DiyaForeignWindow * win)
{
gpointer handle;
g_object_get(win, "handle", &handle, NULL);
assert(handle);
return g_hash_table_remove(shell->windows,handle);
}
void diya_shell_remove_all_windows(DiyaShell * shell)
{
g_hash_table_destroy(shell->windows);
shell->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
}
DiyaShell * diya_shell_new(GtkApplication * app)
{
return DIYA_SHELL(g_object_new(DIYA_TYPE_SHELL,"application",app, NULL));
DiyaShellPrivate* priv = diya_shell_get_instance_private(self);
priv->wayland = NULL;
}
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell)
@@ -252,38 +79,17 @@ DiyaWayland * diya_shell_get_wayland(DiyaShell* shell)
assert(DIYA_IS_WAYLAND(wayland));
return wayland;
}
/*
static void on_orientation_changed (GtkWindow *window, WindowOrientation orientation, ToplevelData *data)
static void diya_shell_class_init(DiyaShellClass *class)
{
(void)window;
GtkOrientation orient_toplevel, orient_sub;
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
gobject_class->dispose = diya_shell_dispose;
gobject_class->set_property = diya_shell_set_property;
gobject_class->get_property = diya_shell_get_property;
switch (orientation) {
case WINDOW_ORIENTATION_HORIZONTAL:
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_HORIZONTAL;
break;
case WINDOW_ORIENTATION_VERTICAL:
orient_toplevel = GTK_ORIENTATION_VERTICAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
break;
case WINDOW_ORIENTATION_NONE:
orient_toplevel = GTK_ORIENTATION_HORIZONTAL;
orient_sub = GTK_ORIENTATION_VERTICAL;
break;
}
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->toplevel_box), orient_toplevel);
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->first_box), orient_sub);
gtk_orientable_set_orientation (GTK_ORIENTABLE (data->second_box), orient_sub);
//gtk_window_resize (window, 1, 1); // force the window to shrink to the smallest size it can
}
*/
/*
static void before_destroy (GtkWidget *win, GtkCssProvider *provider) {
GdkDisplay *display = gdk_display_get_default ();
gtk_style_context_remove_provider_for_display (display, GTK_STYLE_PROVIDER (provider));
}
*/
class->foreign_register = NULL;
class->virtual_keyboard_register = diya_virtual_keyboard_register;
shell_properties[PROP_SHELL_WAYLAND] = g_param_spec_pointer("wayland", NULL, "Shell wayland", G_PARAM_READWRITE); //
g_object_class_install_properties (gobject_class, N_PROPERTIES, shell_properties);
}

View File

@@ -1,31 +1,27 @@
#ifndef DIYA_SHELL_H
#define DIYA_SHELL_H
#include <gtk4-layer-shell.h>
#include <stdint.h>
#include "base.h"
enum diya_win_state
{
DIYA_WIN_STATE_NONE = 0,
DIYA_WIN_STATE_MINIMIZE = 1 << 0,
DIYA_WIN_STATE_MAXIMIZE = 1 << 1,
DIYA_WIN_STATE_FULLSCREEN = 1 << 2,
DIYA_WIN_STATE_FOCUS = 1 << 3,
};
#define DIYA_TYPE_SHELL (diya_shell_get_type ())
G_DECLARE_FINAL_TYPE (DiyaShell, diya_shell, DIYA, SHELL, DiyaObject)
#define DIYA_TYPE_SHELL (diya_shell_get_type())
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_FOREIGN_WINDOW (diya_foreign_window_get_type ())
G_DECLARE_FINAL_TYPE (DiyaForeignWindow, diya_foreign_window, DIYA, FOREIGN_WINDOW, DiyaShellObject)
struct wl_registry;
DiyaForeignWindow* diya_shell_get_window(DiyaShell * shell, gpointer handle);
gboolean diya_shell_add_window(DiyaShell * shell, DiyaForeignWindow * win);
gboolean diya_shell_remove_window(DiyaShell * shell, DiyaForeignWindow * win);
void diya_shell_remove_all_windows(DiyaShell * shell);
typedef void (*wl_protocol_manager_register_t)(struct wl_registry*, uint32_t,DiyaShell*);
DiyaShell * diya_shell_new(GtkApplication * app);
struct _DiyaShellClass
{
DiyaObjectClass parent_class;
wl_protocol_manager_register_t foreign_register;
wl_protocol_manager_register_t virtual_keyboard_register;
};
void diya_shell_wayland_init(DiyaShell *shell);
DiyaWayland * diya_shell_get_wayland(DiyaShell* shell);
#endif

View File

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

View File

@@ -1,8 +1,19 @@
#ifndef DIYA_VIRTUAL_KEYBOARD_H
#define DIYA_VIRTUAL_KEYBOARD_H
#include "virtual-keyboard-unstable-v1.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);
#endif

View File

@@ -1,15 +1,17 @@
#include <wayland-client-protocol.h>
#include <gdk/wayland/gdkwayland.h>
#include <assert.h>
#include "wlr-foreign-toplevel-management-unstable-v1.h"
#include "virtual-keyboard-unstable-v1.h"
#include "wayland.h"
#include "foreign.h"
struct _DiyaWayland
{
DiyaObject parent;
DiyaShellObject parent;
struct wl_compositor * compositor;
struct wl_shm * shm;
struct wl_seat * seat;
};
G_DEFINE_FINAL_TYPE(DiyaWayland, diya_wayland, DIYA_TYPE_SHELL_OBJECT)
@@ -17,7 +19,7 @@ static void diya_wayland_dispose(GObject* object)
{
(void) object;
//DiyaWayland * self = DIYA_WAYLAND(object);
g_debug("diya_wayland_dispose");
g_debug("diya_wayland_dispose: %s", diya_object_to_string(object));
G_OBJECT_CLASS(diya_wayland_parent_class)->dispose(object);
}
@@ -25,17 +27,24 @@ static void diya_wayland_init(DiyaWayland * self)
{
self->compositor = NULL;
self->shm = NULL;
self->seat = NULL;
}
static const gchar* diya_wayland_to_string(DiyaObject* object)
{
(void) object;
return "DiyaWayland - wayland client handle object";
}
static void diya_wayland_class_init(DiyaWaylandClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
//DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
gobject_class->dispose = diya_wayland_dispose;
//gobject_class->set_property = diya_lock_session_set_property;
//gobject_class->get_property = diya_lock_session_get_property;
//base_class->to_string = diya_lock_session_to_string;
base_class->to_string = diya_wayland_to_string;
}
@@ -52,18 +61,34 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
*/
(void) version;
DiyaShell * shell = data;
DiyaShellClass * class = DIYA_SHELL_GET_CLASS(shell);
DiyaWayland * wayland;
g_object_get(shell, "wayland", &wayland, NULL);
assert(DIYA_IS_WAYLAND(wayland));
g_debug("WAYLAND GLOBAL: %s", interface);
if (g_strcmp0(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0)
{
diya_shell_foreign_toplevel_register(registry, name, data);
if(class->foreign_register)
{
//diya_session_shell_foreign_toplevel_register(registry, name, data);
g_debug("Wayland: register shell foreign top level manager");
class->foreign_register(registry, name, data);
}
}
if (g_strcmp0(interface, zwp_virtual_keyboard_manager_v1_interface.name) == 0)
{
if(class->virtual_keyboard_register)
{
//diya_session_shell_foreign_toplevel_register(registry, name, data);
g_debug("Wayland: register virtual keyboard manager");
class->virtual_keyboard_register(registry, name, data);
}
}
/*
else if(!g_strcmp0(interface, ext_session_lock_manager_v1_interface.name))
{
diya_shell_session_lock_register(registry, name);
diya_session_shell_session_lock_register(registry, name);
}
*/
else if (strcmp(interface, wl_compositor_interface.name) == 0)
@@ -74,6 +99,10 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam
{
wayland->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
}
else if (strcmp(interface, wl_seat_interface.name) == 0)
{
wayland->seat = wl_registry_bind(registry, name, &wl_seat_interface, 7);
}
}
static void handle_global_remove(void *data, struct wl_registry *registry,
@@ -143,3 +172,9 @@ struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, gu
assert(self->shm);
return wl_shm_create_pool(self->shm, fd, size);
}
struct wl_seat* diya_wayland_get_seat(DiyaWayland* self)
{
assert(self->seat);
return self->seat;
}

View File

@@ -3,8 +3,8 @@
#include "shell.h"
void diya_shell_wayland_init(DiyaShell *shell);
struct wl_surface* diya_wayland_create_surface(DiyaWayland * self);
struct wl_output* diya_wayland_get_output(DiyaWayland * self, int index);
struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, guint size);
struct wl_seat* diya_wayland_get_seat(DiyaWayland* self);
#endif