Skip to content
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ else()
list(APPEND SRCS ${CMAKE_CURRENT_SOURCE_DIR}/tray_darwin.m)
else()
find_package(APPINDICATOR REQUIRED)
find_package(LIBNOTIFY REQUIRED)
list(APPEND SRCS ${CMAKE_CURRENT_SOURCE_DIR}/tray_linux.c)
endif()
endif()
Expand All @@ -48,7 +49,8 @@ else()
target_compile_options(tray PRIVATE ${APPINDICATOR_CFLAGS})
target_link_directories(tray PRIVATE ${APPINDICATOR_LIBRARY_DIRS})
target_compile_definitions(tray PRIVATE TRAY_APPINDICATOR=1)
target_link_libraries(tray PRIVATE ${APPINDICATOR_LIBRARIES})
target_compile_definitions(tray PRIVATE TRAY_LIBNOTIFY=1)
target_link_libraries(tray PRIVATE ${APPINDICATOR_LIBRARIES} ${LIBNOTIFY_LIBRARIES})
endif()
endif()
endif()
Expand Down
55 changes: 55 additions & 0 deletions cmake/FindLIBNOTIFY.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# - Try to find LibNotify
# This module defines the following variables:
#
# LIBNOTIFY_FOUND - LibNotify was found
# LIBNOTIFY_INCLUDE_DIRS - the LibNotify include directories
# LIBNOTIFY_LIBRARIES - link these to use LibNotify
#
# Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org>
# Copyright (C) 2014 Collabora Ltd.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

find_package(PkgConfig)
pkg_check_modules(LIBNOTIFY QUIET libnotify)

find_path(LIBNOTIFY_INCLUDE_DIRS
NAMES notify.h
HINTS ${LIBNOTIFY_INCLUDEDIR}
${LIBNOTIFY_INCLUDE_DIRS}
PATH_SUFFIXES libnotify
)

find_library(LIBNOTIFY_LIBRARIES
NAMES notify
HINTS ${LIBNOTIFY_LIBDIR}
${LIBNOTIFY_LIBRARY_DIRS}
)

include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibNotify REQUIRED_VARS LIBNOTIFY_INCLUDE_DIRS LIBNOTIFY_LIBRARIES
VERSION_VAR LIBNOTIFY_VERSION)

mark_as_advanced(
LIBNOTIFY_INCLUDE_DIRS
LIBNOTIFY_LIBRARIES
)
4 changes: 4 additions & 0 deletions tray.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ struct tray_menu;
struct tray {
const char *icon;
char *tooltip;
const char *notification_icon;
const char *notification_text;
const char *notification_title;
void (*notification_cb)();
struct tray_menu *menu;
};

Expand Down
56 changes: 39 additions & 17 deletions tray_linux.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#include "tray.h"
#include <string.h>
#include <stddef.h>
#include <libayatana-appindicator/app-indicator.h>

#include <libnotify/notify.h>
#include <stddef.h>
#include <string.h>
#define TRAY_APPINDICATOR_ID "tray-id"

static AppIndicator *indicator = NULL;
static int loop_result = 0;

static int loop_result = 0;
static NotifyNotification *currentNotification = NULL;
static void _tray_menu_cb(GtkMenuItem *item, gpointer data) {
(void)item;
struct tray_menu *m = (struct tray_menu *)data;
Expand All @@ -16,23 +16,26 @@ static void _tray_menu_cb(GtkMenuItem *item, gpointer data) {

static GtkMenuShell *_tray_menu(struct tray_menu *m) {
GtkMenuShell *menu = (GtkMenuShell *)gtk_menu_new();
for (; m != NULL && m->text != NULL; m++) {
for(; m != NULL && m->text != NULL; m++) {
GtkWidget *item;
if (strcmp(m->text, "-") == 0) {
if(strcmp(m->text, "-") == 0) {
item = gtk_separator_menu_item_new();
} else {
if (m->submenu != NULL) {
}
else {
if(m->submenu != NULL) {
item = gtk_menu_item_new_with_label(m->text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item),
GTK_WIDGET(_tray_menu(m->submenu)));
} else if (m->checkbox) {
GTK_WIDGET(_tray_menu(m->submenu)));
}
else if(m->checkbox) {
item = gtk_check_menu_item_new_with_label(m->text);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), !!m->checked);
} else {
}
else {
item = gtk_menu_item_new_with_label(m->text);
}
gtk_widget_set_sensitive(item, !m->disabled);
if (m->cb != NULL) {
if(m->cb != NULL) {
g_signal_connect(item, "activate", G_CALLBACK(_tray_menu_cb), m);
}
}
Expand All @@ -43,12 +46,13 @@ static GtkMenuShell *_tray_menu(struct tray_menu *m) {
}

int tray_init(struct tray *tray) {
if (gtk_init_check(0, NULL) == FALSE) {
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_CATEGORY_APPLICATION_STATUS);
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
notify_init("tray-icon");
tray_update(tray);
return 0;
}
Expand All @@ -63,7 +67,25 @@ void tray_update(struct tray *tray) {
// GTK is all about reference counting, so previous menu should be destroyed
// here
app_indicator_set_menu(indicator, GTK_MENU(_tray_menu(tray->menu)));
if(tray->notification_text != 0 && strlen(tray->notification_text) > 0 && notify_is_initted()) {
if(currentNotification != NULL){
notify_notification_close(currentNotification,NULL);
g_object_unref(G_OBJECT(currentNotification));
}
const char *notification_icon = tray->notification_icon != NULL ? tray->notification_icon : tray->icon;
currentNotification = notify_notification_new(tray->notification_title, tray->notification_text, notification_icon);
if(tray->notification_cb != NULL){
notify_notification_add_action(currentNotification,"default","Default",tray->notification_cb,NULL,NULL);
}
notify_notification_show(currentNotification, NULL);
}
}

void tray_exit(void) { loop_result = -1; }

void tray_exit(void) {
if(currentNotification != NULL){
int v = notify_notification_close(currentNotification,NULL);
if(v == TRUE)g_object_unref(G_OBJECT(currentNotification));
}
notify_uninit();
loop_result = -1;
}
33 changes: 32 additions & 1 deletion tray_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ static WNDCLASSEX wc;
static NOTIFYICONDATA nid;
static HWND hwnd;
static HMENU hmenu = NULL;
static void (*notification_cb)() = 0;
static UINT wm_taskbarcreated;

static LRESULT CALLBACK _tray_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam,
Expand All @@ -31,6 +32,8 @@ static LRESULT CALLBACK _tray_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam,
p.x, p.y, 0, hwnd, NULL);
SendMessage(hwnd, WM_COMMAND, cmd, 0);
return 0;
} else if(lparam == NIN_BALLOONUSERCLICK && notification_cb != NULL){
notification_cb();
}
break;
case WM_COMMAND:
Expand Down Expand Up @@ -139,16 +142,44 @@ void tray_update(struct tray *tray) {
UINT id = ID_TRAY_FIRST;
hmenu = _tray_menu(tray->menu, &id);
SendMessage(hwnd, WM_INITMENUPOPUP, (WPARAM)hmenu, 0);
HICON icon;
HICON icon,largeIcon;
ExtractIconEx(tray->icon, 0, NULL, &icon, 1);
if(tray->notification_icon != 0){
ExtractIconEx(tray->notification_icon, 0, &largeIcon, NULL, 1);
} else {
ExtractIconEx(tray->icon, 0, &largeIcon, NULL, 1);
}
if (nid.hIcon) {
DestroyIcon(nid.hIcon);
}
if(nid.hBalloonIcon){
DestroyIcon(nid.hBalloonIcon);
}
nid.hIcon = icon;
if(largeIcon != 0){
nid.hBalloonIcon = largeIcon;
nid.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
}
if(tray->tooltip != 0 && strlen(tray->tooltip) > 0) {
strncpy(nid.szTip, tray->tooltip, sizeof(nid.szTip));
nid.uFlags |= NIF_TIP;
}
if(tray->notification_title != 0 && strlen(tray->notification_title) > 0){
strncpy(nid.szInfoTitle, tray->notification_title, sizeof(nid.szInfoTitle));
nid.uFlags = NIF_INFO;
} else if((nid.uFlags & NIF_INFO) == NIF_INFO) {
nid.uFlags ^= ~NIF_INFO;
strncpy(nid.szInfoTitle, "", sizeof(nid.szInfoTitle));
}
if(tray->notification_text != 0 && strlen(tray->notification_text) > 0){
strncpy(nid.szInfo, tray->notification_text, sizeof(nid.szInfo));
} else if((nid.uFlags & NIF_INFO) == NIF_INFO) {
nid.uFlags ^= ~NIF_INFO;
strncpy(nid.szInfo, "", sizeof(nid.szInfo));
}
if(tray->notification_cb != NULL){
notification_cb = tray->notification_cb;
}
Shell_NotifyIcon(NIM_MODIFY, &nid);

if (prevmenu != NULL) {
Expand Down