summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rwxr-xr-xexamples/python/NMTester.py44
-rwxr-xr-xexamples/python/NetworkManager.py150
-rw-r--r--examples/python/README21
-rw-r--r--examples/python/systray/Makefile34
-rw-r--r--examples/python/systray/eggtrayicon.c473
-rw-r--r--examples/python/systray/eggtrayicon.h77
-rwxr-xr-xexamples/python/systray/network_tray.py120
-rw-r--r--examples/python/systray/trayicon.override29
-rw-r--r--examples/python/systray/trayiconmodule.c25
10 files changed, 987 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index b650958fac..7ad46a96d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2004-08-27 Bryan Clark <bclark@redhat.com>
+
+ * examples/python/systray/trayiconmodule.c:
+ * examples/python/systray/trayicon.override:
+ * examples/python/systray/network_tray.py:
+ * examples/python/systray/eggtrayicon.h:
+ * examples/python/systray/eggtrayicon.c:
+ * examples/python/systray/Makefile:
+ * examples/python/README:
+ * examples/python/NetworkManager.py:
+ * examples/python/NMTester.py:
+
+ Initial commit of these python example files
+
Fri Aug 28 2004 Dan Williams <dcbw@redhat.com>
* panel-applet/NMWirelessApplet.c
diff --git a/examples/python/NMTester.py b/examples/python/NMTester.py
new file mode 100755
index 0000000000..778a418dc2
--- /dev/null
+++ b/examples/python/NMTester.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+from NetworkManager import NetworkManager
+import gtk
+
+class NMTester(NetworkManager):
+
+ def __init__(self):
+ NetworkManager.__init__(self)
+
+ for signal in self.NM_SIGNALS:
+ self.nm_object.connect_to_signal(signal,
+ self.nm_signal_handler)
+ for signal in self.NMI_SIGNALS:
+ self.nmi_object.connect_to_signal(signal,
+ self.nmi_signal_handler)
+ self.print_device_list()
+
+ def print_device_list(self):
+ d_list = self.get_devices()
+ print
+ print "========================================================="
+ print
+ for d in d_list:
+ for k,v in d.iteritems():
+ print "%s: %s" % (k,v)
+ print
+ print "========================================================="
+ print
+
+ def nm_signal_handler(self, interface, signal_name,
+ service, path, message):
+ self._print_device_list()
+
+ def nmi_signal_handler(self, interface, signal_name,
+ service, path, message):
+ print ("Received signal '%s.%s' from object '%s%s' with message %s"
+ % (interface, signal_name, service, path, message))
+
+if __name__ == "__main__":
+ nmt = NMTester()
+ gtk.main()
+
+
diff --git a/examples/python/NetworkManager.py b/examples/python/NetworkManager.py
new file mode 100755
index 0000000000..0628abb7e2
--- /dev/null
+++ b/examples/python/NetworkManager.py
@@ -0,0 +1,150 @@
+#!/usr/bin/python
+
+import dbus
+from dbus_bindings import DBusException
+
+NM_SERVICE="org.freedesktop.NetworkManager"
+NM_PATH="/org/freedesktop/NetworkManager"
+NM_INTERFACE=NM_SERVICE
+
+# i can append device names like eth0 to this path to get more info
+NM_PATH_DEVICES="/org/freedesktop/NetworkManager/Devices"
+NM_INTERFACE_DEVICES="org.freedesktop.NetworkManager.Devices"
+
+NMI_SERVICE="org.freedesktop.NetworkManagerInfo"
+NMI_PATH="/org/freedesktop/NetworkManagerInfo"
+NMI_INTERFACE=NMI_SERVICE
+
+HAL_SERVICE="org.freedesktop.Hal"
+HAL_PATH="/org/freedesktop/Hal/Manager"
+HAL_INTERFACE="org.freedesktop.Hal.Manager"
+HAL_INTERFACE_DEVICE="org.freedesktop.Hal.Device"
+
+class NetworkManager:
+ WIRED_DEVICE = 1
+ WIRELESS_DEVICE = 2
+
+ NM_SIGNALS = [ "DeviceNoLongerActive",
+ "DeviceNowActive",
+ "DeviceActivating",
+ "DevicesChanging",
+ "DeviceIP4AddressChange",
+ "WirelessNetworkDisappeared",
+ "WirelessNetworkAppeared"
+ ]
+
+ NMI_SIGNALS = [ "TrustedNetworkUpdate",
+ "PreferredNetworkUpdate"
+ ]
+
+ def __init__(self):
+ self.__init_dbus__()
+
+ # dictionary of devices
+ self.__devices = {}
+
+ def __init_dbus__(self):
+ self._bus = dbus.SystemBus()
+ self._nm_service = self._bus.get_service(NM_SERVICE)
+ self.nm_object = self._nm_service.get_object(NM_PATH,
+ NM_INTERFACE)
+
+ self._nmi_service = self._bus.get_service(NMI_SERVICE)
+ self.nmi_object = self._nmi_service.get_object(NMI_PATH,
+ NMI_INTERFACE)
+
+ self._hal_service = self._bus.get_service(HAL_SERVICE)
+ self._hal_manager = self._hal_service.get_object(HAL_PATH,
+ HAL_INTERFACE)
+
+
+ """
+ returns dictionary of the active device information
+ if device does not exist returns get_device failure method
+ """
+ def get_active_device(self):
+ active_device = self.nm_object.getActiveDevice()
+ return self.get_device(active_device)
+
+ """
+ pass device string /org/freedesktop/NetworkManager/Device/eth0
+ returns dictionary of device information
+ if device does not exist returns None
+ """
+ def get_device(self, device):
+ try:
+ nm_device_object = self._nm_service.get_object(device,
+ NM_INTERFACE_DEVICES)
+ d = {}
+ d["nm.name"] = nm_device_object.getName(device)
+ d["nm.type"] = nm_device_object.getType(device)
+ d["nm.udi"] = nm_device_object.getHalUdi(device)
+ d["nm.ip4"] = nm_device_object.getIP4Address(device)
+ d["nm.quality"] = nm_device_object.getMaxQuality(device)
+
+ try:
+ d["nm.active_network"] = nm_device_object.getActiveNetwork(device)
+ except DBusException, e:
+ pass
+
+ try:
+ d["nm.networks"] = nm_device_object.getNetworks(device)
+ except DBusException, e:
+ pass
+
+ active_device = self.nm_object.getActiveDevice()
+ active_device_status = self.nm_object.status()
+
+ if device == active_device:
+ d["nm.status"] = active_device_status
+ else:
+ d["nm.status"] = "not connected"
+
+ if device in self.__devices:
+ for k,v in d.iteritems():
+ self.__devices[device][k] = [v]
+ return d
+ else:
+ hal = self._get_hal_info(d["nm.udi"])
+ for k,v in hal.iteritems():
+ d[k] = v
+ self.__devices[device] = d
+ return d
+ except:
+ return None
+
+ """
+ Returns list of dictionary objects of all active devices
+ Returns empty list if no active devices
+ """
+ def get_devices(self):
+
+ active_devices = self.nm_object.getDevices()
+ devices = []
+
+ for device in active_devices:
+ devices.append(self.get_device(device))
+
+ return devices
+
+ """
+ Returns list of dictionary objects of all devices active or not
+ Returns empty list if no active devices
+ """
+ def get_all_devices(self):
+ return self.__devices.values()
+
+ def _get_hal_info(self, udi):
+ hal_devices = self._hal_manager.FindDeviceStringMatch("info.udi",
+ udi)
+ for hal_device in hal_devices:
+ device_dbus_obj = self._hal_service.get_object(hal_device,
+ HAL_INTERFACE_DEVICE)
+ properties = device_dbus_obj.GetAllProperties()
+ return properties
+
+if __name__ == "__main__":
+ nm = NetworkManager()
+
+
+
diff --git a/examples/python/README b/examples/python/README
new file mode 100644
index 0000000000..7ab5478f96
--- /dev/null
+++ b/examples/python/README
@@ -0,0 +1,21 @@
+Python Examples
+
+You'll need equivalent versions of these packages in order to run most of these examples.
+
+hal-0.2.97.cvs20040823
+dbus-0.22-4
+pygtk2-2.3.96-2
+python-2.3.4-8
+gnome-python2-2.0.2-1
+
+
+NMTester.py
+===============================================================================
+
+This is a simple command line program that sub classes the NetworkManager class. The tester prints out the network devices objects that are returned from the NetworkManager class. The code hangs in the gtk.main() loop once run and will listen for any events from the NetworkManager
+
+
+NetworkManager.py
+===============================================================================
+This object hooks into the NetworkManger and HAL service through D-BUS. The get_device_list code will return a python list [] of dictionary objects representing the devices that the NetworkManger services is aware of.
+
diff --git a/examples/python/systray/Makefile b/examples/python/systray/Makefile
new file mode 100644
index 0000000000..352a65febf
--- /dev/null
+++ b/examples/python/systray/Makefile
@@ -0,0 +1,34 @@
+# Set the C flags to include the GTK+ and Python libraries
+CFLAGS = `pkg-config --cflags gtk+-2.0 pygtk-2.0` -I/usr/include/python2.3/ -I.
+LDFLAGS = `pkg-config --libs gtk+-2.0 pygtk-2.0`
+
+# Build the shared object
+trayicon.so: trayicon.o eggtrayicon.o trayiconmodule.o
+ $(CC) $(LDFLAGS) -shared $^ -o $@
+
+
+# The path to the GTK+ python types
+DEFS=`pkg-config --variable=defsdir pygtk-2.0`
+
+# Generate the C wrapper from the defs and our override file
+trayicon.c: trayicon.defs trayicon.override
+ pygtk-codegen-2.0 --prefix trayicon \
+ --register $(DEFS)/gdk-types.defs \
+ --register $(DEFS)/gtk-types.defs \
+ --override trayicon.override \
+ trayicon.defs > $@
+
+trayicon.defs: eggtrayicon.h config.h
+ python \
+ /usr/share/pygtk/2.0/codegen/h2def.py \
+ eggtrayicon.h > trayicon.defs
+
+config.h:
+ touch config.h
+ ln -s ../NetworkManager.py .
+
+# A rule to clean the generated files
+clean:
+ rm -f trayicon.so *.o trayicon.c trayicon.defs *~ config.h NetworkManager.py
+
+.PHONY: clean
diff --git a/examples/python/systray/eggtrayicon.c b/examples/python/systray/eggtrayicon.c
new file mode 100644
index 0000000000..ddc47d4a33
--- /dev/null
+++ b/examples/python/systray/eggtrayicon.c
@@ -0,0 +1,473 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* eggtrayicon.c
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <libintl.h>
+
+#include "eggtrayicon.h"
+
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+#define _(x) x
+#define N_(x) x
+
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+#define SYSTEM_TRAY_ORIENTATION_HORZ 0
+#define SYSTEM_TRAY_ORIENTATION_VERT 1
+
+enum {
+ PROP_0,
+ PROP_ORIENTATION
+};
+
+static GtkPlugClass *parent_class = NULL;
+
+static void egg_tray_icon_init (EggTrayIcon *icon);
+static void egg_tray_icon_class_init (EggTrayIconClass *klass);
+
+static void egg_tray_icon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void egg_tray_icon_realize (GtkWidget *widget);
+static void egg_tray_icon_unrealize (GtkWidget *widget);
+
+static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
+
+GType
+egg_tray_icon_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EggTrayIconClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_tray_icon_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EggTrayIcon),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_tray_icon_init
+ };
+
+ our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
+ }
+
+ return our_type;
+}
+
+static void
+egg_tray_icon_init (EggTrayIcon *icon)
+{
+ icon->stamp = 1;
+ icon->orientation = GTK_ORIENTATION_HORIZONTAL;
+
+ gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
+}
+
+static void
+egg_tray_icon_class_init (EggTrayIconClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *)klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->get_property = egg_tray_icon_get_property;
+
+ widget_class->realize = egg_tray_icon_realize;
+ widget_class->unrealize = egg_tray_icon_unrealize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation",
+ _("Orientation"),
+ _("The orientation of the tray."),
+ GTK_TYPE_ORIENTATION,
+ GTK_ORIENTATION_HORIZONTAL,
+ G_PARAM_READABLE));
+}
+
+static void
+egg_tray_icon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, icon->orientation);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
+{
+ Display *xdisplay;
+ Atom type;
+ int format;
+ union {
+ gulong *prop;
+ guchar *prop_ch;
+ } prop = { NULL };
+ gulong nitems;
+ gulong bytes_after;
+ int error, result;
+
+ g_assert (icon->manager_window != None);
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ gdk_error_trap_push ();
+ type = None;
+ result = XGetWindowProperty (xdisplay,
+ icon->manager_window,
+ icon->orientation_atom,
+ 0, G_MAXLONG, FALSE,
+ XA_CARDINAL,
+ &type, &format, &nitems,
+ &bytes_after, &(prop.prop_ch));
+ error = gdk_error_trap_pop ();
+
+ if (error || result != Success)
+ return;
+
+ if (type == XA_CARDINAL)
+ {
+ GtkOrientation orientation;
+
+ orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ?
+ GTK_ORIENTATION_HORIZONTAL :
+ GTK_ORIENTATION_VERTICAL;
+
+ if (icon->orientation != orientation)
+ {
+ icon->orientation = orientation;
+
+ g_object_notify (G_OBJECT (icon), "orientation");
+ }
+ }
+
+ if (prop.prop)
+ XFree (prop.prop);
+}
+
+static GdkFilterReturn
+egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
+{
+ EggTrayIcon *icon = user_data;
+ XEvent *xev = (XEvent *)xevent;
+
+ if (xev->xany.type == ClientMessage &&
+ xev->xclient.message_type == icon->manager_atom &&
+ xev->xclient.data.l[1] == icon->selection_atom)
+ {
+ egg_tray_icon_update_manager_window (icon);
+ }
+ else if (xev->xany.window == icon->manager_window)
+ {
+ if (xev->xany.type == PropertyNotify &&
+ xev->xproperty.atom == icon->orientation_atom)
+ {
+ egg_tray_icon_get_orientation_property (icon);
+ }
+ if (xev->xany.type == DestroyNotify)
+ {
+ egg_tray_icon_update_manager_window (icon);
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+egg_tray_icon_unrealize (GtkWidget *widget)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+ GdkWindow *root_window;
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
+ icon->manager_window);
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+ root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
+
+ gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+egg_tray_icon_send_manager_message (EggTrayIcon *icon,
+ long message,
+ Window window,
+ long data1,
+ long data2,
+ long data3)
+{
+ XClientMessageEvent ev;
+ Display *display;
+
+ ev.type = ClientMessage;
+ ev.window = window;
+ ev.message_type = icon->system_tray_opcode_atom;
+ ev.format = 32;
+ ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window);
+ ev.data.l[1] = message;
+ ev.data.l[2] = data1;
+ ev.data.l[3] = data2;
+ ev.data.l[4] = data3;
+
+ display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ gdk_error_trap_push ();
+ XSendEvent (display,
+ icon->manager_window, False, NoEventMask, (XEvent *)&ev);
+ XSync (display, False);
+ gdk_error_trap_pop ();
+}
+
+static void
+egg_tray_icon_send_dock_request (EggTrayIcon *icon)
+{
+ egg_tray_icon_send_manager_message (icon,
+ SYSTEM_TRAY_REQUEST_DOCK,
+ icon->manager_window,
+ gtk_plug_get_id (GTK_PLUG (icon)),
+ 0, 0);
+}
+
+static void
+egg_tray_icon_update_manager_window (EggTrayIcon *icon)
+{
+ Display *xdisplay;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+ XGrabServer (xdisplay);
+
+ icon->manager_window = XGetSelectionOwner (xdisplay,
+ icon->selection_atom);
+
+ if (icon->manager_window != None)
+ XSelectInput (xdisplay,
+ icon->manager_window, StructureNotifyMask|PropertyChangeMask);
+
+ XUngrabServer (xdisplay);
+ XFlush (xdisplay);
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+
+ gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+
+ /* Send a request that we'd like to dock */
+ egg_tray_icon_send_dock_request (icon);
+
+ egg_tray_icon_get_orientation_property (icon);
+ }
+}
+
+static void
+egg_tray_icon_realize (GtkWidget *widget)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+ GdkScreen *screen;
+ GdkDisplay *display;
+ Display *xdisplay;
+ char buffer[256];
+ GdkWindow *root_window;
+
+ if (GTK_WIDGET_CLASS (parent_class)->realize)
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+ screen = gtk_widget_get_screen (widget);
+ display = gdk_screen_get_display (screen);
+ xdisplay = gdk_x11_display_get_xdisplay (display);
+
+ /* Now see if there's a manager window around */
+ g_snprintf (buffer, sizeof (buffer),
+ "_NET_SYSTEM_TRAY_S%d",
+ gdk_screen_get_number (screen));
+
+ icon->selection_atom = XInternAtom (xdisplay, buffer, False);
+
+ icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
+
+ icon->system_tray_opcode_atom = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_OPCODE",
+ False);
+
+ icon->orientation_atom = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_ORIENTATION",
+ False);
+
+ egg_tray_icon_update_manager_window (icon);
+
+ root_window = gdk_screen_get_root_window (screen);
+
+ /* Add a root window filter so that we get changes on MANAGER */
+ gdk_window_add_filter (root_window,
+ egg_tray_icon_manager_filter, icon);
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
+{
+ GdkDisplay *display;
+ GdkScreen *screen;
+
+ display = gdk_x11_lookup_xdisplay (DisplayOfScreen (xscreen));
+ screen = gdk_display_get_screen (display, XScreenNumberOfScreen (xscreen));
+
+ return egg_tray_icon_new_for_screen (screen, name);
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
+{
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL);
+}
+
+EggTrayIcon*
+egg_tray_icon_new (const gchar *name)
+{
+ return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL);
+}
+
+guint
+egg_tray_icon_send_message (EggTrayIcon *icon,
+ gint timeout,
+ const gchar *message,
+ gint len)
+{
+ guint stamp;
+
+ g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
+ g_return_val_if_fail (timeout >= 0, 0);
+ g_return_val_if_fail (message != NULL, 0);
+
+ if (icon->manager_window == None)
+ return 0;
+
+ if (len < 0)
+ len = strlen (message);
+
+ stamp = icon->stamp++;
+
+ /* Get ready to send the message */
+ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
+ (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+ timeout, len, stamp);
+
+ /* Now to send the actual message */
+ gdk_error_trap_push ();
+ while (len > 0)
+ {
+ XClientMessageEvent ev;
+ Display *xdisplay;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ ev.type = ClientMessage;
+ ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
+ ev.format = 8;
+ ev.message_type = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
+ if (len > 20)
+ {
+ memcpy (&ev.data, message, 20);
+ len -= 20;
+ message += 20;
+ }
+ else
+ {
+ memcpy (&ev.data, message, len);
+ len = 0;
+ }
+
+ XSendEvent (xdisplay,
+ icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev);
+ XSync (xdisplay, False);
+ }
+ gdk_error_trap_pop ();
+
+ return stamp;
+}
+
+void
+egg_tray_icon_cancel_message (EggTrayIcon *icon,
+ guint id)
+{
+ g_return_if_fail (EGG_IS_TRAY_ICON (icon));
+ g_return_if_fail (id > 0);
+
+ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
+ (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+ id, 0, 0);
+}
+
+GtkOrientation
+egg_tray_icon_get_orientation (EggTrayIcon *icon)
+{
+ g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL);
+
+ return icon->orientation;
+}
diff --git a/examples/python/systray/eggtrayicon.h b/examples/python/systray/eggtrayicon.h
new file mode 100644
index 0000000000..007f4c18e9
--- /dev/null
+++ b/examples/python/systray/eggtrayicon.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* eggtrayicon.h
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_TRAY_ICON_H__
+#define __EGG_TRAY_ICON_H__
+
+#include <gtk/gtkplug.h>
+#include <gdk/gdkx.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_TRAY_ICON (egg_tray_icon_get_type ())
+#define EGG_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon))
+#define EGG_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+#define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON))
+#define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON))
+#define EGG_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+
+typedef struct _EggTrayIcon EggTrayIcon;
+typedef struct _EggTrayIconClass EggTrayIconClass;
+
+struct _EggTrayIcon
+{
+ GtkPlug parent_instance;
+
+ guint stamp;
+
+ Atom selection_atom;
+ Atom manager_atom;
+ Atom system_tray_opcode_atom;
+ Atom orientation_atom;
+ Window manager_window;
+
+ GtkOrientation orientation;
+};
+
+struct _EggTrayIconClass
+{
+ GtkPlugClass parent_class;
+};
+
+GType egg_tray_icon_get_type (void);
+
+EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen *screen,
+ const gchar *name);
+
+EggTrayIcon *egg_tray_icon_new (const gchar *name);
+
+guint egg_tray_icon_send_message (EggTrayIcon *icon,
+ gint timeout,
+ const char *message,
+ gint len);
+void egg_tray_icon_cancel_message (EggTrayIcon *icon,
+ guint id);
+
+GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon);
+
+G_END_DECLS
+
+#endif /* __EGG_TRAY_ICON_H__ */
diff --git a/examples/python/systray/network_tray.py b/examples/python/systray/network_tray.py
new file mode 100755
index 0000000000..2f5043177d
--- /dev/null
+++ b/examples/python/systray/network_tray.py
@@ -0,0 +1,120 @@
+#! /usr/bin/python
+import pygtk; pygtk.require("2.0")
+import gtk
+import gtk.gdk
+import trayicon
+from NetworkManager import NetworkManager
+
+
+class network_tray:
+
+ def __init__(self):
+ self._make_icons()
+ self._make_menu()
+ self._make_tray()
+
+ self._nm = NetworkManager()
+ for signal in self._nm.NM_SIGNALS:
+ self._nm.nm_object.connect_to_signal(signal,
+ self._network_event)
+
+ self._network_event(None, None, None,None,None)
+
+ def _add_separator_item(self):
+ self._menu.append(gtk.SeparatorMenuItem())
+
+ def _add_device_menu_item(self, device):
+ menuitem = gtk.MenuItem()
+ hbox = gtk.HBox(homogeneous=gtk.FALSE, spacing=3)
+ hbox.pack_start(self._get_icon(device), expand=gtk.FALSE, fill=gtk.FALSE)
+ hbox.pack_start(gtk.Label(device["info.product"]), expand=gtk.TRUE, fill=gtk.TRUE)
+ menuitem.add(hbox)
+ hbox.show()
+ self._menu.append(menuitem)
+ menuitem.show_all()
+
+ def _add_network_menu_item(self, network):
+ menuitem = gtk.MenuItem()
+ hbox = gtk.HBox()
+ menuitem.add(hbox)
+ hbox.add(gtk.Label("label"))
+ progress = gtk.ProgressBar()
+ progress.set_fraction(.5)
+ hbox.add(progress)
+ hbox.show()
+ self._menu.append(menuitem)
+ menuitem.show()
+
+
+ def _network_event(self, interface, signal_name,
+ service, path, message):
+ devices = self._nm.get_devices()
+ tt = ""
+ for device in devices:
+ self._add_device_menu_item(device)
+ tt = "%s%s [%s]\n"%(tt,device["info.product"],device["nm.status"])
+
+ self._tooltips.set_tip(self._menu,tt)
+# self._add_separator_item()
+
+ self._current_icon = self._get_icon(self._nm.get_active_device())
+
+ self._current_icon.show()
+ self._top_level_menu.show_all()
+
+ def _get_icon(self, active_device):
+
+ if active_device:
+ if active_device["nm.type"] == self._nm.WIRED_DEVICE:
+ return self._wired_icon
+ elif active_device["nm.type"] == self._nm.WIRELESS_DEVICE:
+ return self._wireless_icon
+ else:
+ return self._nothing_icon
+
+ def _make_icons(self):
+ pb = gtk.gdk.pixbuf_new_from_file("../../../panel-applet/wireless-applet.png")
+ pb = pb.scale_simple(16,16,gtk.gdk.INTERP_NEAREST)
+ self._nothing_icon = gtk.Image()
+ self._nothing_icon.set_from_pixbuf(pb)
+
+ pb = gtk.gdk.pixbuf_new_from_file("../../../panel-applet/wireless-applet.png")
+ pb = pb.scale_simple(24,24,gtk.gdk.INTERP_NEAREST)
+ self._wireless_icon = gtk.Image()
+ self._wireless_icon.set_from_pixbuf(pb)
+
+ pb = gtk.gdk.pixbuf_new_from_file("../../../panel-applet/wired.png")
+ pb = pb.scale_simple(24,24,gtk.gdk.INTERP_NEAREST)
+ self._wired_icon = gtk.Image()
+ self._wired_icon.set_from_pixbuf(pb)
+
+ def _make_tray(self):
+ self._tray = trayicon.TrayIcon("NetworkManager")
+
+ self._tooltips = gtk.Tooltips()
+ tooltip = "Getting Network Information"
+ self._tooltips.set_tip(self._menu,tooltip)
+
+ self._tray.add(self._menu_bar)
+ self._tray.show()
+
+ def _make_menu(self):
+ self._menu_bar = gtk.MenuBar()
+
+ self._top_level_menu = gtk.MenuItem()
+ self._menu_bar.append(self._top_level_menu)
+
+ self._menu = gtk.Menu()
+ self._top_level_menu.set_submenu(self._menu)
+
+ self._current_icon = self._nothing_icon
+ self._current_icon.show()
+
+ self._top_level_menu.add(self._current_icon)
+ self._menu_bar.show()
+ self._top_level_menu.show()
+ self._menu.show()
+
+if __name__ == "__main__":
+ nt = network_tray()
+ gtk.main()
diff --git a/examples/python/systray/trayicon.override b/examples/python/systray/trayicon.override
new file mode 100644
index 0000000000..6752c2850a
--- /dev/null
+++ b/examples/python/systray/trayicon.override
@@ -0,0 +1,29 @@
+/* -*- Mode: C; c-basic-offset: 4 -*- */
+%%
+headers
+#include <Python.h>
+
+#include "pygobject.h"
+#include "eggtrayicon.h"
+%%
+modulename trayicon
+%%
+import gtk.Plug as PyGtkPlug_Type
+import gtk.gdk.Screen as PyGdkScreen_Type
+%%
+ignore-glob
+ *_get_type
+%%
+override egg_tray_icon_send_message kwargs
+static PyObject*
+_wrap_egg_tray_icon_send_message(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = {"timeout", "message", NULL};
+ int timeout, len, ret;
+ char *message;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "is#:TrayIcon.send_message", kwlist, &timeout, &message, &len))
+ return NULL;
+ ret = egg_tray_icon_send_message(EGG_TRAY_ICON(self->obj), timeout, message, len);
+ return PyInt_FromLong(ret);
+}
diff --git a/examples/python/systray/trayiconmodule.c b/examples/python/systray/trayiconmodule.c
new file mode 100644
index 0000000000..c2959a4854
--- /dev/null
+++ b/examples/python/systray/trayiconmodule.c
@@ -0,0 +1,25 @@
+/* -*- Mode: C; c-basic-offset: 4 -*- */
+
+/* include this first, before NO_IMPORT_PYGOBJECT is defined */
+#include <pygobject.h>
+
+void trayicon_register_classes (PyObject *d);
+
+extern PyMethodDef trayicon_functions[];
+
+DL_EXPORT(void)
+inittrayicon(void)
+{
+ PyObject *m, *d;
+
+ init_pygobject ();
+
+ m = Py_InitModule ("trayicon", trayicon_functions);
+ d = PyModule_GetDict (m);
+
+ trayicon_register_classes (d);
+
+ if (PyErr_Occurred ()) {
+ Py_FatalError ("can't initialise module trayicon :(");
+ }
+}