[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: RFC: status icon support

From: Tom Tromey
Subject: Re: RFC: status icon support
Date: Sun, 13 Jan 2008 18:01:40 -0700
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.990 (gnu/linux)

>>>>> "Michael" == Michael Olson <address@hidden> writes:

Michael> [ ... excellent bug report ]
Michael> I suspect a race condition.

Yes, I think you are right.  I am not sure but maybe the answer is to
call gtk_main_iteration to flush the gtk event queue.  I am testing
that.  If that doesn't work, I guess I'll have to learn more about the
Emacs event stuff... scary.  I may need help.

Michael> Once this issue is fixed, I'd love to see this feature hit
Michael> Emacs CVS.  It will be particularly nice for ERC once your
Michael> erc-status.el is adapted to work with the new code.

I've appended my updated erc-status.el.  I haven't tried it at all, I
just rewrote it to the new API.  

Michael> ;;   => "Couldn't connect to notification server"
Michael> ;;   => libnotify-Message: Unable to get session bus: Failed to
Michael> ;;      execute dbus-launch to autolaunch D-Bus session
Michael> ;;   => Does not show "foo" popup

Are you running dbus?  And do you have a system tray in your panel?
I'm not an expert here, either, but I would only expect these errors
if one of those answers is "no".

FWIW I do see the racy behavior you pointed out, but I don't see this
error.  I'm running a rather standard Gnome desktop -- whatever is in
Fedora Core 6.  My panel does have a system tray.

The notification stuff is cross-desktop, so it should also work if you
are a KDE user.  I have not tested that with the Emacs-based code, but
I have tried out other system-tray-using Gnome applications on KDE.

Thanks for taking the time to try this out.


;;; erc-status.el --- notification area support for ERC

;; Copyright (C) 2007, 2008 Tom Tromey <address@hidden>

;; Author: Tom Tromey <address@hidden>
;; Version: 0.2
;; Keywords: comm

;; This file is not (yet) part of GNU Emacs.
;; However, it is distributed under the same license.

;; GNU Emacs 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, or (at your option)
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Commentary:

;; This provides nice support for the notification area to ERC.  In
;; particular it:
;; * Will blink the icon when you get a private message or are paged
;;   in a channel.
;; * Left-click on the blinking icon will show the appropriate channel
;;   buffer in some frame (which is then raised).  If there are
;;   multiple pages at once, it will show one and you can click again
;;   to go to the next one.
;; * Will pop up notification bubbles when you connect to or
;;   disconnect from a server.
;; This is regular erc module named 'status'; you can enable it as you
;; would any other module.

;; TO DO:
;; - make tool tip show some kind of real status ...?
;; - use a nicer icon
;; - add a menu
;; - integrate with auto-query a bit better
;; - let left click use specified frame or make a new frame?
;; - when last server connection is closed, remove icon

(require 'systray)

(require 'erc)

;; The status icon object.
(defvar erc-status-status-icon nil)

;; List of ERC buffers that caused the status icon to blink.
(defvar erc-status-buffer-list nil)

(defun erc-status-remove-buffer (buffer)
  ;; If the list is not empty, and removing an element makes the list
  ;; empty, stop blinking.
  (and erc-status-buffer-list
       (not (setq erc-status-buffer-list (delq buffer erc-status-buffer-list)))
       (modify-status-icon erc-status-status-icon '((blinking . nil)))))

(defun erc-status-add-buffer (buffer)
  (and (not (erc-buffer-visible buffer))
         (modify-status-icon erc-status-status-icon '((blinking . t)))
         (or (memq buffer erc-status-buffer-list)
             (setq erc-status-buffer-list (cons buffer

(defun erc-status-match-hook (match-type nick message)
  ;; Look for user's nick and make the icon blink.
  (if (eq match-type 'current-nick)
      (erc-status-add-buffer (current-buffer))))

(defun erc-status-buffer-killed ()
  ;; If one of our buffers was killed, remove it.
  (erc-status-remove-buffer (current-buffer)))

(defun erc-status-window-configuration-changed ()
  (let ((new-list)
        (iter erc-status-buffer-list))
    (while iter
      (or (erc-buffer-visible (car iter))
          (setq new-list (cons (car iter) new-list)))
      (setq iter (cdr iter)))
    (or (setq erc-status-buffer-list new-list)
        (modify-status-icon erc-status-status-icon '((blinking . nil))))))

(defun erc-status-disconnected (nick ip reason)
  ;; FIXME: should mention the server from which we were disconnected.
  ;; FIXME: add a :action to reconnect.
  (show-status-icon-message erc-status-status-icon
                            (concat "Disconnected: " reason)))

(defun erc-status-after-connect (server nick)
  (show-status-icon-message erc-status-status-icon
                            (concat "Connected to " server " as " nick)))

(defun erc-status-select-first-buffer ()
  "Switch to the first ERC buffer requiring your attention.
If there is no such buffer, do nothing."
  (when erc-status-buffer-list
    (switch-to-buffer (car erc-status-buffer-list))


;; From: http://www.emacswiki.org/cgi-bin/wiki/ErcPageMe
;; Then modified to suit.

(defun erc-status-PRIVMSG (proc parsed)
  (let* ((nick (car (erc-parse-user (erc-response.sender parsed))))
         (target (car (erc-response.command-args parsed)))
         (msg (erc-response.contents parsed))
         (query  (if (not erc-query-on-unjoined-chan-privmsg)
                   (if (erc-current-nick-p target)
    (when (and (erc-current-nick-p target)
               (not (erc-is-message-ctcp-and-not-action-p msg)))
      ;; Note: assumes you are using auto-query.
      (erc-status-add-buffer (erc-get-buffer query proc))))
  ;; Always return nil.


(define-erc-module status nil
  "Notification area support for ERC."
  ;; Enable.
  ((unless erc-status-status-icon
     (setq erc-status-status-icon
           (make-status-icon '((help-echo . "ERC - IRC client for Emacs")
                               (click-callback . 
   (add-hook 'erc-text-matched-hook 'erc-status-match-hook)
   (add-hook 'kill-buffer-hook 'erc-status-buffer-killed)
   (add-hook 'window-configuration-change-hook
   (add-hook 'erc-after-connect 'erc-status-after-connect)
   (add-hook 'erc-disconnected-hook 'erc-status-disconnected)
   ;; FIXME: Must come *after* erc-auto-query.  Some sort of
   ;; auto-query hook or the like would be good here.
   (add-hook 'erc-server-PRIVMSG-functions 'erc-status-PRIVMSG t))

  ;; Disable.
  ((when erc-status-status-icon
     (delete-status-icon erc-status-status-icon)
     (setq erc-status-status-icon nil))
   (remove-hook 'erc-text-matched-hook 'erc-status-match-hook)
   (remove-hook 'kill-buffer-hook 'erc-status-buffer-killed)
   (remove-hook 'window-configuration-change-hook
   (remove-hook 'erc-after-connect 'erc-status-after-connect)
   (remove-hook 'erc-disconnected-hook 'erc-status-disconnected)
   (remove-hook 'erc-server-PRIVMSG-functions 'erc-status-PRIVMSG)))

;;; erc-status.el ends here

reply via email to

[Prev in Thread] Current Thread [Next in Thread]