commit f027ece1933ce3b817ff58a606e616b25a95f535 Author: Serge A. Zaitsev Date: Sat Jan 7 21:08:46 2017 +0200 initial commit, gtk/appindicator implementation draft diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d1f1de3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +example +example.exe diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aa7cdf1 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +ifeq ($(OS),Windows_NT) + TRAY_CFLAGS := + TRAY_LDFLAGS := +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Linux) + TRAY_CFLAGS := -DTRAY_APPINDICATOR=1 $(shell pkg-config --cflags appindicator3-0.1) + TRAY_LDFLAGS := $(shell pkg-config --libs appindicator3-0.1) +endif +ifeq ($(UNAME_S),Darwin) + TRAY_CFLAGS := -DTRAY_COCOA=1 -x objective-c -framework Cocoa $< -o $@ + TRAY_LDFLAGS := +endif +endif + + +CFLAGS := -g -Wall $(TRAY_CFLAGS) +LDFLAGS := -g $(TRAY_LDFLAGS) + +all: example + +example: example.o + $(CC) $^ $(LDFLAGS) -o $@ + +example.o: example.c tray.h + +clean: + rm -f example.o example example.exe diff --git a/example.c b/example.c new file mode 100644 index 0000000..8121a0b --- /dev/null +++ b/example.c @@ -0,0 +1,33 @@ +#include + +#include "tray.h" + +static struct tray tray; + +static void hello_cb(struct tray_menu *item) { + if (strcmp(tray.icon, "indicator-messages") == 0) { + tray.icon = "indicator-messages-new"; + } else { + tray.icon = "indicator-messages"; + } + tray_update(&tray); +} + +static void quit_cb(struct tray_menu *item) { + tray_exit(); +} + +static struct tray tray = { + .icon = "indicator-messages-new", + .menu = (struct tray_menu[]){ + {NULL, "Hello", 0, hello_cb, NULL}, + {NULL, "Quit", 0, quit_cb, NULL}, + {NULL, NULL, 0, NULL, NULL} + }, +}; + +int main(int argc, char *argv[]) { + tray_init(&tray); + while (tray_loop(1) == 0); + return 0; +} diff --git a/tray.h b/tray.h new file mode 100644 index 0000000..24207e2 --- /dev/null +++ b/tray.h @@ -0,0 +1,82 @@ +#ifndef TRAY_H +#define TRAY_H + +struct tray_menu; + +struct tray { + char *icon; + char *tooltip; + struct tray_menu *menu; +}; + +struct tray_menu { + char *icon; + char *text; /* label */ + int flags; + + void (*cb)(struct tray_menu *); + void *context; +}; + +static void tray_update(struct tray *tray); + +#if defined(TRAY_APPINDICATOR) + +#include +#include + +#define TRAY_APPINDICATOR_ID "tray-id" + +static AppIndicator *indicator = NULL; +static int loop_result = 0; + +static void _tray_menu_cb(GtkMenuItem *item, gpointer data) { + struct tray_menu *m = (struct tray_menu *) data; + m->cb(m); +} + +static int tray_init(struct tray *tray) { + if (gtk_init_check(0, NULL) == FALSE) { + return -1; + } + indicator = app_indicator_new(TRAY_APPINDICATOR_ID, tray->icon, + APP_INDICATOR_CATEGORY_APPLICATION_STATUS); + app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE); + tray_update(tray); + return 0; +} + +static int tray_loop(int blocking) { + gtk_main_iteration_do(blocking); + return loop_result; +} + +static void tray_update(struct tray *tray) { + struct tray_menu *m; + + app_indicator_set_icon(indicator, tray->icon); + GtkMenuShell *gtk_menu = (GtkMenuShell *)gtk_menu_new(); + for (m = tray->menu;; m++) { + if (m->text == NULL) { + break; + } + GtkWidget *item = gtk_menu_item_new_with_label(m->text); + gtk_widget_show(item); + gtk_menu_shell_append(GTK_MENU_SHELL(gtk_menu), item); + if (m->cb != NULL) { + g_signal_connect(item, "activate", G_CALLBACK(_tray_menu_cb), m); + } + } + app_indicator_set_menu(indicator, GTK_MENU(gtk_menu)); +} + +static void tray_exit() { + loop_result = -1; +} + +#elif defined(TRAY_APPKIT) +#elif defined(TRAY_WINAPI) +#else +#endif + +#endif /* TRAY_H */