/* X-Chat * Copyright (C) 2006-2007 Peter Zelezny. * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include "../common/hexchat-plugin.h" #include "../common/hexchat.h" #include "../common/hexchatc.h" #include "../common/inbound.h" #include "../common/server.h" #include "../common/fe.h" #include "../common/util.h" #include "../common/outbound.h" #include "fe-gtk.h" #include "pixmaps.h" #include "maingui.h" #include "menu.h" #include "gtkutil.h" #ifndef WIN32 #include #endif typedef enum /* current icon status */ { TS_NONE, TS_MESSAGE, TS_HIGHLIGHT, TS_FILEOFFER, TS_CUSTOM /* plugin */ } TrayStatus; typedef enum { WS_FOCUSED, WS_NORMAL, WS_HIDDEN } WinStatus; typedef GdkPixbuf* TrayIcon; #define tray_icon_from_file(f) gdk_pixbuf_new_from_file(f,NULL) #define tray_icon_free(i) g_object_unref(i) #define ICON_NORMAL pix_tray_normal #define ICON_MSG pix_tray_message #define ICON_HILIGHT pix_tray_highlight #define ICON_FILE pix_tray_fileoffer #define TIMEOUT 500 static GtkStatusIcon *sticon; static gint flash_tag; static TrayStatus tray_status; #ifdef WIN32 static guint tray_menu_timer; static gint64 tray_menu_inactivetime; #endif static hexchat_plugin *ph; static TrayIcon custom_icon1; static TrayIcon custom_icon2; static int tray_priv_count = 0; static int tray_pub_count = 0; static int tray_hilight_count = 0; static int tray_file_count = 0; static int tray_restore_timer = 0; void tray_apply_setup (void); static gboolean tray_menu_try_restore (void); static void tray_cleanup (void); static void tray_init (void); static WinStatus tray_get_window_status (void) { const char *st; st = hexchat_get_info (ph, "win_status"); if (!st) return WS_HIDDEN; if (!strcmp (st, "active")) return WS_FOCUSED; if (!strcmp (st, "hidden")) return WS_HIDDEN; return WS_NORMAL; } static int tray_count_channels (void) { int cons = 0; GSList *list; session *sess; for (list = sess_list; list; list = list->next) { sess = list->data; if (sess->server->connected && sess->channel[0] && sess->type == SESS_CHANNEL) cons++; } return cons; } static int tray_count_networks (void) { int cons = 0; GSList *list; for (list = serv_list; list; list = list->next) { if (((server *)list->data)->connected) cons++; } return cons; } void fe_tray_set_tooltip (const char *text) { if (sticon) gtk_status_icon_set_tooltip_text (sticon, text); } static void tray_set_tipf (const char *format, ...) { va_list args; char *buf; va_start (args, format); buf = g_strdup_vprintf (format, args); va_end (args); fe_tray_set_tooltip (buf); g_free (buf); } static void tray_stop_flash (void) { int nets, chans; if (flash_tag) { g_source_remove (flash_tag); flash_tag = 0; } if (sticon) { gtk_status_icon_set_from_pixbuf (sticon, ICON_NORMAL); nets = tray_count_networks (); chans = tray_count_channels (); if (nets) tray_set_tipf (_("Connected to %u networks and %u channels - %s"), nets, chans, _(DISPLAY_NAME)); else tray_set_tipf ("%s - %s", _("Not connected."), _(DISPLAY_NAME)); } if (custom_icon1) { tray_icon_free (custom_icon1); custom_icon1 = NULL; } if (custom_icon2) { tray_icon_free (custom_icon2); custom_icon2 = NULL; } tray_status = TS_NONE; } static void tray_reset_counts (void) { tray_priv_count = 0; tray_pub_count = 0; tray_hilight_count = 0; tray_file_count = 0; } static int tray_timeout_cb (TrayIcon icon) { if (custom_icon1) { if (gtk_status_icon_get_pixbuf (sticon) == custom_icon1) { if (custom_icon2) gtk_status_icon_set_from_pixbuf (sticon, custom_icon2); else gtk_status_icon_set_from_pixbuf (sticon, ICON_NORMAL); } else { gtk_status_icon_set_from_pixbuf (sticon, custom_icon1); } } else { if (gtk_status_icon_get_pixbuf (sticon) == ICON_NORMAL) gtk_status_icon_set_from_pixbuf (sticon, icon); else gtk_status_icon_set_from_pixbuf (sticon, ICON_NORMAL); } return 1; } static void tray_set_flash (TrayIcon icon) { if (!sticon) return; /* already flashing the same icon */ if (flash_tag && gtk_status_icon_get_pixbuf (sticon) == icon) return; /* no flashing if window is focused */ if (tray_get_window_status () == WS_FOCUSED) return; tray_stop_flash (); gtk_status_icon_set_from_pixbuf (sticon, icon); if (prefs.hex_gui_tray_blink) flash_tag = g_timeout_add (TIMEOUT, (GSourceFunc) tray_timeout_cb, icon); } void fe_tray_set_flash (const char *filename1, const char *filename2, int tout) { tray_apply_setup (); if (!sticon) return; tray_stop_flash (); if (tout == -1) tout = TIMEOUT; custom_icon1 = tray_icon_from_file (filename1); if (filename2) custom_icon2 = tray_icon_from_file (filename2); gtk_status_icon_set_from_pixbuf (sticon, custom_icon1); flash_tag = g_timeout_add (tout, (GSourceFunc) tray_timeout_cb, NULL); tray_status = TS_CUSTOM; } void fe_tray_set_icon (feicon icon) { tray_apply_setup (); if (!sticon) return; tray_stop_flash (); switch (icon) { case FE_ICON_NORMAL: break; case FE_ICON_MESSAGE: case FE_ICON_PRIVMSG: tray_set_flash (ICON_MSG); break; case FE_ICON_HIGHLIGHT: tray_set_flash (ICON_HILIGHT); break; case FE_ICON_FILEOFFER: tray_set_flash (ICON_FILE); } } void fe_tray_set_file (const char *filename) { tray_apply_setup (); if (!sticon) return; tray_stop_flash (); if (filename) { custom_icon1 = tray_icon_from_file (filename); gtk_status_icon_set_from_pixbuf (sticon, custom_icon1); tray_status = TS_CUSTOM; } } gboolean tray_toggle_visibility (gboolean force_hide) { static int x, y; static GdkScreen *screen; static int maximized; static int fullscreen; GtkWindow *win; if (!sticon) return FALSE; /* ph may have an invalid context now */ hexchat_set_context (ph, hexchat_find_context (ph, NULL, NULL)); win = GTK_WINDOW (hexchat_get_info (ph, "gtkwin_ptr")); tray_stop_flash (); tray_reset_counts (); if (!win) return FALSE; if (force_hide || gtk_widget_get_visible (GTK_WIDGET (win))) { if (prefs.hex_gui_tray_away) hexchat_command (ph, "ALLSERV AWAY"); gtk_window_get_position (win, &x, &y); screen = gtk_window_get_screen (win); maximized = prefs.hex_gui_win_state; fullscreen = prefs.hex_gui_win_fullscreen; gtk_widget_hide (GTK_WIDGET (win)); } else { if (prefs.hex_gui_tray_away) hexchat_command (ph, "ALLSERV BACK"); gtk_window_set_screen (win, screen); gtk_window_move (win, x, y); if (maximized) gtk_window_maximize (win); if (fullscreen) gtk_window_fullscreen (win); gtk_widget_show (GTK_WIDGET (win)); gtk_window_deiconify (win); gtk_window_present (win); } return TRUE; } static void tray_menu_restore_cb (GtkWidget
/* HexChat
 * Copyright (C) 1998-2010 Peter Zelezny.
 * Copyright (C) 2009-2013 Berke Viktor.
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifndef HEXCHAT_ASCII_H
#define HEXCHAT_ASCII_H

void ascii_open (void);

#endif
(_("Private message from: %s (%s) - %s"), from, network, _(DISPLAY_NAME)); else tray_set_tipf (_("%u private messages, latest from: %s (%s) - %s"), tray_priv_count, from, network, _(DISPLAY_NAME)); } } static int tray_priv_cb (char *word[], void *userdata) { tray_priv (word[1], word[2]); return HEXCHAT_EAT_NONE; } static int tray_invited_cb (char *word[], void *userdata) { if (!prefs.hex_away_omit_alerts || tray_find_away_status () != 1) tray_priv (word[2], "Invited"); return HEXCHAT_EAT_NONE; } static int tray_dcc_cb (char *word[], void *userdata) { const char *network; /* if (tray_status == TS_FILEOFFER) return HEXCHAT_EAT_NONE;*/ network = hexchat_get_info (ph, "network"); if (!network) network = hexchat_get_info (ph, "server"); if (prefs.hex_input_tray_priv && (!prefs.hex_away_omit_alerts || tray_find_away_status () != 1)) { tray_set_flash (ICON_FILE); tray_file_count++; if (tray_file_count == 1) tray_set_tipf (_("File offer from: %s (%s) - %s"), word[1], network, _(DISPLAY_NAME)); else tray_set_tipf (_("%u file offers, latest from: %s (%s) - %s"), tray_file_count, word[1], network, _(DISPLAY_NAME)); } return HEXCHAT_EAT_NONE; } static int tray_focus_cb (char *word[], void *userdata) { tray_stop_flash (); tray_reset_counts (); return HEXCHAT_EAT_NONE; } static void tray_cleanup (void) { tray_stop_flash (); if (sticon) { g_object_unref ((GObject *)sticon); sticon = NULL; } } void tray_apply_setup (void) { if (sticon) { if (!prefs.hex_gui_tray) tray_cleanup (); } else { GtkWindow *window = GTK_WINDOW(hexchat_get_info (ph, "gtkwin_ptr")); if (prefs.hex_gui_tray && gtkutil_tray_icon_supported (window)) tray_init (); } } int tray_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg) { /* we need to save this for use with any hexchat_* functions */ ph = plugin_handle; *plugin_name = ""; *plugin_desc = ""; *plugin_version = ""; hexchat_hook_print (ph, "Channel Msg Hilight", -1, tray_hilight_cb, NULL); hexchat_hook_print (ph, "Channel Action Hilight", -1, tray_hilight_cb, NULL); hexchat_hook_print (ph, "Channel Message", -1, tray_message_cb, NULL); hexchat_hook_print (ph, "Channel Action", -1, tray_message_cb, NULL); hexchat_hook_print (ph, "Channel Notice", -1, tray_message_cb, NULL); hexchat_hook_print (ph, "Private Message", -1, tray_priv_cb, NULL); hexchat_hook_print (ph, "Private Message to Dialog", -1, tray_priv_cb, NULL); hexchat_hook_print (ph, "Private Action", -1, tray_priv_cb, NULL); hexchat_hook_print (ph, "Private Action to Dialog", -1, tray_priv_cb, NULL); hexchat_hook_print (ph, "Notice", -1, tray_priv_cb, NULL); hexchat_hook_print (ph, "Invited", -1, tray_invited_cb, NULL); hexchat_hook_print (ph, "DCC Offer", -1, tray_dcc_cb, NULL); hexchat_hook_print (ph, "Focus Window", -1, tray_focus_cb, NULL); GtkWindow *window = GTK_WINDOW(hexchat_get_info (ph, "gtkwin_ptr")); if (prefs.hex_gui_tray && gtkutil_tray_icon_supported (window)) tray_init (); return 1; /* return 1 for success */ } int tray_plugin_deinit (hexchat_plugin *plugin_handle) { #ifdef WIN32 tray_cleanup (); #endif return 1; }