Files
diya-shell/src/shell.c

837 lines
26 KiB
C

#include <glib-unix.h>
#include "shell.h"
#include "wayland.h"
#include "virtual-keyboard.h"
#include "input.h"
#include "idle.h"
#include "wlr-output-power-management-unstable-v1.h"
#include "hook.h"
#include <wayland-client-protocol.h>
#include <gdk/wayland/gdkwayland.h>
#include <gtk4-session-lock.h>
#define diya_shell_config_theme(priv) (g_strconcat(g_get_home_dir(), "/.themes/", priv->theme ? priv->theme : "default", "/gtk-4.0/gtk.css", NULL))
#define diya_shell_config_theme_dir(priv) (g_strconcat(g_get_home_dir(), "/.themes/", priv->theme ? priv->theme : "default", "/gtk-4.0", NULL))
enum
{
NO_PROP,
PROP_SHELL_WAYLAND,
PROP_SHELL_APP,
PROP_SHELL_NAME,
PROP_SHELL_THEME,
PROP_SHELL_IDLE_TO,
PROP_SHELL_LOCK,
N_PROPERTIES
};
static GParamSpec *shell_properties[N_PROPERTIES] = {0};
typedef struct _DiyaShellPrivate
{
DiyaObject parent;
DiyaWayland *wayland;
GtkApplication *app;
gchar *name;
GHashTable *vkbs;
GtkCssProvider *css_provider;
DiyaInput *input;
DiyaHook *files_hook;
gchar *theme;
DiyaIdleNotification *idle_notif;
GtkSessionLockInstance *lock;
} DiyaShellPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT);
static void diya_shell_finalize(GObject *object)
{
g_debug("diya_shell_finalize: %s", diya_object_to_string(object));
DiyaShell *self = DIYA_SHELL(object);
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if (priv->name)
{
g_free(priv->name);
priv->name = NULL;
}
if (priv->theme)
{
g_free(priv->theme);
priv->name = NULL;
}
g_hash_table_destroy(priv->vkbs);
G_OBJECT_CLASS(diya_shell_parent_class)->finalize(object);
}
static void diya_shell_dispose(GObject *object)
{
g_debug("diya_shell_dispose: %s", diya_object_to_string(object));
DiyaShell *self = DIYA_SHELL(object);
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if (priv->idle_notif)
{
g_object_unref(priv->idle_notif);
priv->idle_notif = NULL;
}
if (priv->lock)
{
if (gtk_session_lock_instance_is_locked(priv->lock))
{
gtk_session_lock_instance_unlock(priv->lock);
}
g_object_unref(priv->lock);
}
if (priv->wayland)
{
g_object_unref(priv->wayland);
}
if (priv->css_provider)
{
g_object_unref(priv->css_provider);
}
if (priv->input)
{
g_object_unref(priv->input);
}
if (priv->files_hook)
{
g_object_unref(priv->files_hook);
priv->files_hook = NULL;
}
G_OBJECT_CLASS(diya_shell_parent_class)->dispose(object);
if (priv->app)
{
g_application_quit(G_APPLICATION(priv->app));
}
}
static void diya_shell_reload_theme(DiyaShell *shell)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
if (priv->css_provider)
{
gtk_style_context_remove_provider_for_display(gdk_display_get_default(), GTK_STYLE_PROVIDER(priv->css_provider));
g_object_unref(priv->css_provider);
priv->css_provider = NULL;
}
priv->css_provider = gtk_css_provider_new();
gchar *css_file = diya_shell_config_theme(priv);
g_debug("diya_shell_reload_theme: Looking for css file: %s", css_file);
if (g_file_test(css_file, G_FILE_TEST_EXISTS))
{
GFile *file = g_file_new_for_path(css_file);
gtk_css_provider_load_from_file(priv->css_provider, file);
g_object_unref(file);
}
else
{
g_warning("diya_shell_reload_theme: Unable to load CSS from file: %s. Fallback to default theme", css_file);
gchar *css_resource = g_strconcat("/dev/iohub/diya/shell/css/", priv->name, ".css", NULL);
gtk_css_provider_load_from_resource(priv->css_provider, css_resource);
g_free(css_resource);
}
g_free(css_file);
gtk_style_context_add_provider_for_display(
gdk_display_get_default(),
GTK_STYLE_PROVIDER(priv->css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
}
void diya_shell_reload(DiyaShell *self)
{
diya_shell_reload_theme(self);
}
void on_diya_shell_theme_file_changed(GFileMonitor *monitor, GFile *file, GFile *other, GFileMonitorEvent evtype, gpointer user_data)
{
(void)monitor;
(void)other;
DiyaShell *shell = user_data;
char *fpath = g_file_get_path(file);
g_debug("%s event %x", fpath, evtype);
switch (evtype)
{
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
case G_FILE_MONITOR_EVENT_DELETED:
case G_FILE_MONITOR_EVENT_RENAMED:
case G_FILE_MONITOR_EVENT_MOVED_IN:
case G_FILE_MONITOR_EVENT_MOVED_OUT:
// case G_FILE_MONITOR_EVENT_CHANGED:
//case G_FILE_MONITOR_EVENT_CREATED:
diya_shell_reload_theme(shell);
break;
default:
break;
}
g_free(fpath);
}
static void diya_shell_idle(DiyaIdleNotification *notif, DiyaShell *shell)
{
assert(DIYA_IS_IDLE_NOTIFICATION(notif));
g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_IDLE);
}
static void diya_shell_resume(DiyaIdleNotification *notif, DiyaShell *shell)
{
assert(DIYA_IS_IDLE_NOTIFICATION(notif));
g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_RESUME);
}
static void on_gtk_app_startup(GtkApplication *app, void *data)
{
(void)app;
DiyaShell *shell = data;
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
priv->wayland = diya_wayland_new(DIYA_SHELL(shell));
DiyaShellClass *class = DIYA_SHELL_GET_CLASS(shell);
// log all environment variables in debug
for (gchar **env = g_get_environ(); *env != NULL; env++)
{
g_debug("ENV: %s", *env);
}
// diya_shell_reload(shell);
if (class->startup_handle)
{
class->startup_handle(shell);
}
/*
if (class->monitor_changed_handle)
{
GListModel *monitor_list = gdk_display_get_monitors(gdk_display_get_default());
g_debug("listen to monitor changed");
g_signal_connect(monitor_list, "items-changed", G_CALLBACK(class->monitor_changed_handle), shell);
}
*/
}
static void on_gtk_app_active(GtkApplication *app, void *data)
{
(void)app;
DiyaShell *shell = data;
DiyaShellClass *class = DIYA_SHELL_GET_CLASS(shell);
if (class->active_handle)
{
class->active_handle(shell);
}
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
if(!priv->theme)
{
// read envar
const char *default_theme = g_getenv(DIYA_ENV_THEME);
if (!default_theme)
{
default_theme = "default";
}
g_object_set(shell, DIYA_PROP_SHELL_THEME, default_theme, NULL);
}
}
static gboolean diya_shell_sigint_handle(gpointer data)
{
g_object_unref(DIYA_SHELL(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);
if (priv->app)
{
return;
}
priv->app = gtk_application_new(priv->name, G_APPLICATION_DEFAULT_FLAGS);
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_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)
{
DiyaShell *self = DIYA_SHELL(object);
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
switch (property_id)
{
case PROP_SHELL_NAME:
if (priv->name)
{
return;
}
priv->name = g_strdup(g_value_get_string(value));
init_gtk_application(self);
break;
case PROP_SHELL_IDLE_TO:
if(priv->idle_notif)
{
// g_signal_emit_by_name(self, DIYA_SIGNAL_SHELL_RESUME);
g_object_unref(priv->idle_notif);
}
priv->idle_notif = diya_shell_get_idle_notification(self, g_value_get_uint(value));
g_signal_connect(priv->idle_notif, DIYA_SIGNAL_IDLE_NOTIF_IDLE, G_CALLBACK(diya_shell_idle), self);
g_signal_connect(priv->idle_notif, DIYA_SIGNAL_IDLE_NOTIF_RESUME, G_CALLBACK(diya_shell_resume), self);
break;
case PROP_SHELL_THEME:
{
const gchar *theme = g_value_get_string(value);
gchar* dir = NULL;
if (!priv->theme || !g_str_equal(priv->theme, theme))
{
if (priv->theme)
{
dir = diya_shell_config_theme_dir(priv);
diya_shell_unwatch_file(self, dir);
g_free(dir);
g_free(priv->theme);
}
priv->theme = g_strdup(theme);
dir = diya_shell_config_theme_dir(priv);
g_mkdir_with_parents((const gchar *)dir, 0755);
diya_shell_watch_file(self, dir, G_CALLBACK(on_diya_shell_theme_file_changed), (gpointer)self);
g_free(dir);
diya_shell_reload_theme(self);
}
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
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 PROP_SHELL_WAYLAND:
g_value_set_pointer(value, priv->wayland);
break;
case PROP_SHELL_APP:
g_value_set_pointer(value, priv->app);
break;
case PROP_SHELL_NAME:
g_value_set_string(value, priv->name);
break;
case PROP_SHELL_THEME:
g_value_set_string(value, priv->theme);
break;
case PROP_SHELL_LOCK:
// assert(priv->lock);
g_value_set_pointer(value, priv->lock);
break;
case PROP_SHELL_IDLE_TO:
if(priv->idle_notif)
{
g_value_set_uint(value, diya_idle_notification_get_timeout(priv->idle_notif));
}
else
{
g_value_set_uint(value, 0);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void on_shell_locked(GtkSessionLockInstance *lock, DiyaShell *shell)
{
(void)lock;
assert(shell);
g_message("Shell locked successfully");
g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_LOCKED);
}
static void on_shell_unlocked(GtkSessionLockInstance *lock, DiyaShell *shell)
{
(void)lock;
assert(shell);
g_message("Shell unlocked");
g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_UNLOCKED);
}
static void on_shell_lock_failed(GtkSessionLockInstance *lock, DiyaShell *shell)
{
(void)lock;
assert(shell);
g_critical("Unable to lock shell");
g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_LOCK_FAILED);
}
static void on_monitor_present(GtkSessionLockInstance* lock, GdkMonitor *monitor, DiyaShell *shell)
{
assert(shell);
g_debug("Build lock window for monitor");
DiyaShellClass *class = DIYA_SHELL_GET_CLASS(shell);
if(class->build_lock_window)
{
GtkWindow* window = class->build_lock_window(shell);
gtk_session_lock_instance_assign_window_to_monitor(lock, window, monitor);
}
}
static void diya_shell_init_lock(DiyaShell* self)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if(priv->lock)
{
return;
}
priv->lock = gtk_session_lock_instance_new();
g_signal_connect(priv->lock, DIYA_SIGNAL_SHELL_LOCKED, G_CALLBACK(on_shell_locked), self);
g_signal_connect(priv->lock, "failed", G_CALLBACK(on_shell_lock_failed), self);
g_signal_connect(priv->lock, DIYA_SIGNAL_SHELL_UNLOCKED, G_CALLBACK(on_shell_unlocked), self);
g_signal_connect(priv->lock, "monitor", G_CALLBACK(on_monitor_present), self);
}
static void diya_shell_init(DiyaShell *self)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
priv->wayland = NULL;
priv->app = NULL;
priv->name = NULL;
priv->vkbs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
priv->css_provider = NULL;
priv->input = NULL;
priv->files_hook = NULL;
priv->theme = NULL;
priv->idle_notif = NULL;
priv->lock = NULL;
}
DiyaWayland *diya_shell_get_wayland(DiyaShell *shell)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
assert(DIYA_IS_WAYLAND(priv->wayland));
return priv->wayland;
}
GtkApplication *diya_shell_get_application(DiyaShell *shell)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
assert(GTK_IS_APPLICATION(priv->app));
return priv->app;
}
const char *diya_shell_get_name(DiyaShell *shell)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
return priv->name;
}
static const gchar *diya_shell_to_string(DiyaObject *object)
{
return diya_shell_get_name(DIYA_SHELL(object));
}
static void diya_shell_class_init(DiyaShellClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
gobject_class->dispose = diya_shell_dispose;
gobject_class->finalize = diya_shell_finalize;
gobject_class->set_property = diya_shell_set_property;
gobject_class->get_property = diya_shell_get_property;
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
base_class->to_string = diya_shell_to_string;
class->foreign_register = NULL;
class->virtual_keyboard_register = diya_virtual_keyboard_register;
class->build_lock_window = NULL;
class->startup_handle = NULL;
class->active_handle = NULL;
class->reload_handle = NULL;
shell_properties[PROP_SHELL_WAYLAND] = g_param_spec_pointer(DIYA_PROP_SHELL_WAYLAND, NULL, "Shell wayland", G_PARAM_READABLE); //
shell_properties[PROP_SHELL_NAME] = g_param_spec_string(DIYA_PROP_SHELL_NAME, NULL, "Shell name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
shell_properties[PROP_SHELL_APP] = g_param_spec_pointer(DIYA_PROP_SHELL_APPLICATION, NULL, "Shell application", G_PARAM_READABLE);
shell_properties[PROP_SHELL_THEME] = g_param_spec_string(DIYA_PROP_SHELL_THEME, NULL, "Shell theme", NULL, G_PARAM_READWRITE);
shell_properties[PROP_SHELL_IDLE_TO] = g_param_spec_uint(DIYA_PROP_SHELL_IDLE_TIMEOUT, NULL, "Shell IDLE timeout", 0, UINT32_MAX ,DEFAULT_IDLE_TIMEOUT, G_PARAM_READWRITE);
shell_properties[PROP_SHELL_LOCK] = g_param_spec_pointer(DIYA_PROP_SHELL_LOCK, NULL, "Shell lock", G_PARAM_READABLE);
g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties);
// define signals
g_signal_new(DIYA_SIGNAL_SHELL_KEYBOARD_ENTER,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
3,
G_TYPE_POINTER,
G_TYPE_POINTER,
G_TYPE_POINTER);
g_signal_new(DIYA_SIGNAL_SHELL_KEYBOARD_MODIFIER_CHANGED,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
2,
G_TYPE_POINTER,
G_TYPE_POINTER);
g_signal_new(DIYA_SIGNAL_SHELL_KEYBOARD_LEAVE,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
g_signal_new(DIYA_SIGNAL_SHELL_KEY_PRESSED,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
4,
G_TYPE_POINTER,
G_TYPE_POINTER,
G_TYPE_UINT,
G_TYPE_UINT);
g_signal_new(DIYA_SIGNAL_SHELL_KEY_RELEASED,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
4,
G_TYPE_POINTER,
G_TYPE_POINTER,
G_TYPE_UINT,
G_TYPE_UINT);
g_signal_new(DIYA_SIGNAL_SHELL_IDLE,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
g_signal_new(DIYA_SIGNAL_SHELL_RESUME,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
g_signal_new(DIYA_SIGNAL_SHELL_WINDOW_ENTER,
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(DIYA_SIGNAL_SHELL_WINDOW_LEAVE,
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(DIYA_SIGNAL_SHELL_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(DIYA_SIGNAL_SHELL_UNLOCKED,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
g_signal_new(DIYA_SIGNAL_SHELL_LOCK_FAILED,
DIYA_TYPE_SHELL,
G_SIGNAL_DETAILED |
G_SIGNAL_ACTION |
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
0);
}
static int diya_shell_handle_local_options(GApplication *application, GVariantDict *options, gpointer user_data)
{
(void)application;
(void)user_data;
#ifdef __SHELL_VERSION__
guint32 count;
if (g_variant_dict_lookup(options, "version", "b", &count))
{
g_print("Shell version: %s\n", __SHELL_VERSION__);
return EXIT_SUCCESS;
}
#endif
return -1;
}
int diya_shell_run(DiyaShell *shell, int argc, char **argv)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
assert(GTK_IS_APPLICATION(priv->app));
GtkApplication *app = priv->app;
gchar *path = NULL;
if(g_getenv("GSETTINGS_SCHEMA_DIR") == NULL)
{
path = g_strconcat(g_get_user_config_dir(), "/diya/schemas/", NULL);
g_mkdir_with_parents((const gchar *)path, 0755);
g_setenv("GSETTINGS_SCHEMA_DIR", path, FALSE);
g_free(path);
}
/*
// theme dir
gchar *path = g_strconcat(g_get_user_config_dir(), "/diya/themes/", NULL);
g_mkdir_with_parents((const gchar *)path, 0755);
g_free(path);
*/
// keymap dir
path = g_strconcat(g_get_user_config_dir(), "/diya/xkb/", NULL);
g_mkdir_with_parents((const gchar *)path, 0755);
g_free(path);
const GOptionEntry cmd_params[] =
{
#ifdef __SHELL_VERSION__
{
.long_name = "version",
.short_name = 'v',
.flags = G_OPTION_FLAG_NONE,
.arg = G_OPTION_ARG_NONE,
.arg_data = NULL,
.description = "Show version information",
.arg_description = NULL,
},
#endif
{NULL}
};
g_application_add_main_option_entries(G_APPLICATION(app), cmd_params);
g_signal_connect(app, "handle-local-options", G_CALLBACK(diya_shell_handle_local_options), shell);
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)g_strdup(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, (gpointer)g_strdup("default"), diya_virtual_keyboard_new(shell, NULL));
}
vkb = g_hash_table_lookup(priv->vkbs, "default");
}
return vkb;
}
void diya_shell_monitor_input(DiyaShell *self)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if (priv->input)
{
return;
}
priv->input = diya_input_new(self);
}
gboolean diya_shell_watch_file(DiyaShell *self, const gchar *file, GCallback callback, gpointer userdata)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if (!priv->files_hook)
{
priv->files_hook = diya_hook_new();
}
return diya_hook_install(priv->files_hook, file, callback, userdata, true);
}
void diya_shell_unwatch_file(DiyaShell *self, const gchar *file)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if (priv->files_hook)
{
diya_hook_uninstall(priv->files_hook, file);
}
}
void diya_shell_launch(DiyaShell *self, GAppInfo *app)
{
GError *error = NULL;
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
GAppLaunchContext *context = g_app_launch_context_new();
if (priv->theme)
{
g_app_launch_context_setenv(context, "GTK_THEME", priv->theme);
}
g_app_info_launch(app, NULL, context, &error);
g_object_unref(context);
if (error)
{
g_critical("Unable to launch application: %s", error->message);
g_error_free(error);
return;
}
}
void diya_shell_power_display(DiyaShell* self, gboolean mode)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
struct zwlr_output_power_manager_v1 * mngr = diya_wayland_get_output_mngr(priv->wayland);
if(!mngr)
{
g_warning("Output power manager protocol is not available");
return;
}
GdkDisplay *display = gdk_display_get_default();
GListModel *monitors = gdk_display_get_monitors(display);
guint n_monitors = g_list_model_get_n_items(monitors);
for (guint i = 0; i < n_monitors; ++i)
{
GdkMonitor *monitor = g_list_model_get_item(monitors, i);
struct wl_output * output = gdk_wayland_monitor_get_wl_output(monitor);
struct zwlr_output_power_v1 * output_power = zwlr_output_power_manager_v1_get_output_power(mngr, output);
zwlr_output_power_v1_set_mode(output_power, mode? ZWLR_OUTPUT_POWER_V1_MODE_ON: ZWLR_OUTPUT_POWER_V1_MODE_OFF);
zwlr_output_power_v1_destroy(output_power);
}
}
gboolean diya_shell_watch_script(DiyaShell* self, const gchar* script)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if (!priv->files_hook)
{
priv->files_hook = diya_hook_new();
}
return diya_hook_install_lua(priv->files_hook, script);
}
void diya_shell_lock(DiyaShell* self)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if(!priv->lock)
{
diya_shell_init_lock(self);
}
if(gtk_session_lock_instance_is_locked(priv->lock))
{
g_warning("Shell session is already locked, doing nothing");
return;
}
if(!gtk_session_lock_instance_lock(priv->lock))
{
g_error("gtk_session_lock_instance_lock:Unable to lock the current session");
return;
}
}
void diya_shell_unlock(DiyaShell* self)
{
DiyaShellPrivate *priv = diya_shell_get_instance_private(self);
if(priv->lock)
{
gtk_session_lock_instance_unlock(priv->lock);
g_debug("gtk_session_lock_instance_unlock: Shell unlocked");
}
}