Hello all,
for a project of mine, I need a systray icon. I know that it is possible to get a one with PyKDE and there is a solution for PyGtk, but not for PyQt itself. But the code is rather easy and I found out that the ppl of qjackcontrol implemented a systray icon in Qt for themselves, using the spec + sample code from freedesktop.org (sorry, but I'm too lazy right know to find out all the links). All you need to do is to call some functions in libX11.so. For that, you need the Display (qt_x11_display()) and the WindowID (QWidget.winId())
So far, there are several ways to do the C calls from Python:
- extension module
- Pyrex
- ctypes
I chose the ctypes way and after some hassle (mostly typos!), I got it to actually work. It's not very advanced by now. To try it out, just replace the icon filename with something icon on your system. I put in all values in good faith and they are poorly documented right now, but I'll fix that later on.
I'll go to bed now....
greetings
Torsten -- Torsten Marek <[EMAIL PROTECTED]> ID: A244C858 -- FP: 1902 0002 5DFC 856B F146 894C 7CC5 451E A244 C858 www.keyserver.net -- wwwkeys.eu.pgp.net
import sys import qt from ctypes import *
class SystrayIcon(qt.QLabel):
def __init__(self, parent = None, name = ""):
qt.QLabel.__init__(self, parent, name, qt.Qt.WMouseNoMask | qt.Qt.WRepaintNoErase | qt.Qt.WType_TopLevel | qt.Qt.WStyle_Customize | qt.Qt.WStyle_NoBorder | qt.Qt.WStyle_StaysOnTop)
self.setMinimumSize(22, 22);
self.setBackgroundMode(qt.Qt.X11ParentRelative)
self.setBackgroundOrigin(qt.QWidget.WindowOrigin)
libX11 = cdll.LoadLibrary("/usr/X11R6/lib/libX11.so")
# get all functions, set arguments + return types
XDefaultScreenOfDisplay = libX11.XDefaultScreenOfDisplay
XDefaultScreenOfDisplay.argtypes = [c_void_p]
XDefaultScreenOfDisplay.restype = c_void_p
XScreenNumberOfScreen = libX11.XScreenNumberOfScreen
XScreenNumberOfScreen.argtypes = [c_void_p]
XInternAtom = libX11.XInternAtom
XInternAtom.argtypes = [c_void_p, c_char_p, c_int]
XGrabServer = libX11.XGrabServer
XGrabServer.argtypes = [c_void_p]
XGetSelectionOwner = libX11.XGetSelectionOwner
XGetSelectionOwner.argtypes = [c_void_p, c_int]
XSelectInput = libX11.XSelectInput
XSelectInput.argtypes = [c_void_p, c_int, c_long]
XUngrabServer = libX11.XUngrabServer
XUngrabServer.argtypes = [c_void_p]
XFlush = libX11.XFlush
XFlush.argtypes = [c_void_p]
# XClientMessageEvent
class data(Union):
_fields_ = [("b", c_char * 20),
("s", c_short * 10),
("l", c_long * 5)]
class XClientMessageEvent(Structure):
_fields_ = [("type", c_int),
("serial", c_ulong),
("send_event", c_int),
("display", c_void_p),
("window", c_int),
("message_type", c_int),
("format", c_int),
("data", data)]
# XEvent struct
class XEvent(Union):
_fields_ = [("xclient", XClientMessageEvent)]
XSendEvent = libX11.XSendEvent
XSendEvent.argtypes = [c_void_p, c_int, c_int, c_long, c_void_p]
XSync = libX11.XSync
XSync.argtypes = [c_void_p, c_int]
dpy = int(qt.qt_xdisplay())
trayWin = self.winId();
print "mywinid: 0x%x" % trayWin
screen = XDefaultScreenOfDisplay(dpy)
iscreen = XScreenNumberOfScreen(screen)
selectionAtom = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S%i" % iscreen, 0)
XGrabServer(dpy)
managerWin = XGetSelectionOwner(dpy, selectionAtom)
print "managerWin: 0x%x" % managerWin
if managerWin != 0:
XSelectInput(dpy, managerWin, 1L << 17)
XUngrabServer(dpy);
XFlush(dpy);
print managerWin
if managerWin != 0:
k = data()
k.l = (0, 0, trayWin, 0, 0)
ev = XClientMessageEvent(33, #type
0, # serial
0, # send_event
dpy, # display
managerWin, # window
XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", 0), # message type
32, # format
k)
XSendEvent(dpy, managerWin, 0, 0, addressof(ev))
XSync(dpy, 0)
img = qt.QImage("/usr/share/rattlesnake/pixmaps/rattlesnake64.png")
pm = qt.QPixmap()
pm.convertFromImage(img.smoothScale(22, 22), 0)
self.setPixmap(pm)
self.setAlignment(qt.Qt.AlignHCenter)
self.popup = qt.QPopupMenu()
self.popup.insertItem("This is amazing, but please quit now!", self.close)
def mousePressEvent(self, e):
if e.button() == qt.Qt.RightButton:
self.popup.popup(e.globalPos())
print "test"
a = qt.QApplication(sys.argv)
w = SystrayIcon()
qt.QObject.connect(a,qt.SIGNAL("lastWindowClosed()"),a,qt.SLOT("quit()"))
w.show()
a.exec_loop()
signature.asc
Description: OpenPGP digital signature
