-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtray.c
119 lines (101 loc) · 3.04 KB
/
tray.c
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
// gcc `pkg-config appindicator3-0.1 --cflags` tray.c -o build/tray `pkg-config
// appindicator3-0.1 --libs`
#include "tray.h"
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <libappindicator/app-indicator.h>
#define ICON_NAME_EN "indicator-keyboard-En"
#define ICON_NAME_VI "indicator-keyboard-Vi"
static void handlecommand(gchar *sz, AppIndicator *indicator)
{
if (g_ascii_strcasecmp(sz, "daklak_off\n") == 0) {
app_indicator_set_icon(indicator, ICON_NAME_EN);
}
else if (g_ascii_strcasecmp(sz, "daklak_on\n") == 0) {
app_indicator_set_icon(indicator, ICON_NAME_VI);
}
}
static gboolean mycallback(GIOChannel *channel, GIOCondition cond,
gpointer data)
{
gchar *str_return;
gsize length;
gsize terminator_pos;
GError *error = NULL;
AppIndicator *indicator = data;
GIOStatus status = g_io_channel_read_line(channel, &str_return, &length,
&terminator_pos, &error);
if (status != G_IO_STATUS_NORMAL) {
perror("read");
return TRUE;
}
if (error != NULL) {
printf("%s\n", error->message);
return TRUE;
}
handlecommand(str_return, indicator);
g_free(str_return);
return TRUE;
}
static void quit_activated(GSimpleAction *simple, GVariant *parameter,
gpointer user_data)
{
struct indicator_state *state;
state = user_data;
state->state->running = false;
close(state->sock_fd);
gtk_main_quit();
}
static GActionEntry app_entries[]
= {{"quit", quit_activated, NULL, NULL, NULL}};
AppIndicator *gtr_icon_new(struct indicator_state *state)
{
AppIndicator *indicator
= app_indicator_new("daklak-indicator", ICON_NAME_VI,
APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
GtkWidget *menu;
GMenu *menuModel = g_menu_new();
GMenuItem *quitMenuItem = g_menu_item_new("Quit", "app.quit");
g_menu_append_item(menuModel, quitMenuItem);
menu = gtk_menu_new_from_model(G_MENU_MODEL(menuModel));
GSimpleActionGroup *group;
group = g_simple_action_group_new();
g_action_map_add_action_entries(G_ACTION_MAP(group), app_entries,
G_N_ELEMENTS(app_entries),
(gpointer)state);
gtk_widget_insert_action_group(menu, "app", G_ACTION_GROUP(group));
app_indicator_set_menu(indicator, GTK_MENU(menu));
app_indicator_set_title(indicator, "daklak");
return indicator;
}
void run_tray(struct daklakwl_state *state)
{
gtk_init(NULL, NULL);
int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock_fd == -1) {
perror("socket");
exit(1);
}
struct sockaddr_un server;
memset(&server, 0, sizeof(server));
server.sun_family = AF_UNIX;
strncpy(server.sun_path, "/tmp/daklak.sock",
sizeof(server.sun_path) - 1);
if (connect(sock_fd, (struct sockaddr *)&server, sizeof(server))
== -1) {
perror("connect");
exit(1);
}
struct indicator_state istate = {
.state = state,
.sock_fd = sock_fd,
};
AppIndicator *indicator = gtr_icon_new(&istate);
GIOChannel *gio_channel = g_io_channel_unix_new(sock_fd);
g_io_add_watch(gio_channel, G_IO_IN, mycallback, (gpointer)indicator);
gtk_main();
}