1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
// gtklock-userinfo-module
// Copyright (c) 2024 Erik Reider, Jovan Lanik
// User info module
#include <act/act.h>
#include "gtklock-module.h"
#define MODULE_DATA(x) (x->module_data[self_id])
#define USERINFO(x) ((struct userinfo *)MODULE_DATA(x))
extern void config_load(const char *path, const char *group, GOptionEntry entries[]);
struct userinfo {
GtkWidget *user_revealer;
GtkWidget *user_box;
GtkWidget *user_icon;
GtkWidget *user_name;
};
const gchar module_name[] = "userinfo";
const guint module_major_version = 4;
const guint module_minor_version = 0;
static int self_id;
static ActUserManager *act_manager = NULL;
static ActUser *act_user = NULL;
static gboolean no_round_image = FALSE;
static gboolean horizontal_layout = FALSE;
static gboolean under_clock = FALSE;
static gint image_size = 96;
GOptionEntry module_entries[] = {
{ "no-round-image", 0, 0, G_OPTION_ARG_NONE, &no_round_image, NULL, NULL },
{ "horizontal-layout", 0, 0, G_OPTION_ARG_NONE, &horizontal_layout, NULL, NULL },
{ "under-clock", 0, 0, G_OPTION_ARG_NONE, &under_clock, NULL, NULL },
{ "image-size", 0, 0, G_OPTION_ARG_INT, &image_size, NULL, NULL },
{ NULL },
};
static void window_set_userinfo(ActUser* user, struct Window *ctx) {
gboolean loaded = FALSE;
g_object_get(user, "is-loaded", &loaded, NULL);
if(loaded != TRUE) return;
const char *name = act_user_get_real_name(user);
if(name == NULL) {
g_warning("userinfo-module: User name not found");
name = act_user_get_user_name(user);
}
gtk_label_set_text(GTK_LABEL(USERINFO(ctx)->user_name), name);
if(image_size < 0) {
g_warning("userinfo-module: Invalid image size: %d, using default value", image_size);
image_size = 96;
}
GdkPixbuf *pixbuf = NULL;
const char *path = act_user_get_icon_file(user);
if(path != NULL) {
GError *error = NULL;
pixbuf = gdk_pixbuf_new_from_file_at_size(path, image_size, image_size, &error);
if(error != NULL) {
g_warning("userinfo-module: User image error: %s", error->message);
g_error_free(error);
}
} else g_warning("userinfo-module: User image not found");
if(pixbuf == NULL) {
GtkIconTheme *theme = gtk_icon_theme_get_default();
GtkIconInfo *icon =
gtk_icon_theme_lookup_icon(theme, "avatar-default-symbolic", image_size, GTK_ICON_LOOKUP_FORCE_SIZE);
GError *error = NULL;
pixbuf = gtk_icon_info_load_icon(icon, &error);
if(error != NULL) {
g_warning("userinfo-module: User icon error: %s", error->message);
g_error_free(error);
}
}
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, image_size, image_size);
cairo_t *cr = cairo_create(surface);
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
// Makes the image circular
if(!no_round_image) {
const int half_size = image_size / 2;
cairo_arc(cr, half_size, half_size, half_size, 0, 2 * G_PI);
cairo_clip(cr);
}
cairo_paint(cr);
gtk_image_set_from_surface(GTK_IMAGE(USERINFO(ctx)->user_icon), surface);
}
static void gtklock_set_userinfo(ActUser* user, struct GtkLock *gtklock) {
if(gtklock->focused_window != NULL) window_set_userinfo(user, gtklock->focused_window);
}
static void gtklock_user_loaded(ActUser* user, GParamSpec *spec, struct GtkLock *gtklock) {
if(gtklock->focused_window != NULL) window_set_userinfo(user, gtklock->focused_window);
}
static void init_user_manager(struct GtkLock *gtklock) {
if(act_manager == NULL) act_manager = act_user_manager_get_default();
if(act_user_manager_no_service(act_manager)) {
g_warning("userinfo-module: AccountsService is not running");
return;
} else if(act_user == NULL) {
const char *username = g_get_user_name();
act_user = act_user_manager_get_user(act_manager, username);
g_signal_connect(act_user, "notify::is-loaded", G_CALLBACK(gtklock_user_loaded), gtklock);
g_signal_connect(act_user, "changed", G_CALLBACK(gtklock_set_userinfo), gtklock);
}
}
static void setup_userinfo(struct Window *ctx) {
if(MODULE_DATA(ctx) != NULL) {
gtk_widget_destroy(USERINFO(ctx)->user_revealer);
g_free(MODULE_DATA(ctx));
MODULE_DATA(ctx) = NULL;
}
MODULE_DATA(ctx) = g_malloc(sizeof(struct userinfo));
USERINFO(ctx)->user_revealer = gtk_revealer_new();
gtk_widget_set_halign(USERINFO(ctx)->user_revealer, GTK_ALIGN_CENTER);
gtk_widget_set_name(USERINFO(ctx)->user_revealer, "user-revealer");
gtk_revealer_set_reveal_child(GTK_REVEALER(USERINFO(ctx)->user_revealer), TRUE);
gtk_revealer_set_transition_type(GTK_REVEALER(USERINFO(ctx)->user_revealer), GTK_REVEALER_TRANSITION_TYPE_NONE);
gtk_container_add(GTK_CONTAINER(ctx->info_box), USERINFO(ctx)->user_revealer);
if(!under_clock) gtk_box_reorder_child(GTK_BOX(ctx->info_box), USERINFO(ctx)->user_revealer, 0);
//if(under_clock) g_object_set(USERINFO(ctx)->user_revealer, "margin-top", 10, NULL);
GtkOrientation o = horizontal_layout ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL ;
USERINFO(ctx)->user_box = gtk_box_new(o, 5);
gtk_widget_set_halign(USERINFO(ctx)->user_box, GTK_ALIGN_CENTER);
gtk_widget_set_name(USERINFO(ctx)->user_box, "user-box");
gtk_container_add(GTK_CONTAINER(USERINFO(ctx)->user_revealer), USERINFO(ctx)->user_box);
// Profile picture
USERINFO(ctx)->user_icon = gtk_image_new();
gtk_widget_set_name(USERINFO(ctx)->user_icon, "user-image");
gtk_container_add(GTK_CONTAINER(USERINFO(ctx)->user_box), USERINFO(ctx)->user_icon);
// Profile name
USERINFO(ctx)->user_name = gtk_label_new(NULL);
gtk_widget_set_name(USERINFO(ctx)->user_name, "user-name");
gtk_container_add(GTK_CONTAINER(USERINFO(ctx)->user_box), USERINFO(ctx)->user_name);
window_set_userinfo(act_user, ctx);
gtk_widget_show_all(USERINFO(ctx)->user_revealer);
}
void on_activation(struct GtkLock *gtklock, int id) {
self_id = id;
init_user_manager(gtklock);
GtkCssProvider *provider = gtk_css_provider_new();
GError *err = NULL;
const char css[] =
"#user-name {"
"font-size: 18pt;"
"}"
;
gtk_css_provider_load_from_data(provider, css, -1, &err);
if(err != NULL) {
g_warning("Style loading failed: %s", err->message);
g_error_free(err);
} else {
gtk_style_context_add_provider_for_screen(
gdk_screen_get_default(),
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
);
}
g_object_unref(provider);
}
void on_focus_change(struct GtkLock *gtklock, struct Window *win, struct Window *old) {
setup_userinfo(win);
if(gtklock->hidden)
gtk_revealer_set_reveal_child(GTK_REVEALER(USERINFO(win)->user_revealer), FALSE);
if(old != NULL && win != old)
gtk_revealer_set_reveal_child(GTK_REVEALER(USERINFO(old)->user_revealer), FALSE);
}
void on_window_destroy(struct GtkLock *gtklock, struct Window *ctx) {
if(MODULE_DATA(ctx) != NULL) {
gtk_widget_destroy(USERINFO(ctx)->user_revealer);
g_free(MODULE_DATA(ctx));
MODULE_DATA(ctx) = NULL;
}
}
void on_idle_hide(struct GtkLock *gtklock) {
if(gtklock->focused_window) {
GtkRevealer *revealer = GTK_REVEALER(USERINFO(gtklock->focused_window)->user_revealer);
gtk_revealer_set_reveal_child(revealer, FALSE);
}
}
void on_idle_show(struct GtkLock *gtklock) {
if(gtklock->focused_window) {
GtkRevealer *revealer = GTK_REVEALER(USERINFO(gtklock->focused_window)->user_revealer);
gtk_revealer_set_reveal_child(revealer, TRUE);
}
}
|