emacs-devel
[Top][All Lists]
Advanced

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

RFC: status icon support


From: Tom Tromey
Subject: RFC: status icon support
Date: Sun, 30 Dec 2007 12:56:54 -0700

This patch implements status icon support for Emacs.

A status icon is an icon that sits in a part of the panel called the
"system tray".  It can be used to display notifications that are
somewhat less intrusive than a real dialog box.  A status icon can
also have a menu (unimplemented here), react to button presses, and
can display notification messages.

This patch only works when using Gtk.  It could in theory be made to
work with other toolkits -- there is a cross-desktop systray
specification, and both Windows and the Mac support something similar.
However, I don't know these other platforms, so someone else would
have to implement that.

This patch is still incomplete.  It needs a configure change and some
#ifdefs.  It also needs a ChangeLog entry and, I think, a section in
the elisp manual.

I'm looking for feedback on the general approach, the code, etc.

FWIW I've been using a version of this based on an external utility
for about a year now.  The best use I've found for it is integrating
with ERC; I have an ERC module that I'll rewrite and submit once this
code goes in.  I've also got hacks for EMMS and the calendar, and
other things are possible (mail notification comes to mind).

Tom

Index: alloc.c
===================================================================
RCS file: /sources/emacs/emacs/src/alloc.c,v
retrieving revision 1.432
diff -u -r1.432 alloc.c
--- alloc.c     16 Nov 2007 21:24:59 -0000      1.432
+++ alloc.c     30 Dec 2007 19:47:59 -0000
@@ -56,6 +56,7 @@
 #include "charset.h"
 #include "syssignal.h"
 #include "termhooks.h"         /* For struct terminal.  */
+#include "systray.h"
 #include <setjmp.h>
 
 /* GC_MALLOC_CHECK defined means perform validity checks of malloc'd
@@ -3021,6 +3022,16 @@
   return f;
 }
 
+struct status_icon *
+allocate_status_icon ()
+{
+  struct status_icon *s = ALLOCATE_PSEUDOVECTOR (struct status_icon,
+                                                param_alist, PVEC_STATUS_ICON);
+  /* Zero out the non-GC'd fields.  FIXME: This should be made unnecessary.  */
+  bzero (&(s->param_alist),
+        ((char*)(s+1)) - ((char*)&(s->param_alist)));
+  return s;
+}
 
 struct Lisp_Process *
 allocate_process ()
Index: emacs.c
===================================================================
RCS file: /sources/emacs/emacs/src/emacs.c,v
retrieving revision 1.413
diff -u -r1.413 emacs.c
--- emacs.c     2 Dec 2007 16:23:40 -0000       1.413
+++ emacs.c     30 Dec 2007 19:48:01 -0000
@@ -1579,6 +1579,7 @@
       /* Called before init_window_once for Mac OS Classic.  */
       syms_of_search ();
       syms_of_frame ();
+      syms_of_systray ();
 #endif
       syms_of_syntax ();
       syms_of_terminal ();
Index: keyboard.c
===================================================================
RCS file: /sources/emacs/emacs/src/keyboard.c,v
retrieving revision 1.935
diff -u -r1.935 keyboard.c
--- keyboard.c  10 Dec 2007 03:48:05 -0000      1.935
+++ keyboard.c  30 Dec 2007 19:48:03 -0000
@@ -500,6 +500,8 @@
 #ifdef HAVE_DBUS
 Lisp_Object Qdbus_event;
 #endif
+Lisp_Object Qstatus_icon_click_event;
+
 /* Lisp_Object Qmouse_movement; - also an event header */
 
 /* Properties of event headers.  */
@@ -4298,6 +4300,11 @@
          kbd_fetch_ptr = event + 1;
        }
 #endif
+      else if (event->kind == STATUS_ICON_CLICK_EVENT)
+       {
+         obj = make_lispy_event (event);
+         kbd_fetch_ptr = event + 1;
+       }
       else
        {
          /* If this event is on a different frame, return a switch-frame this
@@ -6174,6 +6181,9 @@
       }
 #endif /* HAVE_DBUS */
 
+    case STATUS_ICON_CLICK_EVENT:
+      return Fcons (Qstatus_icon_click_event, event->arg);
+
 #ifdef HAVE_GPM
     case GPM_CLICK_EVENT:
       {
@@ -11780,6 +11790,9 @@
   staticpro (&Qdbus_event);
 #endif
 
+  Qstatus_icon_click_event = intern ("status-icon-click-event");
+  staticpro (&Qstatus_icon_click_event);
+
   Qmenu_enable = intern ("menu-enable");
   staticpro (&Qmenu_enable);
   Qmenu_alias = intern ("menu-alias");
@@ -12516,6 +12529,9 @@
   initial_define_lispy_key (Vspecial_event_map, "dbus-event",
                            "dbus-handle-event");
 #endif
+
+  initial_define_lispy_key (Vspecial_event_map, "status-icon-click-event",
+                           "status-icon-handle-click-event");
 }
 
 /* Mark the pointers in the kboard objects.
Index: lisp.h
===================================================================
RCS file: /sources/emacs/emacs/src/lisp.h,v
retrieving revision 1.603
diff -u -r1.603 lisp.h
--- lisp.h      22 Nov 2007 01:01:26 -0000      1.603
+++ lisp.h      30 Dec 2007 19:48:03 -0000
@@ -349,7 +349,8 @@
   PVEC_HASH_TABLE = 0x40000,
   PVEC_TERMINAL = 0x80000,
   PVEC_OTHER = 0x100000,
-  PVEC_TYPE_MASK = 0x1ffe00
+  PVEC_STATUS_ICON = 0x200000,
+  PVEC_TYPE_MASK = 0x2ffe00
 
 #if 0 /* This is used to make the value of PSEUDOVECTOR_FLAG available to
         GDB.  It doesn't work on OS Alpha.  Moved to a variable in
@@ -1552,6 +1553,8 @@
 #define GC_BOOL_VECTOR_P(x) GC_PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
 #define FRAMEP(x) PSEUDOVECTORP (x, PVEC_FRAME)
 #define GC_FRAMEP(x) GC_PSEUDOVECTORP (x, PVEC_FRAME)
+#define STATUS_ICONP(x) PSEUDOVECTORP (x, PVEC_STATUS_ICON)
+#define GC_STATUS_ICONP(x) GC_PSEUDOVECTORP (x, PVEC_STATUS_ICON)
 
 #define SUB_CHAR_TABLE_P(x) (CHAR_TABLE_P (x) && NILP (XCHAR_TABLE (x)->top))
 
@@ -2616,6 +2620,7 @@
 extern struct Lisp_Hash_Table *allocate_hash_table P_ ((void));
 extern struct window *allocate_window P_ ((void));
 extern struct frame *allocate_frame P_ ((void));
+extern struct status_icon *allocate_status_icon P_ ((void));
 extern struct Lisp_Process *allocate_process P_ ((void));
 extern struct terminal *allocate_terminal P_ ((void));
 extern int gc_in_progress;
@@ -3248,6 +3253,9 @@
 extern void syms_of_sound P_ ((void));
 extern void init_sound P_ ((void));
 
+/* Defined in systray.c */
+extern void syms_of_systray P_ ((void));
+
 /* Defined in category.c */
 extern void init_category_once P_ ((void));
 extern void syms_of_category P_ ((void));
Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.243
diff -u -r1.243 print.c
--- print.c     22 Nov 2007 16:16:02 -0000      1.243
+++ print.c     30 Dec 2007 19:48:03 -0000
@@ -2031,6 +2031,8 @@
          strout (buf, -1, -1, printcharfun, 0);
          PRINTCHAR ('>');
        }
+      else if (STATUS_ICONP (obj))
+       strout ("#<status-icon>", -1, -1, printcharfun, 0);
       else
        {
          EMACS_INT size = XVECTOR (obj)->size;
Index: systray.c
===================================================================
RCS file: systray.c
diff -N systray.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ systray.c   30 Dec 2007 19:48:03 -0000
@@ -0,0 +1,446 @@
+/* Elisp bindings system tray icons
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+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
+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 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.  */
+
+#include "config.h"
+
+#include "lisp.h"
+#include "systray.h"
+#include "frame.h"
+#include "charset.h"
+#include "coding.h"
+#include "blockinput.h"
+#include "termhooks.h"
+
+#include <gtk/gtk.h>
+#include <libnotify/notify.h>
+
+/* FIXME: should be in a header.  */
+extern Lisp_Object Qhelp_echo;
+extern Lisp_Object Qstatus_icon_click_event;
+
+Lisp_Object Vstatus_icon_list;
+
+Lisp_Object Qblinking;
+Lisp_Object Qstatus_icon_live_p;
+Lisp_Object Qclick_callback;
+Lisp_Object QCbody, QCtimeout, QCurgency, QCicon;
+Lisp_Object Qlow, Qcritical, Qwarning, Qquestion, Qerror;
+
+#define GET_ICON(s) ((GtkStatusIcon *) ((s)->icon))
+
+/* Callback which is called when the user clicks on a status icon.  */
+static void
+activate_icon (GtkWidget *widget, gpointer data)
+{
+  Lisp_Object icon = (Lisp_Object) data;
+  struct input_event event;
+  EVENT_INIT (event);
+  event.kind = STATUS_ICON_CLICK_EVENT;
+  event.frame_or_window = Qnil;
+  event.arg = icon;
+  kbd_buffer_store_event (&event);
+}
+
+/* Apply property KEY with value VALUE to icon SICON.  */
+static void
+apply_one_icon_property (sicon, key, value)
+     struct status_icon *sicon;
+     Lisp_Object key, value;
+{
+  if (EQ (key, Qicon_name))
+    {
+      struct gcpro gcpro1;
+      Lisp_Object filename = Qnil;
+      GCPRO1 (filename);
+      if (NILP (value))
+       {
+         /* Default to the GNU.  */
+         filename = build_string ("emacs_48.png");
+       }
+      else
+       {
+         CHECK_STRING (value);
+         filename = value;
+       }
+      /* Not clear if x_find_image_file returns a string with the
+        correct encoding for Gtk.  However, it is already used this
+        way in gtkutil.c.  */
+      filename = x_find_image_file (filename);
+      if (NILP (filename))
+       {
+         /* No good choice, so choose a semi-appropriate stock
+            icon.  */
+         gtk_status_icon_set_from_stock (GET_ICON (sicon),
+                                         GTK_STOCK_DIALOG_QUESTION);
+       }
+      else
+       gtk_status_icon_set_from_file (GET_ICON (sicon),
+                                      (char *) SDATA (filename));
+      UNGCPRO;
+    }
+  else if (EQ (key, Qblinking))
+    gtk_status_icon_set_blinking (GET_ICON (sicon), ! NILP (value));
+  else if (EQ (key, Qvisible))
+    gtk_status_icon_set_visible (GET_ICON (sicon), ! NILP (value));
+  else if (EQ (key, Qhelp_echo))
+    {
+      struct gcpro gcpro1;
+      Lisp_Object tooltip = Qnil;
+      GCPRO1 (tooltip);
+      if (NILP (value))
+       gtk_status_icon_set_tooltip (GET_ICON (sicon), NULL);
+      else
+       {
+         /* FIXME: should accept a sexp to eval here.  */
+         CHECK_STRING (value);
+         tooltip = ENCODE_UTF_8 (value);
+         gtk_status_icon_set_tooltip (GET_ICON (sicon),
+                                      (char *) SDATA (tooltip));
+       }
+      UNGCPRO;
+    }
+  else
+    {
+      /* Ignore things we don't understand.  */
+    }
+}
+
+/* Apply the ALIST of properties to status icon ICON.  */
+static void
+apply_status_icon_alist (icon, alist)
+     Lisp_Object icon, alist;
+{
+  Lisp_Object tail;
+  struct status_icon *sicon;
+
+  CHECK_LIVE_STATUS_ICON (icon);
+  sicon = XSTATUS_ICON (icon);
+
+  for (tail = alist; CONSP (tail); tail = XCDR (tail))
+    {
+      Lisp_Object key, value;
+      Lisp_Object elt = XCAR (tail);
+      if (! CONSP (elt))
+       continue;
+      key = XCAR (elt);
+      value = XCDR (elt);
+
+      apply_one_icon_property (sicon, key, value);
+
+      /* Update frame parameters.  */
+      elt = Fassq (key, sicon->param_alist);
+      if (NILP (elt))
+       sicon->param_alist = Fcons (Fcons (key, value), sicon->param_alist);
+      else
+       Fsetcdr (elt, value);
+    }
+}
+
+DEFUN ("make-status-icon", Fmake_status_icon, Smake_status_icon,
+       0, 1, 0,
+       doc: /* Return a newly created status icon.
+Optional argument ALIST is an alist of parameters for the new frame.
+See `modify-status-icon-parameters' for a list of recognized parameters.*/)
+     (alist)
+     Lisp_Object alist;
+{
+  struct status_icon *sicon;
+  Lisp_Object icon, deflist;
+  struct gcpro gcpro1;
+
+  BLOCK_INPUT;
+
+  sicon = allocate_status_icon ();
+  XSETSTATUS_ICON (icon, sicon);
+  sicon->param_alist = Qnil;
+  sicon->icon = gtk_status_icon_new ();
+
+  g_signal_connect (sicon->icon, "activate", G_CALLBACK (activate_icon),
+                   (gpointer) icon);
+
+  Vstatus_icon_list = Fcons (icon, Vstatus_icon_list);
+
+  GCPRO1 (deflist);
+
+  /* Make some defaults.  */
+  deflist = Fcons (Fcons (Qclick_callback, Qnil),
+                  Fcons (Fcons (Qicon_name, Qnil),
+                         Fcons (Fcons (Qblinking, Qnil),
+                                Fcons (Fcons (Qvisible, Qt),
+                                       Fcons (Fcons (Qhelp_echo, Qnil),
+                                              alist)))));
+  apply_status_icon_alist (icon, deflist);
+
+  UNBLOCK_INPUT;
+
+  RETURN_UNGCPRO (icon);
+}
+
+DEFUN ("modify-status-icon-parameters", Fmodify_status_icon_parameters,
+       Smodify_status_icon_parameters,
+       2, 2, 0,
+       doc: /* Modify the parameters of status icon ICON according to ALIST.
+Each element of alist has the form (PARM . VALUE), where PARM is a symbol.
+Undefined PARMs are ignored, but stored in the frame's parameter list
+so that `status-icon-parameters' will return them.
+
+Currently defined parameters and their values are:
+
+  icon-name   The file name of an icon to display.
+  blinking    If non-nil, the status icon will blink.
+  visible     If nil, status icon is invisible.
+  help-echo   A string which will be displayed as a tooltip for the
+              status icon.*/)
+     (icon, alist)
+     Lisp_Object icon, alist;
+{
+  BLOCK_INPUT;
+  apply_status_icon_alist (icon, alist);
+  UNBLOCK_INPUT;
+  return Qnil;
+}
+
+DEFUN ("status-icon-parameters", Fstatus_icon_parameters,
+       Sstatus_icon_parameters,
+       1, 1, 0,
+       doc: /* Return the parameters-alist of the status icon ICON.
+It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.*/)
+     (icon)
+     Lisp_Object icon;
+{
+  struct status_icon *sicon;
+  CHECK_LIVE_STATUS_ICON (icon);
+  sicon = XSTATUS_ICON (icon);
+  return Fcopy_alist (sicon->param_alist);
+}
+
+DEFUN ("status-icon-list", Fstatus_icon_list, Sstatus_icon_list,
+       0, 0, 0,
+       doc: /* Return a list of all status icons.  */)
+     ()
+{
+  return Fcopy_sequence (Vstatus_icon_list);
+}
+
+DEFUN ("delete-status-icon", Fdelete_status_icon, Sdelete_status_icon,
+       1, 1, 0,
+       doc: /* Delete the status icon ICON.  */)
+     (icon)
+     Lisp_Object icon;
+{
+  struct status_icon *sicon;
+  CHECK_LIVE_STATUS_ICON (icon);
+  sicon = XSTATUS_ICON (icon);
+  BLOCK_INPUT;
+  g_object_unref (sicon->icon);
+  UNBLOCK_INPUT;
+  sicon->icon = NULL;
+  Vstatus_icon_list = Fdelq (icon, Vstatus_icon_list);
+  return Qnil;
+}
+
+DEFUN ("show-status-icon-message", Fshow_status_icon_message,
+       Sshow_status_icon_message,
+       2, MANY, 0,
+       doc: /* Post a notification message attached to the icon ICON.
+ICON is a status icon created by `make-status-icon'.
+SUMMARY is the message to display, a string.
+
+The remaining arguments, if any, are a property list specifying
+additional parameters of the notification:
+
+  :body TEXT       Set the body text of the notification.
+  :timeout VALUE   Set the timeout value.
+                   nil means use the default.
+                  t means never time out.
+                  An integer specifies the timeout in milliseconds.
+  :urgency VALUE   Set the urgency level.  VALUE is a symbol, one of
+                   'low', 'normal', 'critical'.  The default is 'normal'.
+  :icon VALUE      Set the notification icon.  VALUE is a symbol, currently
+                   one of 'warning', 'info', 'question', 'error'.  The
+                  default is 'info'.  */)
+     (nargs, args)
+     int nargs;
+     Lisp_Object *args;
+{
+  struct status_icon *sicon;
+  struct gcpro gcpro1;
+  Lisp_Object gc_temp = Qnil;
+  GError *gerr = NULL;
+  NotifyNotification *notification;
+
+  int i;
+  Lisp_Object icon = args[0];
+  Lisp_Object summary = args[1];
+
+  if ((nargs - 2) % 2 != 0)
+    error ("Invalid number of arguments");
+
+  CHECK_LIVE_STATUS_ICON (icon);
+  CHECK_STRING (summary);
+
+  if (! notify_is_initted () && ! notify_init ("Emacs"))
+    error ("Couldn't connect to notification server");
+
+  sicon = XSTATUS_ICON (icon);
+
+  GCPRO1 (gc_temp);
+
+  gc_temp = ENCODE_UTF_8 (summary);
+
+  BLOCK_INPUT;
+
+  /* FIXME: allow actions, setting the icon, callback when the
+     notification is closed, maybe hints.  */
+  notification
+    = notify_notification_new_with_status_icon (SDATA (gc_temp), NULL,
+                                               GTK_STOCK_DIALOG_INFO,
+                                               GET_ICON (XSTATUS_ICON (icon)));
+
+  for (i = 2; i < nargs; i += 2)
+    {
+      Lisp_Object key = args[i];
+      Lisp_Object value = args[i + 1];
+      if (EQ (key, QCbody))
+       {
+         /* Ignore things we don't understand.  */
+         if (STRINGP (value))
+           {
+             gc_temp = ENCODE_UTF_8 (value);
+             g_object_set (G_OBJECT (notification), "body", SDATA (gc_temp),
+                           NULL);
+           }
+       }
+      else if (EQ (key, QCtimeout))
+       {
+         gint timeout = NOTIFY_EXPIRES_DEFAULT;
+         if (EQ (value, Qt))
+           timeout = NOTIFY_EXPIRES_NEVER;
+         else if (INTEGERP (value))
+           {
+             timeout = XINT (value);
+             if (timeout <= 0)
+               timeout = NOTIFY_EXPIRES_DEFAULT;
+           }
+         notify_notification_set_timeout (notification, timeout);
+       }
+      else if (EQ (key, QCurgency))
+       {
+         NotifyUrgency urgency = NOTIFY_URGENCY_NORMAL;
+         if (EQ (value, Qlow))
+           urgency = NOTIFY_URGENCY_LOW;
+         else if (EQ (value, Qcritical))
+           urgency = NOTIFY_URGENCY_CRITICAL;
+         notify_notification_set_urgency (notification, urgency);
+       }
+      else if (EQ (key, QCicon))
+       {
+         char *icon_name = GTK_STOCK_DIALOG_INFO;
+         if (EQ (value, Qwarning))
+           icon_name = GTK_STOCK_DIALOG_WARNING;
+         else if (EQ (value, Qquestion))
+           icon_name = GTK_STOCK_DIALOG_QUESTION;
+         else if (EQ (value, Qerror))
+           icon_name = GTK_STOCK_DIALOG_ERROR;
+         g_object_set (G_OBJECT (notification), "icon-name", icon_name, NULL);
+       }
+    }
+
+  notify_notification_show (notification, &gerr);
+  /* FIXME: error handling?  */
+  g_object_unref (notification);
+
+  UNBLOCK_INPUT;
+
+  RETURN_UNGCPRO (Qnil);
+}
+
+DEFUN ("status-icon-handle-click-event", Fstatus_icon_handle_click_event,
+       Sstatus_icon_handle_click_event,
+       1, 1, "e",
+       doc: /* Internal handler for status icon click events.
+A status icon click event is generated in response to the user clicking
+on a status icon.  This handler calls the specified callback function,
+if any.*/)
+     (event)
+     Lisp_Object event;
+{
+  struct status_icon *sicon;
+  Lisp_Object elt;
+
+  /* Just ignore garbage.  */
+  if (! CONSP (event) || ! EQ (XCAR (event), Qstatus_icon_click_event)
+      || ! STATUS_ICONP (XCDR (event))
+      || ! STATUS_ICON_LIVE_P (XSTATUS_ICON (XCDR (event))))
+    return Qnil;
+
+  sicon = XSTATUS_ICON (XCDR (event));
+  elt = Fassq (Qclick_callback, sicon->param_alist);
+  if (CONSP (elt) && FUNCTIONP (XCDR (elt)))
+    {
+      struct gcpro gcpro1;
+      Lisp_Object fun = XCDR (elt);
+      GCPRO1 (fun);
+      Ffuncall (1, &fun);
+      UNGCPRO;
+    }
+
+  return Qnil;
+}
+
+void
+syms_of_systray ()
+{
+  Qstatus_icon_live_p = intern ("status-icon-live-p");
+  staticpro (&Qstatus_icon_live_p);
+  Qblinking = intern ("blinking");
+  staticpro (&Qblinking);  
+  Qclick_callback = intern ("click-callback");
+  staticpro (&Qclick_callback);
+  QCbody = intern (":body");
+  staticpro (&QCbody);
+  QCtimeout = intern (":timeout");
+  staticpro (&QCtimeout);
+  QCurgency = intern (":urgency");
+  staticpro (&QCurgency);
+  QCicon = intern (":icon");
+  staticpro (&QCicon);
+  Qlow = intern ("low");
+  staticpro (&Qlow);
+  Qcritical = intern ("critical");
+  staticpro (&Qcritical);
+  Qwarning = intern ("warning");
+  staticpro (&Qwarning);
+  Qquestion = intern ("question");
+  staticpro (&Qquestion);
+  Qerror = intern ("error");
+  staticpro (&Qerror);
+
+  staticpro (&Vstatus_icon_list);
+  Vstatus_icon_list = Qnil;
+
+  defsubr (&Smake_status_icon);
+  defsubr (&Smodify_status_icon_parameters);
+  defsubr (&Sdelete_status_icon);
+  defsubr (&Sstatus_icon_parameters);
+  defsubr (&Sstatus_icon_list);
+  defsubr (&Sshow_status_icon_message);
+  defsubr (&Sstatus_icon_handle_click_event);
+}
Index: systray.h
===================================================================
RCS file: systray.h
diff -N systray.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ systray.h   30 Dec 2007 19:48:03 -0000
@@ -0,0 +1,52 @@
+/* Define systray object for GNU Emacs.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+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
+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 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.  */
+
+#ifndef EMACS_SYSTRAY_H
+#define EMACS_SYSTRAY_H
+
+extern Lisp_Object Qstatus_icon_live_p;
+
+struct status_icon
+{
+  EMACS_UINT size;
+  struct Lisp_Vector *next;
+
+  /* Parameter alist of this status icon.  */
+  Lisp_Object param_alist;
+
+  /* Beyond here, there should be no more Lisp_Object components.  */
+
+  /* The icon widget, or NULL if it has been destroyed.  Really a
+     'GtkStatusIcon *'.  */
+  void *icon;
+};
+
+#define XSTATUS_ICON(p) \
+  (eassert (GC_STATUS_ICONP (p)), (struct status_icon *) XPNTR (p))
+
+#define XSETSTATUS_ICON(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_STATUS_ICON))
+
+#define STATUS_ICON_LIVE_P(s) (((s)->icon) != 0)
+
+#define CHECK_LIVE_STATUS_ICON(s)                                      \
+  CHECK_TYPE (STATUS_ICONP (s) && STATUS_ICON_LIVE_P (XSTATUS_ICON (s)), \
+             Qstatus_icon_live_p, s)
+
+#endif /* EMACS_SYSTRAY_H */
Index: termhooks.h
===================================================================
RCS file: /sources/emacs/emacs/src/termhooks.h,v
retrieving revision 1.90
diff -u -r1.90 termhooks.h
--- termhooks.h 2 Dec 2007 16:23:40 -0000       1.90
+++ termhooks.h 30 Dec 2007 19:48:03 -0000
@@ -201,6 +201,8 @@
   , DBUS_EVENT
 #endif
 
+  , STATUS_ICON_CLICK_EVENT
+
 #ifdef WINDOWSNT
   /* Generated when an APPCOMMAND event is received, in response to
      Multimedia or Internet buttons on some keyboards.
Index: Makefile.in
===================================================================
RCS file: /sources/emacs/emacs/src/Makefile.in,v
retrieving revision 1.361
diff -u -r1.361 Makefile.in
--- Makefile.in 2 Dec 2007 16:23:40 -0000       1.361
+++ Makefile.in 30 Dec 2007 19:47:59 -0000
@@ -593,7 +593,7 @@
 /* lastfile must follow all files
    whose initialized data areas should be dumped as pure by dump-emacs.  */
 obj=    dispnew.o frame.o scroll.o xdisp.o $(XMENU_OBJ) window.o \
-       charset.o coding.o category.o ccl.o \
+       charset.o coding.o category.o ccl.o systray.o \
        cm.o term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ) $(DBUS_OBJ) \
        emacs.o keyboard.o macros.o keymap.o sysdep.o \
        buffer.o filelock.o insdel.o marker.o \
@@ -944,7 +944,7 @@
    Note that SunOS needs -lm to come before -lc; otherwise, you get
    duplicated symbols.  If the standard libraries were compiled
    with GCC, we might need gnulib again after them.  */
-LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \
+LIBES = $(LOADLIBES) $(LIBS) -lnotify $(LIBX) $(LIBSOUND) $(RSVG_LIBS) 
$(DBUS_LIBS) \
    LIBGPM LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \
    LIBS_DEBUG $(GETLOADAVG_LIBS) $(GNULIB_VAR) LIB_MATH LIB_STANDARD \
    $(GNULIB_VAR)
@@ -1190,6 +1190,7 @@
 sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \
    process.h dispextern.h termhooks.h termchar.h termopts.h \
    frame.h atimer.h window.h msdos.h dosfns.h keyboard.h cm.h $(config_h)
+systray.o: systray.c $(config_h) lisp.h frame.h
 term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \
    disptab.h dispextern.h keyboard.h charset.h coding.h ccl.h msdos.h \
    window.h keymap.h blockinput.h atimer.h systime.h




reply via email to

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