302 lines
9.9 KiB
C
302 lines
9.9 KiB
C
#include "session-shell.h"
|
|
|
|
#include <assert.h>
|
|
#include <gtk4-session-lock.h>
|
|
#include <xkbcommon/xkbcommon.h>
|
|
|
|
#include "shell.h"
|
|
#include "foreign.h"
|
|
#include "background.h"
|
|
#include "launcher.h"
|
|
#include "session-lock.h"
|
|
|
|
enum
|
|
{
|
|
NO_PROP,
|
|
SHELL_BACKGROUND_WIDGET,
|
|
SHELL_LAUNCHPAD_WIDGET,
|
|
SHELL_LOCK_SESSION,
|
|
SHELL_WINDOWS,
|
|
N_PROPERTIES
|
|
};
|
|
|
|
static GParamSpec *shell_properties[N_PROPERTIES] = {0};
|
|
|
|
struct _DiyaSessionShell
|
|
{
|
|
DiyaShell parent;
|
|
GtkWindow *background;
|
|
DiyaLauncher *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: %s", diya_object_to_string(object));
|
|
if (self->lock)
|
|
{
|
|
g_object_unref(self->lock);
|
|
}
|
|
if (self->background)
|
|
{
|
|
gtk_window_destroy(self->background);
|
|
}
|
|
if (self->launcher)
|
|
{
|
|
g_object_unref(self->launcher);
|
|
}
|
|
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_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_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 void diya_session_on_key_pressed(DiyaShell* shell, struct xkb_keymap *xkb_keymap, struct xkb_state *xkb_state, uint32_t key, uint32_t time, gpointer userdata)
|
|
{
|
|
(void) xkb_keymap;
|
|
(void) userdata;
|
|
(void) time;
|
|
DiyaSessionShell* self = DIYA_SESSION_SHELL(shell);
|
|
uint32_t keycode = key + 8;
|
|
xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, keycode);
|
|
g_debug("Key press %d", sym);
|
|
switch(sym)
|
|
{
|
|
case XKB_KEY_Escape:
|
|
diya_launcher_show_dashboard(self->launcher, false);
|
|
break;
|
|
case XKB_KEY_space:
|
|
if(xkb_state_mod_name_is_active(xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE)) {
|
|
diya_launcher_toggle_dashboard(self->launcher);
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/*
|
|
char buf[128];
|
|
xkb_keysym_get_name(sym, buf, sizeof(buf));
|
|
g_warning("key-pressed (%d): sym: %-12s (%d)", time, buf, sym);
|
|
xkb_state_key_get_utf8(xkb_state, keycode, buf, sizeof(buf));
|
|
g_warning("\tutf8: '%s'", buf);
|
|
*/
|
|
}
|
|
|
|
static void diya_session_shell_startup(DiyaShell *shell)
|
|
{
|
|
diya_session_shell_init_background(DIYA_SESSION_SHELL(shell));
|
|
diya_session_shell_launcher_init(DIYA_SESSION_SHELL(shell));
|
|
g_signal_connect(shell, DIYA_SIGNAL_SHELL_KEY_PRESSED, G_CALLBACK(diya_session_on_key_pressed), NULL);
|
|
}
|
|
|
|
static void diya_session_shell_active(DiyaShell *shell)
|
|
{
|
|
diya_shell_monitor_input(shell);
|
|
}
|
|
|
|
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_shell_class->startup_handle = diya_session_shell_startup;
|
|
base_shell_class->active_handle = diya_session_shell_active;
|
|
|
|
/// 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_BACKGROUND_WIDGET] = g_param_spec_pointer(DIYA_PROP_SESSION_BACKGROUND, NULL, "Shell background widget", G_PARAM_READWRITE);
|
|
shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer(DIYA_PROP_SESSION_LAUNCHPAD, NULL, "Shell launchpad", G_PARAM_READWRITE);
|
|
shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer(DIYA_PROP_SESSION_LOCK, NULL, "Shell lock session", G_PARAM_READABLE);
|
|
shell_properties[SHELL_WINDOWS] = g_param_spec_pointer(DIYA_PROP_SESSION_WINDOWS, NULL, "Shell foreign windows", G_PARAM_READABLE);
|
|
|
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties);
|
|
|
|
g_signal_new(DIYA_SIGNAL_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(DIYA_SIGNAL_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(DIYA_SIGNAL_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(DIYA_SIGNAL_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, DIYA_SIGNAL_SESSION_LOCKED);
|
|
}
|
|
|
|
static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaSessionShell *shell)
|
|
{
|
|
(void)lock;
|
|
assert(shell);
|
|
g_message("Session unlocked");
|
|
g_signal_emit_by_name(shell, DIYA_SIGNAL_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, DIYA_PROP_FOREIGN_WINDOW_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, DIYA_PROP_FOREIGN_WINDOW_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);
|
|
}
|
|
|
|
/*
|
|
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));
|
|
}
|
|
*/
|