feat: Add hook mechanism + use gsettings:
- Allow to install hooks that execute lua scripts on changes of watched files - Use gsetting to store shell parameters such as: theme, idle-timeout, etc.
This commit is contained in:
9
hooks/check_compiled_schemas.lua
Normal file
9
hooks/check_compiled_schemas.lua
Normal file
@@ -0,0 +1,9 @@
|
||||
local compiled_schemas = diya.system.user_config_dir() .. "/diya/schemas/gschemas.compiled"
|
||||
|
||||
if not diya.system.file_exists(compiled_schemas) then
|
||||
diya.system.log_info("Regenerating "..compiled_schemas)
|
||||
local script_path = debug.getinfo(1, "S").source:sub(2)
|
||||
local script_dir = script_path:match("(.*/)")
|
||||
local script_compile_schemas = script_dir .. "/compile_schemas.lua"
|
||||
dofile(script_compile_schemas)
|
||||
end
|
||||
21
hooks/compile_schemas.lua
Normal file
21
hooks/compile_schemas.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
local schemas_dir = diya.system.user_data_dir() .. "/glib-2.0/schemas"
|
||||
|
||||
local target_dir = diya.system.user_config_dir() .. "/diya/schemas/"
|
||||
|
||||
local session_schemas = schemas_dir.."/dev.iohub.diya.session.gschema.xml"
|
||||
if not diya.system.file_exists(session_schemas) then
|
||||
-- copy session schemas if not exists
|
||||
diya.system.save_resource("/dev/iohub/diya/shell/schemas/session.gschema.xml", session_schemas)
|
||||
return
|
||||
end
|
||||
|
||||
-- create the compiled schemas dir if not exists
|
||||
diya.system.mkdir(target_dir)
|
||||
|
||||
local cmd = "/usr/bin/glib-compile-schemas --targetdir="..target_dir.." "..schemas_dir -- .." &"
|
||||
diya.system.log_info("Executing: "..cmd)
|
||||
local handle = io.popen(cmd)
|
||||
local result = handle:read("*a") -- Reads all output
|
||||
handle:close()
|
||||
|
||||
diya.system.log_info(result)
|
||||
21
hooks/hooks.lua
Normal file
21
hooks/hooks.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
local script_path = debug.getinfo(1, "S").source:sub(2)
|
||||
local script_dir = script_path:match("(.*/)")
|
||||
local schemas_dir = diya.system.user_data_dir() .. "/glib-2.0/schemas"
|
||||
|
||||
-- create the schemas dir if not exists
|
||||
diya.system.mkdir(schemas_dir)
|
||||
|
||||
local script_compile_schemas = script_dir .. "/compile_schemas.lua"
|
||||
-- install hook on schemas dir
|
||||
diya.hook.changed(schemas_dir, script_compile_schemas, false)
|
||||
|
||||
local session_schemas = schemas_dir.."/dev.iohub.diya.session.gschema.xml"
|
||||
if not diya.system.file_exists(session_schemas) then
|
||||
-- copy session schemas if not exists
|
||||
diya.system.save_resource("/dev/iohub/diya/shell/schemas/session.gschema.xml", session_schemas)
|
||||
end
|
||||
|
||||
local compiled_schemas = diya.system.user_config_dir() .. "/diya/schemas/gschemas.compiled"
|
||||
local script_check_schema = script_dir .. "/check_compiled_schemas.lua"
|
||||
diya.hook.changed(compiled_schemas, script_check_schema, true)
|
||||
24
meson.build
24
meson.build
@@ -28,6 +28,7 @@ wayland_protocols = dependency('wayland-protocols', version: '>=1.16')
|
||||
|
||||
wl_protocol_dir = wayland_protocols.get_variable('pkgdatadir')
|
||||
|
||||
lua = dependency('lua')
|
||||
|
||||
# pkg_config = import('pkgconfig')
|
||||
# gnome = import('gnome')
|
||||
@@ -68,6 +69,7 @@ base = [
|
||||
'src/widgets/virtual-keyboard-widgets.c',
|
||||
'src/files-monitor.c',
|
||||
'src/idle.c',
|
||||
'src/hook.c',
|
||||
wayland_targets
|
||||
]
|
||||
|
||||
@@ -84,15 +86,29 @@ dm_src = [
|
||||
'src/widgets/dashboard-widget.c',
|
||||
]
|
||||
|
||||
buil_dep = [gtk, gtk_layer_shell, wayland_client, xkbcommon]
|
||||
build_dep = [gtk, gtk_layer_shell, wayland_client, xkbcommon, lua]
|
||||
|
||||
session_resource = gnome.compile_resources('session-resources','resources/gresource-session.xml')
|
||||
|
||||
session_schemas_files = [
|
||||
'resources/schemas/dev.iohub.diya.session.gschema.xml',
|
||||
]
|
||||
session_schema = custom_target('gschemas.compiled',
|
||||
output: 'gschemas.compiled',
|
||||
command: [
|
||||
find_program('glib-compile-schemas'),
|
||||
'--targetdir='+meson.current_build_dir(),
|
||||
meson.current_source_dir() / 'resources/schemas'
|
||||
],
|
||||
depend_files: session_schemas_files,
|
||||
build_by_default: true,
|
||||
install: false,
|
||||
)
|
||||
executable(
|
||||
'diya-shell',
|
||||
dm_src,
|
||||
session_resource,
|
||||
dependencies: buil_dep,
|
||||
session_schema,
|
||||
dependencies: build_dep,
|
||||
include_directories : incdir)
|
||||
|
||||
login_src = [
|
||||
@@ -107,5 +123,5 @@ executable(
|
||||
'diya-login-shell',
|
||||
login_src,
|
||||
login_resource,
|
||||
dependencies: buil_dep,
|
||||
dependencies: build_dep,
|
||||
include_directories : incdir)
|
||||
@@ -12,7 +12,8 @@ diya-dashboard
|
||||
|
||||
#diya_shell_background
|
||||
{
|
||||
background-image:url("file:///etc/xdg/labwc/wpp.jpg");
|
||||
/*background-image:url("file:///etc/xdg/labwc/wpp.jpg");*/
|
||||
background-color: violet;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/dev/iohub/diya/shell/css">
|
||||
<file alias="dev.iohub.diya.login-shell.css">resources/css/login-shell.css</file>
|
||||
<file alias="dev.iohub.diya.login.css">resources/css/login-shell.css</file>
|
||||
<file alias="virtual-keyboard.css">resources/css/virtual-keyboard.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/dev/iohub/diya/shell/vkb">
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
<file alias="taskbar.ui">resources/ui/taskbar.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/dev/iohub/diya/shell/css">
|
||||
<file alias="dev.iohub.diya.session-shell.css">resources/css/session-shell.css</file>
|
||||
<file alias="dev.iohub.diya.session.css">resources/css/session-shell.css</file>
|
||||
<file alias="virtual-keyboard.css">resources/css/virtual-keyboard.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/dev/iohub/diya/shell/schemas">
|
||||
<file alias="session.gschema.xml">resources/schemas/dev.iohub.diya.session.gschema.xml</file>
|
||||
</gresource>
|
||||
<gresource prefix="/dev/iohub/diya/shell/icons/scalable">
|
||||
<file alias="gear">resources/icons/scalable/gear.svg</file>
|
||||
</gresource>
|
||||
|
||||
15
resources/schemas/dev.iohub.diya.session.gschema.xml
Normal file
15
resources/schemas/dev.iohub.diya.session.gschema.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schemalist>
|
||||
<schema path="/dev/iohub/diya/session/" id="dev.iohub.diya.session">
|
||||
<key name="idle-timeout" type="i">
|
||||
<default>60000</default>
|
||||
<summary>Idle timeout</summary>
|
||||
<description>The time in milliseconds before the session is considered idle.</description>
|
||||
</key>
|
||||
<key name="theme" type="s">
|
||||
<default>'diya'</default>
|
||||
<summary>System theme</summary>
|
||||
<description>The system theme used for the session.</description>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
@@ -28,6 +28,14 @@
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="btn_test">
|
||||
<property name="visible">1</property>
|
||||
<property name="label" translatable="yes">Test</property>
|
||||
<!--signal name="toggled" handler="diya_dashboard_toggle"/-->
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
||||
@@ -10,5 +10,5 @@ G_DECLARE_FINAL_TYPE (DiyaFilesMonitor, diya_files_monitor, DIYA, FILES_MONITOR,
|
||||
DiyaFilesMonitor* diya_files_monitor_new();
|
||||
gboolean diya_files_monitor_watch(DiyaFilesMonitor* monitor, const gchar* file, GCallback callback, gpointer userdata);
|
||||
void diya_files_monitor_unwatch(DiyaFilesMonitor* monitor, const gchar* file);
|
||||
|
||||
gboolean diya_files_monitor_is_watched(DiyaFilesMonitor* monitor, const gchar* file);
|
||||
#endif
|
||||
@@ -55,37 +55,51 @@ DiyaFilesMonitor* diya_files_monitor_new()
|
||||
return self;
|
||||
}
|
||||
|
||||
gboolean diya_files_monitor_watch(DiyaFilesMonitor* self, const gchar* path, GCallback callback, gpointer userdata)
|
||||
gboolean diya_files_monitor_watch(DiyaFilesMonitor* self, const gchar* any_path, GCallback callback, gpointer userdata)
|
||||
{
|
||||
GFileMonitor* fm = NULL;
|
||||
if(!g_hash_table_contains(self->watch_table, path))
|
||||
char* abs_path = g_canonicalize_filename(any_path, NULL);
|
||||
if(!g_hash_table_contains(self->watch_table, abs_path))
|
||||
{
|
||||
GError *err = NULL;
|
||||
GFile* file = g_file_new_for_path(path);
|
||||
GFile* file = g_file_new_for_path(abs_path);
|
||||
fm = g_file_monitor(file, G_FILE_MONITOR_WATCH_MOVES, NULL, &err);
|
||||
g_object_unref(file);
|
||||
if (err)
|
||||
{
|
||||
g_warning("Unable to watch file %s: %s", path, err->message);
|
||||
g_warning("Unable to watch file %s: %s", abs_path, err->message);
|
||||
g_error_free(err);
|
||||
g_free(abs_path);
|
||||
return false;
|
||||
}
|
||||
g_info("DiyaFilesMonitor: watch new file: %s", path);
|
||||
g_hash_table_insert(self->watch_table, (gpointer)g_strdup(path), fm);
|
||||
g_info("DiyaFilesMonitor: watch new file: %s", abs_path);
|
||||
g_hash_table_insert(self->watch_table, (gpointer)g_strdup(abs_path), fm);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_info("File %s is already watched, register callback handle to the existing watcher", path);
|
||||
fm = g_hash_table_lookup(self->watch_table, path);
|
||||
g_info("File %s is already watched, register callback handle to the existing watcher", abs_path);
|
||||
fm = g_hash_table_lookup(self->watch_table, abs_path);
|
||||
}
|
||||
g_signal_connect(G_OBJECT(fm), "changed", callback, userdata);
|
||||
g_free(abs_path);
|
||||
return true;
|
||||
}
|
||||
|
||||
void diya_files_monitor_unwatch(DiyaFilesMonitor* self, const gchar* path)
|
||||
void diya_files_monitor_unwatch(DiyaFilesMonitor* self, const gchar* any_path)
|
||||
{
|
||||
if(!g_hash_table_contains(self->watch_table, path))
|
||||
gchar* abs_path = g_canonicalize_filename(any_path, NULL);
|
||||
g_debug("Unwatching: %s", abs_path);
|
||||
if(g_hash_table_contains(self->watch_table, abs_path))
|
||||
{
|
||||
g_hash_table_remove(self->watch_table, (gconstpointer)path);
|
||||
g_hash_table_remove(self->watch_table, (gconstpointer)abs_path);
|
||||
}
|
||||
g_free(abs_path);
|
||||
}
|
||||
|
||||
gboolean diya_files_monitor_is_watched(DiyaFilesMonitor* self, const gchar* file)
|
||||
{
|
||||
gchar* abs_path = g_canonicalize_filename(file, NULL);
|
||||
gboolean watched = g_hash_table_contains(self->watch_table, abs_path);
|
||||
g_free(abs_path);
|
||||
return watched;
|
||||
}
|
||||
419
src/hook.c
Normal file
419
src/hook.c
Normal file
@@ -0,0 +1,419 @@
|
||||
#include <glib-unix.h>
|
||||
#include <gio/gio.h>
|
||||
#include "hook.h"
|
||||
#include "files-monior.h"
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
struct _DiyaHookHandle
|
||||
{
|
||||
DiyaObject parent;
|
||||
DiyaHook* hook;
|
||||
gchar* script;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaHookHandle, diya_hook_handle, DIYA_TYPE_OBJECT)
|
||||
|
||||
static void diya_hook_handle_finalize(GObject* object)
|
||||
{
|
||||
DiyaHookHandle* self = DIYA_HOOK_HANDLE(object);
|
||||
g_debug("diya_hook_handle_finalize: %s", diya_object_to_string(object));
|
||||
if(self->script)
|
||||
{
|
||||
g_free(self->script);
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_hook_handle_dispose(GObject* object)
|
||||
{
|
||||
(void) object;
|
||||
g_debug("diya_hook_disponse: %s", diya_object_to_string(object));
|
||||
}
|
||||
|
||||
static void diya_hook_handle_init(DiyaHookHandle* self)
|
||||
{
|
||||
self->hook = NULL;
|
||||
self->script = NULL;
|
||||
}
|
||||
|
||||
struct _DiyaHook
|
||||
{
|
||||
DiyaObject parent;
|
||||
DiyaFilesMonitor *files_watchdog;
|
||||
GHashTable* lua_hooks;
|
||||
};
|
||||
|
||||
static const gchar *diya_hook_handle_to_string(DiyaObject *object)
|
||||
{
|
||||
DiyaHookHandle* self = DIYA_HOOK_HANDLE(object);
|
||||
return self->script;
|
||||
}
|
||||
|
||||
static void diya_hook_handle_class_init(DiyaHookHandleClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||
|
||||
gobject_class->finalize = diya_hook_handle_finalize;
|
||||
gobject_class->dispose = diya_hook_handle_dispose;
|
||||
base_class->to_string = diya_hook_handle_to_string;
|
||||
}
|
||||
|
||||
static DiyaHookHandle* diya_hook_handle_new(DiyaHook* hook, const gchar* script)
|
||||
{
|
||||
DiyaHookHandle* self = DIYA_HOOK_HANDLE(g_object_new(DIYA_TYPE_HOOK_HANDLE, NULL));
|
||||
self->hook = hook;
|
||||
self->script = g_strdup(script);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
G_DEFINE_FINAL_TYPE(DiyaHook, diya_hook, DIYA_TYPE_OBJECT)
|
||||
|
||||
static void execute_hook_script(DiyaHook* self, const gchar* script, gboolean allow_install_hook);
|
||||
|
||||
static void diya_hook_finalize(GObject *object)
|
||||
{
|
||||
DiyaHook *self = DIYA_HOOK(object);
|
||||
g_debug("diya_hook_finalize: %s", diya_object_to_string(object));
|
||||
if(self->lua_hooks)
|
||||
{
|
||||
g_hash_table_destroy(self->lua_hooks);
|
||||
}
|
||||
G_OBJECT_CLASS(diya_hook_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void diya_hook_dispose(GObject *object)
|
||||
{
|
||||
DiyaHook *self = DIYA_HOOK(object);
|
||||
g_debug("diya_hook_dispose: %s", diya_object_to_string(object));
|
||||
if(self->files_watchdog)
|
||||
{
|
||||
g_object_unref(self->files_watchdog);
|
||||
self->files_watchdog = NULL;
|
||||
}
|
||||
G_OBJECT_CLASS(diya_hook_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void diya_hook_init(DiyaHook *self)
|
||||
{
|
||||
self->files_watchdog = diya_files_monitor_new();
|
||||
self->lua_hooks = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy);
|
||||
}
|
||||
|
||||
static const gchar *diya_hook_to_string(DiyaObject *object)
|
||||
{
|
||||
(void) object;
|
||||
return "Diya Hook";
|
||||
}
|
||||
|
||||
static void diya_hook_class_init(DiyaHookClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||
|
||||
gobject_class->finalize = diya_hook_finalize;
|
||||
gobject_class->dispose = diya_hook_dispose;
|
||||
base_class->to_string = diya_hook_to_string;
|
||||
}
|
||||
|
||||
DiyaHook* diya_hook_new()
|
||||
{
|
||||
DiyaHook* self = DIYA_HOOK(g_object_new(DIYA_TYPE_HOOK, NULL));
|
||||
return self;
|
||||
}
|
||||
|
||||
static void reset_lua_hook(DiyaHook* self, const gchar* hook, gboolean init)
|
||||
{
|
||||
gchar* abs_path = g_canonicalize_filename(hook, NULL);
|
||||
if(g_hash_table_contains(self->lua_hooks, abs_path))
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gchar* target;
|
||||
DiyaHookHandle* handle;
|
||||
g_hash_table_iter_init (&iter, g_hash_table_lookup(self->lua_hooks, abs_path));
|
||||
while (g_hash_table_iter_next(&iter, (gpointer) &target, (gpointer) &handle))
|
||||
{
|
||||
g_info("Remove lua hook %s for: %s", handle->script, target);
|
||||
diya_files_monitor_unwatch(self->files_watchdog, target);
|
||||
}
|
||||
g_hash_table_remove(self->lua_hooks, abs_path);
|
||||
}
|
||||
if(init)
|
||||
{
|
||||
g_hash_table_insert(self->lua_hooks,abs_path, g_hash_table_new_full(g_str_hash,g_str_equal,g_free,g_object_unref));
|
||||
}
|
||||
}
|
||||
|
||||
void on_diya_hook_on_file_changed(GFileMonitor *monitor, GFile *file, GFile *other, GFileMonitorEvent evtype, gpointer user_data)
|
||||
{
|
||||
(void)monitor;
|
||||
(void)other;
|
||||
DiyaHookHandle* handle = (DiyaHookHandle*) user_data;
|
||||
char *path = g_file_get_path(file);
|
||||
g_debug("on_diya_hook_on_file_changed: %s event %x", path, evtype);
|
||||
switch (evtype)
|
||||
{
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
case G_FILE_MONITOR_EVENT_MOVED_IN:
|
||||
// case G_FILE_MONITOR_EVENT_CHANGED:
|
||||
//case G_FILE_MONITOR_EVENT_CREATED:
|
||||
case G_FILE_MONITOR_EVENT_DELETED:
|
||||
case G_FILE_MONITOR_EVENT_RENAMED:
|
||||
case G_FILE_MONITOR_EVENT_MOVED_OUT:
|
||||
execute_hook_script(handle->hook,handle->script, false);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
static int l_on_file_changed(lua_State *L)
|
||||
{
|
||||
gchar *target = g_canonicalize_filename((const char*)luaL_checkstring(L, 1), NULL);
|
||||
const char *script = (const char*)luaL_checkstring(L, 2);
|
||||
gboolean exec_on_start = (gboolean) lua_toboolean(L, 3);
|
||||
// get global table on top of stack
|
||||
lua_getglobal(L, "diya");
|
||||
|
||||
lua_getfield(L, -1, "handle");
|
||||
DiyaHook* self = (DiyaHook*)lua_touserdata(L, -1);
|
||||
// remove the hook object
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L,-1,"trigger");
|
||||
const char* trigger = (const char*) luaL_checkstring(L,-1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// remove global table on top of stack
|
||||
lua_pop(L, 1);
|
||||
|
||||
g_debug("Install file watchdog for %s: script %s from trigger %s", target, script, trigger);
|
||||
if(!g_hash_table_contains(self->lua_hooks, trigger))
|
||||
{
|
||||
g_critical("Unknow trigger: %s for target %s (%s)", trigger, target, script);
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushstring(L, "Trigger file unknown");
|
||||
g_free(target);
|
||||
return 2;
|
||||
}
|
||||
|
||||
GHashTable* lookup = g_hash_table_lookup(self->lua_hooks, trigger);
|
||||
if(g_hash_table_contains(lookup, target))
|
||||
{
|
||||
g_hash_table_remove(lookup, target);
|
||||
diya_files_monitor_unwatch(self->files_watchdog, target);
|
||||
}
|
||||
DiyaHookHandle* handle = diya_hook_handle_new(self, script);
|
||||
|
||||
if(!diya_files_monitor_watch(self->files_watchdog, target, G_CALLBACK(on_diya_hook_on_file_changed), handle))
|
||||
{
|
||||
g_critical("Unable to setup watchdog for target %s (%s)", target, script);
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushstring(L, "Unable to setup watchdog");
|
||||
g_free(target);
|
||||
g_object_unref(handle);
|
||||
return 2;
|
||||
}
|
||||
g_hash_table_insert(lookup, target, handle);
|
||||
if(exec_on_start)
|
||||
{
|
||||
execute_hook_script(self, script, false);
|
||||
}
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg hook_module [] = {
|
||||
{"changed", l_on_file_changed},
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
static int l_log_info(lua_State *L)
|
||||
{
|
||||
const char* msg = (const char*)luaL_checkstring(L, 1);
|
||||
g_info("%s", msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_log_warning(lua_State *L)
|
||||
{
|
||||
const char* msg = (const char*)luaL_checkstring(L, 1);
|
||||
g_warning("%s", msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_log_error(lua_State *L)
|
||||
{
|
||||
const char* msg = (const char*)luaL_checkstring(L, 1);
|
||||
g_critical("%s", msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_user_home(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, g_get_home_dir());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_user_config_dir(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, g_get_user_config_dir());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_user_data_dir(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, g_get_user_data_dir());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_save_resource(lua_State *L)
|
||||
{
|
||||
const char* resource = (const char*) luaL_checkstring(L,1);
|
||||
const char* path = (const char*) luaL_checkstring(L,2);
|
||||
|
||||
GError *error = NULL;
|
||||
g_info("Saving resource %s to %s", resource, path);
|
||||
GBytes *bytes = g_resources_lookup_data(resource, 0, &error);
|
||||
if (error != NULL)
|
||||
{
|
||||
g_critical("Unable to read resource %s", error->message);
|
||||
g_error_free(error);
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
g_file_set_contents(path, g_bytes_get_data(bytes, NULL), g_bytes_get_size(bytes), &error);
|
||||
g_bytes_unref(bytes);
|
||||
if (error != NULL)
|
||||
{
|
||||
g_critical("Unable to read write resource %s to file %s: %s", resource, path, error->message);
|
||||
g_error_free(error);
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_exists(lua_State *L)
|
||||
{
|
||||
const char* path = (const char*) luaL_checkstring(L,1);
|
||||
lua_pushboolean(L, g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_mkdir(lua_State *L)
|
||||
{
|
||||
const char* path = (const char*) luaL_checkstring(L,1);
|
||||
lua_pushboolean(L, g_mkdir_with_parents((const gchar *)path, 0755) == 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg system_module [] = {
|
||||
{"log_info", l_log_info},
|
||||
{"log_warning", l_log_warning},
|
||||
{"log_error", l_log_error},
|
||||
{"user_home", l_user_home},
|
||||
{"user_config_dir", l_user_config_dir},
|
||||
{"user_data_dir", l_user_data_dir},
|
||||
{"save_resource", l_save_resource},
|
||||
{"file_exists", l_file_exists},
|
||||
{"mkdir", l_mkdir},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static void execute_hook_script(DiyaHook* self, const gchar* script, gboolean allow_install_hook)
|
||||
{
|
||||
lua_State* L = NULL;
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
if(L)
|
||||
{
|
||||
g_debug("Executing %s", script);
|
||||
// install custom lib to lua state
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L,"system");
|
||||
luaL_newlib(L, system_module);
|
||||
lua_settable(L, -3);
|
||||
|
||||
if(allow_install_hook)
|
||||
{
|
||||
lua_pushstring(L,"hook");
|
||||
luaL_newlib(L, hook_module);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "trigger");
|
||||
lua_pushstring(L, script);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
lua_pushstring(L,"handle");
|
||||
lua_pushlightuserdata(L, self);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_setglobal(L, "diya");
|
||||
|
||||
if (luaL_loadfile(L, script) || lua_pcall(L, 0, 0, 0))
|
||||
{
|
||||
g_critical("cannot execute hook script: [%s] %s", script, lua_tostring(L, -1));
|
||||
}
|
||||
lua_close(L);
|
||||
}
|
||||
}
|
||||
|
||||
void on_diya_hook_lua_script_changed(GFileMonitor *monitor, GFile *file, GFile *other, GFileMonitorEvent evtype, gpointer user_data)
|
||||
{
|
||||
(void)monitor;
|
||||
(void)other;
|
||||
DiyaHook *self = user_data;
|
||||
char *path = g_file_get_path(file);
|
||||
g_debug("on_diya_hook_lua_script_changed: %s event %x", path, evtype);
|
||||
switch (evtype)
|
||||
{
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
case G_FILE_MONITOR_EVENT_MOVED_IN:
|
||||
// case G_FILE_MONITOR_EVENT_CHANGED:
|
||||
// case G_FILE_MONITOR_EVENT_CREATED:
|
||||
// unwatched all watched files installed by this script
|
||||
reset_lua_hook(self, path, true);
|
||||
// re-execute the script to install additional hook
|
||||
execute_hook_script(self,path, true);
|
||||
break;
|
||||
case G_FILE_MONITOR_EVENT_DELETED:
|
||||
case G_FILE_MONITOR_EVENT_RENAMED:
|
||||
case G_FILE_MONITOR_EVENT_MOVED_OUT:
|
||||
reset_lua_hook(self, path, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
gboolean diya_hook_install_lua(DiyaHook* self, const gchar* script)
|
||||
{
|
||||
// unwatch the file
|
||||
reset_lua_hook(self, script, true);
|
||||
diya_files_monitor_unwatch(self->files_watchdog, script);
|
||||
execute_hook_script(self, script, true);
|
||||
return diya_files_monitor_watch(self->files_watchdog, script, G_CALLBACK(on_diya_hook_lua_script_changed), self);
|
||||
}
|
||||
|
||||
void diya_hook_uninstall(DiyaHook* self, const gchar* file)
|
||||
{
|
||||
reset_lua_hook(self, file, false);
|
||||
diya_files_monitor_unwatch(self->files_watchdog, file);
|
||||
}
|
||||
|
||||
gboolean diya_hook_install(DiyaHook* self, const gchar* file, GCallback callback, gpointer userdata, gboolean singleton)
|
||||
{
|
||||
if(singleton)
|
||||
{
|
||||
// unwatch previously watch of the same file
|
||||
diya_files_monitor_unwatch(self->files_watchdog, file);
|
||||
}
|
||||
return diya_files_monitor_watch(self->files_watchdog, file, callback, userdata);
|
||||
}
|
||||
18
src/hook.h
Normal file
18
src/hook.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef DIYA_HOOK_H
|
||||
#define DIYA_HOOK_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
|
||||
#define DIYA_TYPE_HOOK (diya_hook_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaHook, diya_hook, DIYA, HOOK, DiyaObject)
|
||||
|
||||
#define DIYA_TYPE_HOOK_HANDLE (diya_hook_handle_get_type())
|
||||
G_DECLARE_FINAL_TYPE (DiyaHookHandle, diya_hook_handle, DIYA, HOOK_HANDLE, DiyaObject)
|
||||
|
||||
DiyaHook* diya_hook_new();
|
||||
gboolean diya_hook_install(DiyaHook* self, const gchar* file, GCallback callback, gpointer userdata, gboolean singleton);
|
||||
gboolean diya_hook_install_lua(DiyaHook* self, const gchar* script);
|
||||
void diya_hook_uninstall(DiyaHook* self, const gchar* file);
|
||||
|
||||
#endif
|
||||
@@ -123,6 +123,7 @@ DiyaIdleNotification* diya_shell_get_idle_notification(DiyaShell* shell, guint t
|
||||
DiyaIdleNotification* self = g_object_new(DIYA_TYPE_IDLE_NOTIFICATION, "shell", shell, NULL);
|
||||
struct wl_seat *seat = diya_wayland_get_seat(wayland);
|
||||
self->timeout = timeout_ms;
|
||||
g_info("Set IDLE notification for timeout %d", timeout_ms);
|
||||
self->notification = ext_idle_notifier_v1_get_idle_notification(mngr, timeout_ms, seat);
|
||||
ext_idle_notification_v1_add_listener(self->notification, &g_idle_listener_impl, self);
|
||||
return self;
|
||||
|
||||
@@ -310,6 +310,11 @@ static void diya_login_on_shell_resume(DiyaShell* shell)
|
||||
diya_shell_power_display(shell, true);
|
||||
}
|
||||
|
||||
static void diya_login_shell_active(DiyaShell *shell)
|
||||
{
|
||||
g_object_set(shell, DIYA_PROP_SHELL_IDLE_TIMEOUT, DEFAULT_IDLE_TIMEOUT, NULL);
|
||||
}
|
||||
|
||||
static void diya_login_shell_startup(DiyaShell *shell)
|
||||
{
|
||||
DiyaLoginShell *self = DIYA_LOGIN_SHELL(shell);
|
||||
@@ -340,5 +345,6 @@ static void diya_login_shell_class_init(DiyaLoginShellClass *class)
|
||||
DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class);
|
||||
base_shell_class->monitor_changed_handle = on_monitor_changed;
|
||||
base_shell_class->startup_handle = diya_login_shell_startup;
|
||||
base_shell_class->active_handle = diya_login_shell_active;
|
||||
// base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register;
|
||||
}
|
||||
@@ -6,6 +6,6 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
DiyaLoginShell* shell = DIYA_LOGIN_SHELL(g_object_new(DIYA_TYPE_LOGIN_SHELL, "name", "dev.iohub.diya.login-shell", NULL));
|
||||
DiyaLoginShell* shell = DIYA_LOGIN_SHELL(g_object_new(DIYA_TYPE_LOGIN_SHELL, "name", "dev.iohub.diya.login", NULL));
|
||||
return diya_shell_run(DIYA_SHELL(shell), argc, argv);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#include "launcher.h"
|
||||
#include "session-lock.h"
|
||||
#include "idle.h"
|
||||
|
||||
#define compiled_schema_path() (g_strconcat(g_getenv("GSETTINGS_SCHEMA_DIR"), "/gschemas.compiled", NULL))
|
||||
|
||||
enum
|
||||
{
|
||||
NO_PROP,
|
||||
@@ -29,6 +32,7 @@ struct _DiyaSessionShell
|
||||
DiyaLauncher *launcher;
|
||||
GHashTable *windows;
|
||||
GtkSessionLockInstance *lock;
|
||||
GSettings *settings;
|
||||
};
|
||||
G_DEFINE_FINAL_TYPE(DiyaSessionShell, diya_session_shell, DIYA_TYPE_SHELL)
|
||||
|
||||
@@ -57,6 +61,10 @@ static void diya_session_shell_dispose(GObject *object)
|
||||
{
|
||||
g_object_unref(self->launcher);
|
||||
}
|
||||
if(self->settings)
|
||||
{
|
||||
g_object_unref(self->settings);
|
||||
}
|
||||
G_OBJECT_CLASS(diya_session_shell_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
@@ -150,9 +158,66 @@ static void diya_session_on_shell_resume(DiyaShell* shell)
|
||||
diya_shell_power_display(shell, true);
|
||||
}
|
||||
|
||||
void diya_session_init_settings(DiyaSessionShell* self)
|
||||
{
|
||||
g_return_if_fail(DIYA_IS_SESSION_SHELL(self));
|
||||
if(self->settings)
|
||||
{
|
||||
g_debug("Setting is already initialized. Nothing todo");
|
||||
return;
|
||||
}
|
||||
|
||||
GSettingsSchemaSource* source = g_settings_schema_source_get_default();
|
||||
if (!source)
|
||||
{
|
||||
g_warning("No gsetting schema source found");
|
||||
return;
|
||||
}
|
||||
// Look up the schema ID
|
||||
GSettingsSchema* schema = g_settings_schema_source_lookup(source, SESSION_SHELL_SCHEMA_ID, TRUE);
|
||||
if (schema)
|
||||
{
|
||||
g_debug("Loading setting from compiled schema");
|
||||
self->settings = g_settings_new(SESSION_SHELL_SCHEMA_ID);
|
||||
g_settings_bind(self->settings, DIYA_PROP_SHELL_IDLE_TIMEOUT, DIYA_SHELL(self), DIYA_PROP_SHELL_IDLE_TIMEOUT, G_SETTINGS_BIND_DEFAULT);
|
||||
g_settings_bind(self->settings, DIYA_PROP_SHELL_THEME, DIYA_SHELL(self), DIYA_PROP_SHELL_THEME, G_SETTINGS_BIND_DEFAULT);
|
||||
g_settings_schema_unref(schema);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning("Unable to find schema ID %s", SESSION_SHELL_SCHEMA_ID);
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_session_shell_startup(DiyaShell *shell)
|
||||
{
|
||||
DiyaSessionShell* self = DIYA_SESSION_SHELL(shell);
|
||||
|
||||
const gchar* const* dirs = g_get_system_config_dirs();
|
||||
|
||||
gchar* path = NULL;
|
||||
gboolean hook_found = false;
|
||||
for (int i = 0; dirs[i] != NULL; i++)
|
||||
{
|
||||
path = g_strconcat(dirs[0], "/diya/hooks/hooks.lua", NULL);
|
||||
g_debug("Looking for hook scripts: %s", path);
|
||||
if (g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))
|
||||
{
|
||||
//hook script path
|
||||
g_debug("Install LUA hook at: %s", path);
|
||||
diya_shell_watch_script(shell, path);
|
||||
hook_found = true;
|
||||
}
|
||||
g_free(path);
|
||||
}
|
||||
if(!hook_found)
|
||||
{
|
||||
path = g_strconcat(g_get_user_config_dir(), "/diya/hooks/hooks.lua", NULL);
|
||||
g_debug("No system hook found. Install local hook at: %s", path);
|
||||
diya_shell_watch_script(shell, path);
|
||||
g_free(path);
|
||||
}
|
||||
|
||||
diya_session_shell_init_background(self);
|
||||
diya_session_shell_launcher_init(self);
|
||||
g_signal_connect(shell, DIYA_SIGNAL_SHELL_KEY_PRESSED, G_CALLBACK(diya_session_on_key_pressed), NULL);
|
||||
@@ -162,6 +227,7 @@ static void diya_session_shell_startup(DiyaShell *shell)
|
||||
|
||||
static void diya_session_shell_active(DiyaShell *shell)
|
||||
{
|
||||
diya_session_init_settings(DIYA_SESSION_SHELL(shell));
|
||||
diya_shell_monitor_input(shell);
|
||||
}
|
||||
|
||||
@@ -282,6 +348,7 @@ static void diya_session_shell_init(DiyaSessionShell *self)
|
||||
// self->app = NULL;
|
||||
self->background = NULL;
|
||||
self->launcher = NULL;
|
||||
self->settings = 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);
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#define DIYA_PROP_SESSION_LOCK "session-lock"
|
||||
#define DIYA_PROP_SESSION_WINDOWS "windows"
|
||||
|
||||
#define SESSION_SHELL_SCHEMA_ID "dev.iohub.diya.session"
|
||||
|
||||
#define DIYA_TYPE_SESSION_SHELL (diya_session_shell_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DiyaSessionShell, diya_session_shell, DIYA, SESSION_SHELL, DiyaShell)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ static void session_unlocked(DiyaSessionShell* shell, void* data)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
DiyaSessionShell *shell = DIYA_SESSION_SHELL(g_object_new(DIYA_TYPE_SESSION_SHELL, "name","dev.iohub.diya.session-shell", NULL));
|
||||
DiyaSessionShell *shell = DIYA_SESSION_SHELL(g_object_new(DIYA_TYPE_SESSION_SHELL, "name","dev.iohub.diya.session", NULL));
|
||||
g_signal_connect(shell, DIYA_SIGNAL_SESSION_LOCKED, G_CALLBACK(session_locked), NULL);
|
||||
g_signal_connect(shell, DIYA_SIGNAL_SESSION_UNLOCKED, G_CALLBACK(session_unlocked), NULL);
|
||||
return diya_shell_run(DIYA_SHELL(shell), argc, argv);
|
||||
|
||||
103
src/shell.c
103
src/shell.c
@@ -2,15 +2,13 @@
|
||||
#include "shell.h"
|
||||
#include "wayland.h"
|
||||
#include "virtual-keyboard.h"
|
||||
#include "files-monior.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>
|
||||
|
||||
#define DEFAULT_IDLE_TIMEOUT 60*1000 // 1m
|
||||
|
||||
#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
|
||||
@@ -35,7 +33,7 @@ typedef struct _DiyaShellPrivate
|
||||
GHashTable *vkbs;
|
||||
GtkCssProvider *css_provider;
|
||||
DiyaInput *input;
|
||||
DiyaFilesMonitor *files_watchdog;
|
||||
DiyaHook *files_hook;
|
||||
gchar *theme;
|
||||
DiyaIdleNotification *idle_notif;
|
||||
} DiyaShellPrivate;
|
||||
@@ -78,10 +76,10 @@ static void diya_shell_dispose(GObject *object)
|
||||
{
|
||||
g_object_unref(priv->input);
|
||||
}
|
||||
if (priv->files_watchdog)
|
||||
if (priv->files_hook)
|
||||
{
|
||||
g_object_unref(priv->files_watchdog);
|
||||
priv->files_watchdog = NULL;
|
||||
g_object_unref(priv->files_hook);
|
||||
priv->files_hook = NULL;
|
||||
}
|
||||
if (priv->idle_notif)
|
||||
{
|
||||
@@ -137,14 +135,10 @@ void diya_shell_reload(DiyaShell *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);
|
||||
char *opath = NULL;
|
||||
g_debug("%s event %x", fpath, evtype);
|
||||
if (other)
|
||||
{
|
||||
opath = g_file_get_path(other);
|
||||
}
|
||||
switch (evtype)
|
||||
{
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
@@ -152,17 +146,13 @@ void on_diya_shell_theme_file_changed(GFileMonitor *monitor, GFile *file, GFile
|
||||
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:
|
||||
// case G_FILE_MONITOR_EVENT_CHANGED:
|
||||
//case G_FILE_MONITOR_EVENT_CREATED:
|
||||
diya_shell_reload_theme(shell);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (opath)
|
||||
{
|
||||
g_free(opath);
|
||||
}
|
||||
g_free(fpath);
|
||||
}
|
||||
|
||||
@@ -186,18 +176,13 @@ static void on_gtk_app_startup(GtkApplication *app, void *data)
|
||||
priv->wayland = diya_wayland_new(DIYA_SHELL(shell));
|
||||
DiyaShellClass *class = DIYA_SHELL_GET_CLASS(shell);
|
||||
|
||||
// read envar
|
||||
const char *default_theme = g_getenv(DIYA_ENV_THEME);
|
||||
if (default_theme)
|
||||
// log all environment variables in debug
|
||||
for (gchar **env = g_get_environ(); *env != NULL; env++)
|
||||
{
|
||||
priv->theme = g_strdup(default_theme);
|
||||
g_debug("ENV: %s", *env);
|
||||
}
|
||||
|
||||
gchar *dir = diya_shell_config_theme_dir(priv);
|
||||
diya_shell_watch_file(shell, dir, G_CALLBACK(on_diya_shell_theme_file_changed), (gpointer)shell);
|
||||
g_free(dir);
|
||||
|
||||
diya_shell_reload(shell);
|
||||
// diya_shell_reload(shell);
|
||||
if (class->startup_handle)
|
||||
{
|
||||
class->startup_handle(shell);
|
||||
@@ -208,6 +193,7 @@ static void on_gtk_app_startup(GtkApplication *app, void *data)
|
||||
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)
|
||||
@@ -215,16 +201,22 @@ static void on_gtk_app_active(GtkApplication *app, void *data)
|
||||
(void)app;
|
||||
DiyaShell *shell = data;
|
||||
DiyaShellClass *class = DIYA_SHELL_GET_CLASS(shell);
|
||||
// DiyaShellPrivate *priv = diya_shell_get_instance_private(shell);
|
||||
/**
|
||||
* TODO: read timeout from setting
|
||||
*/
|
||||
g_object_set(shell, DIYA_PROP_SHELL_IDLE_TIMEOUT, DEFAULT_IDLE_TIMEOUT, NULL);
|
||||
|
||||
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)
|
||||
@@ -277,6 +269,7 @@ static void diya_shell_set_property(GObject *object, guint property_id, const GV
|
||||
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));
|
||||
@@ -286,13 +279,21 @@ static void diya_shell_set_property(GObject *object, guint property_id, const GV
|
||||
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;
|
||||
@@ -346,7 +347,7 @@ static void diya_shell_init(DiyaShell *self)
|
||||
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_watchdog = NULL;
|
||||
priv->files_hook = NULL;
|
||||
priv->theme = NULL;
|
||||
priv->idle_notif = NULL;
|
||||
}
|
||||
@@ -516,7 +517,14 @@ 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);
|
||||
@@ -525,7 +533,7 @@ int diya_shell_run(DiyaShell *shell, int argc, char **argv)
|
||||
*/
|
||||
|
||||
// keymap dir
|
||||
gchar *path = g_strconcat(g_get_user_config_dir(), "/diya/xkb/", NULL);
|
||||
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[] =
|
||||
@@ -541,7 +549,8 @@ int diya_shell_run(DiyaShell *shell, int argc, char **argv)
|
||||
.arg_description = NULL,
|
||||
},
|
||||
#endif
|
||||
{NULL}};
|
||||
{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);
|
||||
@@ -603,19 +612,19 @@ void diya_shell_monitor_input(DiyaShell *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_watchdog)
|
||||
if (!priv->files_hook)
|
||||
{
|
||||
priv->files_watchdog = diya_files_monitor_new();
|
||||
priv->files_hook = diya_hook_new();
|
||||
}
|
||||
return diya_files_monitor_watch(priv->files_watchdog, file, callback, userdata);
|
||||
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_watchdog)
|
||||
if (priv->files_hook)
|
||||
{
|
||||
diya_files_monitor_unwatch(priv->files_watchdog, file);
|
||||
diya_hook_uninstall(priv->files_hook, file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,4 +668,14 @@ void diya_shell_power_display(DiyaShell* self, gboolean mode)
|
||||
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);
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "base.h"
|
||||
|
||||
#define DEFAULT_IDLE_TIMEOUT 60*1000 // 1m
|
||||
|
||||
#define DIYA_ENV_THEME "DIYA_DEFAULT_THEME"
|
||||
#define DIYA_ENV_VKB_KEYMAP "DIYA_VKB_KEYMAP"
|
||||
|
||||
@@ -49,6 +51,7 @@ const char* diya_shell_get_name(DiyaShell* shell);
|
||||
DiyaVirtualKeyboard* diya_shell_get_virtual_keyboard(DiyaShell* shell, const gchar* name);
|
||||
void diya_shell_monitor_input(DiyaShell* shell);
|
||||
gboolean diya_shell_watch_file(DiyaShell* shell, const gchar* file, GCallback callback, gpointer userdata);
|
||||
gboolean diya_shell_watch_script(DiyaShell* shell, const gchar* script);
|
||||
void diya_shell_unwatch_file(DiyaShell* shell, const gchar* file);
|
||||
void diya_shell_power_display(DiyaShell* shell, gboolean mode);
|
||||
void diya_shell_launch(DiyaShell* shell, GAppInfo* app);
|
||||
|
||||
@@ -116,6 +116,8 @@ struct _DiyaTaskbarWidget
|
||||
DiyaTaskbarListModel *model;
|
||||
GtkListItemFactory *factory;
|
||||
guint selection_changed_sig_id;
|
||||
|
||||
GtkWidget *btn_test;
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -278,6 +280,16 @@ static void diya_taskbar_list_model_selection_changed_cb(GtkSelectionModel *mode
|
||||
}
|
||||
}
|
||||
|
||||
static void diya_dashboard_btn_test_clicked(GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
(void) widget;
|
||||
g_return_if_fail(DIYA_IS_SHELL_WINDOW(user_data));
|
||||
DiyaShellWindow* self = user_data;
|
||||
DiyaSessionShell* shell = DIYA_SESSION_SHELL(diya_shell_window_get_shell(self));
|
||||
g_return_if_fail(DIYA_IS_SESSION_SHELL(shell));
|
||||
// TODO remove
|
||||
}
|
||||
|
||||
static void diya_taskbar_widget_init(DiyaTaskbarWidget *self)
|
||||
{
|
||||
g_debug("diya_taskbar_widget_init");
|
||||
@@ -323,6 +335,8 @@ static void diya_taskbar_widget_init(DiyaTaskbarWidget *self)
|
||||
g_signal_connect(controller, "leave", G_CALLBACK(diya_taskbar_applist_leave), self);
|
||||
gtk_widget_add_controller(GTK_WIDGET(self->apps_list), GTK_EVENT_CONTROLLER(controller));
|
||||
*/
|
||||
|
||||
g_signal_connect(self->btn_test, "clicked", G_CALLBACK(diya_dashboard_btn_test_clicked), self);
|
||||
}
|
||||
|
||||
static void diya_taskbar_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
@@ -392,6 +406,7 @@ static void diya_taskbar_widget_class_init(DiyaTaskbarWidgetClass *class)
|
||||
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), DiyaTaskbarWidget, btn_toggle);
|
||||
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), DiyaTaskbarWidget, apps_list);
|
||||
|
||||
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), DiyaTaskbarWidget, btn_test);
|
||||
// gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), diya_dashboard_toggle);
|
||||
|
||||
gtk_widget_class_set_css_name(GTK_WIDGET_CLASS(class), "diya-taskbar");
|
||||
|
||||
Reference in New Issue
Block a user