Chandra
view release on metacpan or search on metacpan
include/webview-tray-gtk.c view on Meta::CPAN
/*
* webview-tray-gtk.c â Linux system tray (GtkStatusIcon) backend
*
* Uses GtkStatusIcon (deprecated but widely supported) with GtkMenu.
* Falls back gracefully if no system tray is available.
*/
struct webview_tray_gtk {
GtkStatusIcon *icon;
GtkWidget *menu;
};
/* Forward */
static void tray_gtk_activate(GtkStatusIcon *icon, gpointer user_data);
static void tray_gtk_popup(GtkStatusIcon *icon, guint button,
guint activate_time, gpointer user_data);
/* Menu item activation callback */
static void tray_gtk_menu_item_activated(GtkMenuItem *menuitem,
gpointer user_data) {
int *item_data = (int *)user_data;
/* item_data[0] = item_id, item_data[1..] = pointer to tray */
/* We pack item_id and tray pointer together */
(void)menuitem;
/* This approach is fragile. Instead, use g_object_set_data. */
}
/* Alternative: use g_object_set_data to attach callback info */
struct tray_gtk_cb_data {
struct webview_tray *tray;
int item_id;
};
static void tray_gtk_item_activated(GtkMenuItem *menuitem, gpointer data) {
(void)menuitem;
struct tray_gtk_cb_data *cb = (struct tray_gtk_cb_data *)data;
if (cb && cb->tray && cb->tray->menu_cb) {
cb->tray->menu_cb(cb->tray->w, cb->item_id);
}
}
static GtkWidget *tray_gtk_build_menu(struct webview_tray *t,
struct webview_tray_item *items,
int count) {
GtkWidget *menu = gtk_menu_new();
for (int i = 0; i < count; i++) {
struct webview_tray_item *it = &items[i];
GtkWidget *mi;
if (it->is_separator) {
mi = gtk_separator_menu_item_new();
} else if (it->is_checked) {
mi = gtk_check_menu_item_new_with_label(it->label ? it->label : "");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mi), TRUE);
} else {
mi = gtk_menu_item_new_with_label(it->label ? it->label : "");
}
if (it->is_disabled) {
gtk_widget_set_sensitive(mi, FALSE);
}
if (it->submenu_count > 0 && it->submenu && !it->is_separator) {
GtkWidget *sub = tray_gtk_build_menu(t, it->submenu, it->submenu_count);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi), sub);
} else if (!it->is_separator) {
/* Connect signal for leaf items */
struct tray_gtk_cb_data *cb = (struct tray_gtk_cb_data *)
g_malloc(sizeof(struct tray_gtk_cb_data));
cb->tray = t;
cb->item_id = it->id;
g_signal_connect_data(G_OBJECT(mi), "activate",
G_CALLBACK(tray_gtk_item_activated),
cb, (GClosureNotify)g_free, 0);
}
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
}
gtk_widget_show_all(menu);
return menu;
}
static void tray_gtk_activate(GtkStatusIcon *icon, gpointer user_data) {
(void)icon;
struct webview_tray *t = (struct webview_tray *)user_data;
/* Left click â invoke item 0 if it exists, or just show menu */
if (t->menu_cb && t->item_count > 0) {
t->menu_cb(t->w, -1); /* -1 = tray icon clicked */
}
}
static void tray_gtk_popup(GtkStatusIcon *icon, guint button,
guint activate_time, gpointer user_data) {
struct webview_tray *t = (struct webview_tray *)user_data;
( run in 1.898 second using v1.01-cache-2.11-cpan-39bf76dae61 )