about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am10
-rw-r--r--configure.ac19
-rw-r--r--icons/proIcon.pngbin0 -> 662 bytes
-rw-r--r--icons/proIconMsg.pngbin0 -> 1391 bytes
-rwxr-xr-xinstall-all.sh4
-rw-r--r--src/main.c6
-rw-r--r--src/profanity.c38
-rw-r--r--src/tray.c166
-rw-r--r--src/tray.h50
10 files changed, 285 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore
index 988268d2..5a6c56c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,7 +33,6 @@ m4/
 src/config.h
 src/config.h.in
 src/config.h.in~
-src/prof_config.h
 src/gitversion.h
 src/gitversion.h.in
 src/stamp-h1
diff --git a/Makefile.am b/Makefile.am
index 57deb1a0..9dfb400c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,7 +47,8 @@ core_sources = \
 	src/plugins/callbacks.h src/plugins/callbacks.c \
 	src/plugins/autocompleters.c src/plugins/autocompleters.h \
 	src/plugins/themes.c src/plugins/themes.h \
-	src/plugins/settings.c src/plugins/settings.h
+	src/plugins/settings.c src/plugins/settings.h \
+	src/tray.h src/tray.c
 
 unittest_sources = \
 	src/contact.c src/contact.h src/common.c \
@@ -84,6 +85,7 @@ unittest_sources = \
 	src/window_list.c src/window_list.h \
 	src/event/server_events.c src/event/server_events.h \
 	src/event/client_events.c src/event/client_events.h \
+	src/tray.h src/tray.c \
 	tests/unittests/xmpp/stub_xmpp.c \
 	tests/unittests/ui/stub_ui.c \
 	tests/unittests/log/stub_log.c \
@@ -169,6 +171,8 @@ otr_unittest_sources = \
 
 themes_sources = themes/*
 
+icons_sources = icons/*
+
 script_sources = bootstrap.sh configure-debug install-all.sh
 
 man_sources = docs/profanity.1
@@ -197,6 +201,8 @@ endif
 if INCLUDE_GIT_VERSION
 BUILT_SOURCES = $(git_include)
 endif
+profanity_iconsdir = @ICONS_PATH@
+profanity_icons_DATA = $(icons_sources)
 
 if BUILD_C_API
 lib_LTLIBRARIES = libprofanity.la
@@ -225,7 +231,7 @@ endif
 
 man_MANS = $(man_sources)
 
-EXTRA_DIST = $(man_sources) $(themes_sources) $(script_sources) profrc.example LICENSE.txt
+EXTRA_DIST = $(man_sources) $(icons_sources) $(themes_sources) $(script_sources) profrc.example LICENSE.txt
 
 if INCLUDE_GIT_VERSION
 EXTRA_DIST += .git/HEAD .git/index
diff --git a/configure.ac b/configure.ac
index 5e1a5381..427c0f89 100644
--- a/configure.ac
+++ b/configure.ac
@@ -63,6 +63,8 @@ AC_ARG_WITH([xscreensaver],
     [AS_HELP_STRING([--with-xscreensaver], [use libXScrnSaver to determine idle time])])
 AC_ARG_WITH([themes],
     [AS_HELP_STRING([--with-themes[[=PATH]]], [install themes (default yes)])])
+AC_ARG_ENABLE([icons],
+    [AS_HELP_STRING([--enable-icons], [enable icons])])
 
 ### plugins
 
@@ -158,6 +160,13 @@ PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.26], [],
 PKG_CHECK_MODULES([curl], [libcurl], [],
     [AC_MSG_ERROR([libcurl is required for profanity])])
 
+# Checks GTK+ 2.0
+PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.24.10],
+                  [AC_DEFINE([HAVE_GTK], [1], [libgtk module])],
+                  [AS_IF([test "x$enable_icons" = xyes],
+                         [AC_MSG_ERROR([gtk+-2.0 or higher is required for icons])],
+                         [AC_MSG_NOTICE([gtk+-2.0 not found, icons not enabled])])])
+
 AS_IF([test "x$PLATFORM" != xosx],
     [AC_CHECK_LIB([readline], [main], [],
         [AC_MSG_ERROR([libreadline is required for profanity])])],
@@ -250,6 +259,9 @@ AS_IF([test "x$with_themes" = xno -o "x$with_themes" = xyes -o "x$with_themes" =
 AC_SUBST(THEMES_PATH)
 AM_CONDITIONAL([THEMES_INSTALL], "$THEMES_INSTALL")
 
+ICONS_PATH='${pkgdatadir}/icons'
+AC_SUBST(ICONS_PATH)
+
 ### cmocka is required only for tests, profanity shouldn't be linked with it
 ### TODO: pass cmocka_CFLAGS and cmocka_LIBS to Makefile.am
 PKG_CHECK_MODULES([cmocka], [cmocka], [],
@@ -271,9 +283,9 @@ AM_CFLAGS="-Wall -Wno-deprecated-declarations"
 AS_IF([test "x$PACKAGE_STATUS" = xdevelopment],
     [AM_CFLAGS="$AM_CFLAGS -Wunused -Werror"])
 AM_LDFLAGS="$AM_LDFLAGS -export-dynamic"
-AM_CPPFLAGS="$AM_CPPFLAGS $glib_CFLAGS $curl_CFLAGS $libnotify_CFLAGS $PYTHON_CPPFLAGS"
-AM_CPPFLAGS="$AM_CPPFLAGS -DTHEMES_PATH=\"\\\"$THEMES_PATH\\\"\""
-LIBS="$glib_LIBS $curl_LIBS $libnotify_LIBS $PYTHON_LIBS $PYTHON_LDFLAGS $LIBS"
+AM_CPPFLAGS="$AM_CPPFLAGS $glib_CFLAGS $curl_CFLAGS $libnotify_CFLAGS $PYTHON_CPPFLAGS ${GTK_CFLAGS}"
+AM_CPPFLAGS="$AM_CPPFLAGS -DTHEMES_PATH=\"\\\"$THEMES_PATH\\\"\" -DICONS_PATH=\"\\\"$ICONS_PATH\\\"\""
+LIBS="$glib_LIBS $curl_LIBS $libnotify_LIBS $PYTHON_LIBS $PYTHON_LDFLAGS ${GTK_LIBS} $LIBS"
 
 AC_SUBST(AM_LDFLAGS)
 AC_SUBST(AM_CFLAGS)
@@ -295,5 +307,6 @@ echo "LIBS           : $LIBS"
 echo "XML Parser     : $PARSER"
 echo "Install themes : $THEMES_INSTALL"
 echo "Themes path    : $THEMES_PATH"
+echo "Icons path     : $ICONS_PATH"
 echo ""
 echo "Now you can run \`make' to build profanity"
diff --git a/icons/proIcon.png b/icons/proIcon.png
new file mode 100644
index 00000000..2ccdba62
--- /dev/null
+++ b/icons/proIcon.png
Binary files differdiff --git a/icons/proIconMsg.png b/icons/proIconMsg.png
new file mode 100644
index 00000000..d92108c2
--- /dev/null
+++ b/icons/proIconMsg.png
Binary files differdiff --git a/install-all.sh b/install-all.sh
index cbb8aad8..8eb6e3da 100755
--- a/install-all.sh
+++ b/install-all.sh
@@ -24,7 +24,7 @@ debian_prepare()
     echo
     echo Profanity installer... installing dependencies
     echo
-    sudo apt-get -y install git automake autoconf libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr5-dev libreadline-dev libtool libgpgme11-dev
+    sudo apt-get -y install git automake autoconf libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr5-dev libreadline-dev libtool libgpgme11-dev libgtk2.0-dev
 
 }
 
@@ -34,7 +34,7 @@ fedora_prepare()
     echo Profanity installer... installing dependencies
     echo
 
-    sudo dnf -y install gcc git autoconf automake openssl-devel expat-devel ncurses-devel glib2-devel libnotify-devel libcurl-devel libXScrnSaver-devel libotr-devel readline-devel libtool gpgme-devel
+    sudo dnf -y install gcc git autoconf automake openssl-devel expat-devel ncurses-devel glib2-devel libnotify-devel libcurl-devel libXScrnSaver-devel libotr-devel readline-devel libtool gpgme-devel gtk2-devel
 }
 
 opensuse_prepare()
diff --git a/src/main.c b/src/main.c
index 128aecda..7f87c165 100644
--- a/src/main.c
+++ b/src/main.c
@@ -136,6 +136,12 @@ main(int argc, char **argv)
         g_print("Python plugins: Disabled\n");
 #endif
 
+#ifdef HAVE_GTK
+        g_print("GTK icons: Enabled\n");
+#else
+        g_print("GTK icons: Disabled\n");
+#endif
+
         return 0;
     }
 
diff --git a/src/profanity.c b/src/profanity.c
index a78ccfdc..2595f5f7 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -37,6 +37,10 @@
 #include "gitversion.h"
 #endif
 
+#ifdef HAVE_GTK
+#include <gtk/gtk.h>
+#include "tray.h"
+#endif
 #include <locale.h>
 #include <signal.h>
 #include <stdlib.h>
@@ -92,10 +96,21 @@ char *saved_status;
 
 static gboolean cont = TRUE;
 static gboolean force_quit = FALSE;
+#ifdef HAVE_GTK
+static gboolean gtk_ready = FALSE;
+#endif
 
 void
 prof_run(char *log_level, char *account_name)
 {
+#ifdef HAVE_GTK
+    gtk_ready = gtk_init_check(0, NULL);
+    log_debug("Env is GTK-ready: %s", gtk_ready ? "true" : "false");
+    if (gtk_ready) {
+        gtk_init(0, NULL);
+        gtk_main_iteration_do(FALSE);
+    }
+#endif
     _init(log_level);
     plugins_on_start();
     _connect_default(account_name);
@@ -130,6 +145,11 @@ prof_run(char *log_level, char *account_name)
         jabber_process_events(10);
         iq_autoping_check();
         ui_update();
+#ifdef HAVE_GTK
+        if (gtk_ready) {
+            gtk_main_iteration_do(FALSE);
+        }
+#endif
     }
 }
 
@@ -352,6 +372,12 @@ _init(char *log_level)
 #endif
     atexit(_shutdown);
     plugins_init();
+#ifdef HAVE_GTK
+    if (gtk_ready) {
+        log_debug("Building GTK icon");
+        create_tray();
+    }
+#endif
     inp_nonblocking(TRUE);
 }
 
@@ -370,7 +396,11 @@ _shutdown(void)
     if (conn_status == JABBER_CONNECTED) {
         cl_ev_disconnect();
     }
-
+#ifdef HAVE_GTK
+    if (gtk_ready) {
+        destroy_tray();
+    }
+#endif
     jabber_shutdown();
     plugins_on_shutdown();
     muc_close();
@@ -404,6 +434,8 @@ _create_directories(void)
 
     GString *themes_dir = g_string_new(xdg_config);
     g_string_append(themes_dir, "/profanity/themes");
+    GString *icons_dir = g_string_new(xdg_config);
+    g_string_append(icons_dir, "/profanity/icons");
     GString *chatlogs_dir = g_string_new(xdg_data);
     g_string_append(chatlogs_dir, "/profanity/chatlogs");
     GString *logs_dir = g_string_new(xdg_data);
@@ -414,6 +446,9 @@ _create_directories(void)
     if (!mkdir_recursive(themes_dir->str)) {
         log_error("Error while creating directory %s", themes_dir->str);
     }
+    if (!mkdir_recursive(icons_dir->str)) {
+        log_error("Error while creating directory %s", icons_dir->str);
+    }
     if (!mkdir_recursive(chatlogs_dir->str)) {
         log_error("Error while creating directory %s", chatlogs_dir->str);
     }
@@ -425,6 +460,7 @@ _create_directories(void)
     }
 
     g_string_free(themes_dir, TRUE);
+    g_string_free(icons_dir, TRUE);
     g_string_free(chatlogs_dir, TRUE);
     g_string_free(logs_dir, TRUE);
     g_string_free(plugins_dir, TRUE);
diff --git a/src/tray.c b/src/tray.c
new file mode 100644
index 00000000..98039977
--- /dev/null
+++ b/src/tray.c
@@ -0,0 +1,166 @@
+/*
+ * tray.c
+ *
+ * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#include "config.h"
+
+#ifdef HAVE_GTK
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "tray.h"
+#include "window_list.h"
+#include "log.h"
+
+static GtkStatusIcon *prof_tray = NULL;
+static GString *icon_filename = NULL;
+static GString *icon_msg_filename = NULL;
+static gint unread_messages;
+static gboolean shutting_down;
+static guint timer;
+
+/* {{{ Privates */
+
+/*
+ * Get icons from installation share folder or (if defined) .locale user's folder
+ *
+ * As implementation, looking through all the entries in the .locale folder is chosen.
+ * While useless as now, it might be useful in case an association name-icon is created.
+ * As now, with 2 icons only, this is pretty useless, but it is not harming ;)
+ *
+ */
+static void
+_get_icons(void)
+{
+    GString *icons_dir =  NULL;
+
+#ifdef ICONS_PATH
+
+    icons_dir = g_string_new(ICONS_PATH);
+    icon_filename = g_string_new(icons_dir->str);
+    icon_msg_filename = g_string_new(icons_dir->str);
+    g_string_append(icon_filename, "/proIcon.png");
+    g_string_append(icon_msg_filename, "/proIconMsg.png");
+    g_string_free(icons_dir, TRUE);
+
+#endif /* ICONS_PATH */
+
+    gchar *xdg_config = xdg_get_config_home();
+    icons_dir = g_string_new(xdg_config);
+    g_free(xdg_config);
+    g_string_append(icons_dir, "/profanity/icons");
+    GError *err = NULL;
+    if (!g_file_test(icons_dir->str, G_FILE_TEST_IS_DIR)) {
+        return;
+    }
+    GDir *dir = g_dir_open(icons_dir->str, 0, &err);
+    if (dir) {
+        GString *name = g_string_new(g_dir_read_name(dir));
+        while (name->len) {
+            if (g_strcmp0("proIcon.png", name->str) == 0) {
+                if (icon_filename) {
+                    g_string_free(icon_filename, TRUE);
+                }
+                icon_filename = g_string_new(icons_dir->str);
+                g_string_append(icon_filename, "/proIcon.png");
+            } else if (g_strcmp0("proIconMsg.png", name->str) == 0) {
+                if (icon_msg_filename) {
+                    g_string_free(icon_msg_filename, TRUE);
+                }
+                icon_msg_filename = g_string_new(icons_dir->str);
+                g_string_append(icon_msg_filename, "/proIconMsg.png");
+            }
+            g_string_free(name, TRUE);
+            name = g_string_new(g_dir_read_name(dir));
+        }
+        g_string_free(name, TRUE);
+    } else {
+        log_error("Unable to open dir: %s", err->message);
+        g_error_free(err);
+    }
+    g_dir_close(dir);
+    g_string_free(icons_dir, TRUE);
+}
+
+/*
+ * Callback for the timer
+ *
+ * This is the callback that the timer is calling in order to check if messages are there.
+ *
+ */
+gboolean
+_tray_change_icon(gpointer data)
+{
+    if (shutting_down) {
+        return FALSE;
+    }
+
+    unread_messages = wins_get_total_unread();
+
+    if (unread_messages) {
+        gtk_status_icon_set_from_file(prof_tray, icon_msg_filename->str);
+    } else {
+        gtk_status_icon_set_from_file(prof_tray, icon_filename->str);
+    }
+
+    return TRUE;
+}
+
+/* }}} */
+/* {{{ Public */
+
+void
+create_tray(void)
+{
+    _get_icons();
+    prof_tray = gtk_status_icon_new_from_file(icon_filename->str);
+    shutting_down = FALSE;
+    timer = g_timeout_add(5000, _tray_change_icon, NULL);
+}
+
+void
+destroy_tray(void)
+{
+    shutting_down = TRUE;
+    g_source_remove(timer);
+    if (prof_tray) {
+        g_clear_object(&prof_tray);
+        prof_tray = NULL;
+    }
+    g_string_free(icon_filename, TRUE);
+    g_string_free(icon_msg_filename, TRUE);
+}
+
+/* }}} */
+#endif
diff --git a/src/tray.h b/src/tray.h
new file mode 100644
index 00000000..416ca7d2
--- /dev/null
+++ b/src/tray.h
@@ -0,0 +1,50 @@
+/*
+ * tray.h
+ *
+ * Copyright (C) 2012 - 2016 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#ifndef PROFANITY_TRAY_H
+#define PROFANITY_TRAY_H
+
+/*
+ * Create tray icon
+ *
+ * This will initialize the timer that will be called in order to change the icons
+ * and will search the icons in the defaults paths
+ */
+void create_tray(void);
+/*
+ * Destroy tray icon
+ */
+void destroy_tray(void);
+
+#endif