📄 notify.c
字号:
/* * Purple buddy notification plugin. * * Copyright (C) 2000-2001, Eric Warmenhoven (original code) * Copyright (C) 2002, Etan Reisner <deryni@eden.rutgers.edu> (rewritten code) * Copyright (C) 2003, Christian Hammond (update for changed API) * Copyright (C) 2003, Brian Tarricone <bjt23@cornell.edu> (mostly rewritten) * Copyright (C) 2003, Mark Doliner (minor cleanup) * Copyright (C) 2003, Etan Reisner (largely rewritten again) * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *//* TODO * 22:22:17 <seanegan> deryni: speaking of notify.c... you know what else * might be a neat feature? * 22:22:30 <seanegan> Changing the window icon. * 22:23:25 <deryni> seanegan: To what? * 22:23:42 <seanegan> deryni: I dunno. Flash it between the regular icon and * blank or something. * 22:23:53 <deryni> Also I think purple might re-set that sort of frequently, * but I'd have to look. * 22:25:16 <seanegan> deryni: I keep my conversations in one workspace and am * frequently in an another, and the icon flashing in the pager would be a * neat visual clue. *//* * From Etan, 2002: * -Added config dialog * -Added control over notification method * -Added control over when to release notification * * -Added option to get notification for chats also * -Cleaned up code * -Added option to notify on click as it's own option * rather then as what happens when on focus isn't clicked * -Added apply button to change the denotification methods for * open conversation windows * -Fixed apply to conversations, count now keeps count across applies * -Fixed(?) memory leak, and in the process fixed some stupidities * -Hit enter when done editing the title string entry box to save it * * Thanks to Carles Pina i Estany <carles@pinux.info> * for count of new messages option * * From Brian, 20 July 2003: * -Use new xml prefs * -Better handling of notification states tracking * -Better pref change handling * -Fixed a possible memleak and possible crash (rare) * -Use gtk_window_get_title() rather than gtkwin->title * -Other random fixes and cleanups * * Etan again, 12 August 2003: * -Better use of the new xml prefs * -Removed all bitmask stuff * -Even better pref change handling * -Removed unnecessary functions * -Reworking of notification/unnotification stuff * -Header file include cleanup * -General code cleanup * * Etan yet again, 04 April 2004: * -Re-added Urgent option * -Re-added unnotify on focus option (still needs work, as it will only * react to focus-in events when the entry or history widgets are focused) * * Sean, 08 January, 2005: * -Added Raise option, formally in Purple proper */#include "internal.h"#include "pidgin.h"#include "gtkprefs.h"#include "conversation.h"#include "prefs.h"#include "signals.h"#include "version.h"#include "debug.h"#include "gtkplugin.h"#include "gtkutils.h"#ifndef _WIN32#include <X11/Xatom.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#endif#define NOTIFY_PLUGIN_ID "gtk-x11-notify"static PurplePlugin *my_plugin = NULL;#ifndef _WIN32static GdkAtom _Cardinal = GDK_NONE;static GdkAtom _PurpleUnseenCount = GDK_NONE;#endif/* notification set/unset */static int notify(PurpleConversation *conv, gboolean increment);static void notify_win(PidginWindow *purplewin);static void unnotify(PurpleConversation *conv, gboolean reset);static int unnotify_cb(GtkWidget *widget, gpointer data, PurpleConversation *conv);/* gtk widget callbacks for prefs panel */static void type_toggle_cb(GtkWidget *widget, gpointer data);static void method_toggle_cb(GtkWidget *widget, gpointer data);static void notify_toggle_cb(GtkWidget *widget, gpointer data);static gboolean options_entry_cb(GtkWidget *widget, GdkEventFocus *event, gpointer data);static void apply_method(void);static void apply_notify(void);/* string function */static void handle_string(PidginWindow *purplewin);/* count_title function */static void handle_count_title(PidginWindow *purplewin);/* count_xprop function */static void handle_count_xprop(PidginWindow *purplewin);/* urgent function */static void handle_urgent(PidginWindow *purplewin, gboolean set);/* raise function */static void handle_raise(PidginWindow *purplewin);/****************************************//* Begin doing stuff below this line... *//****************************************/static guintcount_messages(PidginWindow *purplewin){ guint count = 0; GList *convs = NULL, *l; for (convs = purplewin->gtkconvs; convs != NULL; convs = convs->next) { PidginConversation *conv = convs->data; for (l = conv->convs; l != NULL; l = l->next) { count += GPOINTER_TO_INT(purple_conversation_get_data(l->data, "notify-message-count")); } } return count;}static intnotify(PurpleConversation *conv, gboolean increment){ gint count; gboolean has_focus; PidginWindow *purplewin = NULL; if (conv == NULL) return 0; /* We want to remove the notifications, but not reset the counter */ unnotify(conv, FALSE); purplewin = PIDGIN_CONVERSATION(conv)->win; /* If we aren't doing notifications for this type of conversation, return */ if (((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && !purple_prefs_get_bool("/plugins/gtk/X11/notify/type_im")) || ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) && !purple_prefs_get_bool("/plugins/gtk/X11/notify/type_chat"))) return 0; g_object_get(G_OBJECT(purplewin->window), "has-toplevel-focus", &has_focus, NULL); if (purple_prefs_get_bool("/plugins/gtk/X11/notify/type_focused") || !has_focus) { if (increment) { count = GPOINTER_TO_INT(purple_conversation_get_data(conv, "notify-message-count")); count++; purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(count)); } notify_win(purplewin); } return 0;}static voidnotify_win(PidginWindow *purplewin){ if (count_messages(purplewin) <= 0) return; if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_count")) handle_count_title(purplewin); if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_count_xprop")) handle_count_xprop(purplewin); if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_string")) handle_string(purplewin); if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_urgent")) handle_urgent(purplewin, TRUE); if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_raise")) handle_raise(purplewin);}static voidunnotify(PurpleConversation *conv, gboolean reset){ PurpleConversation *active_conv = NULL; PidginWindow *purplewin = NULL; g_return_if_fail(conv != NULL); purplewin = PIDGIN_CONVERSATION(conv)->win; active_conv = pidgin_conv_window_get_active_conversation(purplewin); /* reset the conversation window title */ purple_conversation_autoset_title(active_conv); if (reset) { /* Only need to actually remove the urgent hinting here, since * removing it just to have it readded in re-notify is an * unnecessary couple extra RTs to the server */ handle_urgent(purplewin, FALSE); purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0)); /* Same logic as for the urgent hint, xprops are also a RT. * This needs to go here so that it gets the updated message * count. */ handle_count_xprop(purplewin); } return;}static intunnotify_cb(GtkWidget *widget, gpointer data, PurpleConversation *conv){ if (GPOINTER_TO_INT(purple_conversation_get_data(conv, "notify-message-count")) != 0) unnotify(conv, TRUE); return 0;}static gbooleanmessage_displayed_cb(PurpleAccount *account, const char *who, char *message, PurpleConversation *conv, PurpleMessageFlags flags){ if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && purple_prefs_get_bool("/plugins/gtk/X11/notify/type_chat_nick") && !(flags & PURPLE_MESSAGE_NICK))) return FALSE; if ((flags & PURPLE_MESSAGE_RECV) && !(flags & PURPLE_MESSAGE_DELAYED)) notify(conv, TRUE); return FALSE;}static voidim_sent_im(PurpleAccount *account, const char *receiver, const char *message){ PurpleConversation *conv = NULL; if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_send")) { conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, receiver, account); unnotify(conv, TRUE); }}static voidchat_sent_im(PurpleAccount *account, const char *message, int id){ PurpleConversation *conv = NULL; if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_send")) { conv = purple_find_chat(purple_account_get_connection(account), id); unnotify(conv, TRUE); }}static intattach_signals(PurpleConversation *conv){ PidginConversation *gtkconv = NULL; PidginWindow *gtkwin = NULL; GSList *imhtml_ids = NULL, *entry_ids = NULL; guint id; gtkconv = PIDGIN_CONVERSATION(conv); if (!gtkconv) { purple_debug_misc("notify", "Failed to find gtkconv\n"); return 0; } gtkwin = gtkconv->win; if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_focus")) { /* TODO should really find a way to make this work no matter * where the focus is inside the conv window, without having * to bind to focus-in-event on the g(d|t)kwindow */ /* try setting the signal on the focus-in-event for * gtkwin->notebook->container? */ id = g_signal_connect(G_OBJECT(gtkconv->entry), "focus-in-event", G_CALLBACK(unnotify_cb), conv);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -