[prev in list] [next in list] [prev in thread] [next in thread]
List: pykde
Subject: Re: [PyKDE] Systray icons in PyQt
From: Torsten Marek <shlomme () gmx ! net>
Date: 2004-05-27 15:22:13
Message-ID: 40B607A5.3080305 () gmx ! net
[Download RAW message or body]
[Attachment #2 (multipart/mixed)]
Hello,
2nd version of ctypes code and Python extension module with one func
only.
The spec can be found here
http://freedesktop.org/Standards/systemtray-spec/systemtray-spec-0.1.html,
the code itself is taken from qjackctl (qjackctl.sf.net).
When the code has undergone some review, I'll put it into the wiki.
Should it be distributed somewhere else? Maybe it could go into the PyQt
examples directory?
greetings
Torsten
--
Torsten Marek <shlomme@gmx.net>
ID: A244C858 -- FP: 1902 0002 5DFC 856B F146 894C 7CC5 451E A244 C858
www.keyserver.net -- wwwkeys.eu.pgp.net
["SystrayIcon.py" (text/x-python)]
import qt
import ctypes as c
class SystrayIcon(qt.QLabel):
"""On construction, you have to supply a QPixmap instance holding the application \
icon. The pixmap should not be bigger than 32x32, preferably 22x22. Currently, no \
check is made.
The class can emits two signals:
Leftclick on icon: activated()
Rightclick on icon: contextMenuRequested(const QPoint&)
"""
def __init__(self, icon, 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 = c.cdll.LoadLibrary("/usr/X11R6/lib/libX11.so")
# get all functions, set arguments + return types
XDefaultScreenOfDisplay = libX11.XDefaultScreenOfDisplay
XDefaultScreenOfDisplay.argtypes = [c.c_void_p]
XDefaultScreenOfDisplay.restype = c.c_void_p
XScreenNumberOfScreen = libX11.XScreenNumberOfScreen
XScreenNumberOfScreen.argtypes = [c.c_void_p]
XInternAtom = libX11.XInternAtom
XInternAtom.argtypes = [c.c_void_p, c.c_char_p, c.c_int]
XGrabServer = libX11.XGrabServer
XGrabServer.argtypes = [c.c_void_p]
XGetSelectionOwner = libX11.XGetSelectionOwner
XGetSelectionOwner.argtypes = [c.c_void_p, c.c_int]
XSelectInput = libX11.XSelectInput
XSelectInput.argtypes = [c.c_void_p, c.c_int, c.c_long]
XUngrabServer = libX11.XUngrabServer
XUngrabServer.argtypes = [c.c_void_p]
XFlush = libX11.XFlush
XFlush.argtypes = [c.c_void_p]
class data(c.Union):
_fields_ = [("b", c.c_char * 20),
("s", c.c_short * 10),
("l", c.c_long * 5)]
class XClientMessageEvent(c.Structure):
_fields_ = [("type", c.c_int),
("serial", c.c_ulong),
("send_event", c.c_int),
("display", c.c_void_p),
("window", c.c_int),
("message_type", c.c_int),
("format", c.c_int),
("data", data)]
XSendEvent = libX11.XSendEvent
XSendEvent.argtypes = [c.c_void_p, c.c_int, c.c_int, c.c_long, c.c_void_p]
XSync = libX11.XSync
XSync.argtypes = [c.c_void_p, c.c_int]
dpy = int(qt.qt_xdisplay())
trayWin = self.winId();
iscreen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(dpy))
# get systray window (holds _NET_SYSTEM_TRAY_S<screen> atom)
selectionAtom = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S%i" % iscreen, 0)
XGrabServer(dpy)
managerWin = XGetSelectionOwner(dpy, selectionAtom)
if managerWin != 0:
# set StructureNotifyMask (1L << 17)
XSelectInput(dpy, managerWin, 1L << 17)
XUngrabServer(dpy);
XFlush(dpy);
if managerWin != 0:
# send "SYSTEM_TRAY_OPCODE_REQUEST_DOCK to managerWin
k = data()
k.l = (0, # CurrentTime
0, # REQUEST_DOCK
trayWin, # window ID
0, # empty
0) # empty
ev = XClientMessageEvent(33, #type: ClientMessage
0, # serial
0, # send_event
dpy, # display
managerWin, # systray manager
XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", 0), \
# message type 32, # format
k) # message data
XSendEvent(dpy, managerWin, 0, 0, c.addressof(ev))
XSync(dpy, 0)
self.setPixmap(icon)
self.setAlignment(qt.Qt.AlignHCenter)
if parent:
qt.QToolTip.add(self, parent.caption())
def setTooltipText(self, text):
qt.QToolTip.add(self, text)
def mousePressEvent(self, e):
if e.button() == qt.Qt.RightButton:
self.emit(qt.PYSIGNAL("contextMenuRequested(const QPoint&)"), \
(e.globalPos(),)) elif e.button() == qt.Qt.LeftButton:
self.emit(qt.PYSIGNAL("activated()"), ())
["traywin.c" (text/x-csrc)]
#include <Python.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
/* System Tray Protocol Specification opcodes. */
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
static PyObject* setTrayIcon(PyObject* self, PyObject* args) /*Display *dpy, Window trayWin*/
{
/* System Tray Protocol Specification. */
Display *dpy;
Window trayWin;
PyArg_ParseTuple(args, "ll", &dpy, &trayWin);
Screen *screen = XDefaultScreenOfDisplay(dpy);
int iScreen = XScreenNumberOfScreen(screen);
char szAtom[32];
snprintf(szAtom, sizeof(szAtom), "_NET_SYSTEM_TRAY_S%d", iScreen);
Atom selectionAtom = XInternAtom(dpy, szAtom, False);
XGrabServer(dpy);
Window managerWin = XGetSelectionOwner(dpy, selectionAtom);
if (managerWin != None)
XSelectInput(dpy, managerWin, StructureNotifyMask);
XUngrabServer(dpy);
XFlush(dpy);
if (managerWin != None) {
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = managerWin;
ev.xclient.message_type = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
ev.xclient.data.l[2] = trayWin;
ev.xclient.data.l[3] = 0;
ev.xclient.data.l[4] = 0;
XSendEvent(dpy, managerWin, False, NoEventMask, &ev);
XSync(dpy, False);
}
return Py_None;
}
static char traywin_docs[] =
"setTrayIcon: make the window WID a tray icon\n";
static PyMethodDef traywin_funcs[]= {
{"setTrayIcon", (PyCFunction)setTrayIcon, METH_VARARGS, traywin_docs},
{NULL}
};
void inittraywin(void)
{
PyObject* thismod = Py_InitModule3("traywin", traywin_funcs, "empty");
}
["systray2.py" (text/x-python)]
import qt
import sys
import traywin
class SystrayIcon(qt.QLabel):
def __init__(self, icon, 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)
dpy = int(qt.qt_xdisplay())
winid = self.winId();
print "test"
traywin.setTrayIcon(dpy, winid)
self.setPixmap(icon)
self.setAlignment(qt.Qt.AlignHCenter)
if parent:
qt.QToolTip.add(self, parent.caption())
def setTooltipText(self, text):
qt.QToolTip.add(self, text)
def mousePressEvent(self, e):
if e.button() == qt.Qt.RightButton:
self.emit(qt.PYSIGNAL("contextMenuRequested(const QPoint&)"), \
(e.globalPos(),)) elif e.button() == qt.Qt.LeftButton:
self.emit(qt.PYSIGNAL("activated()"), ())
def showPopup(pos):
popup.popup(pos)
a = qt.QApplication(sys.argv)
img = qt.QImage("/home/shlomme/bilder/rattlesnake_tray.png")
pm = qt.QPixmap()
pm.convertFromImage(img.smoothScale(22, 22), 0)
w = SystrayIcon(pm)
w.setTooltipText("Rattlesnake")
popup = qt.QPopupMenu()
popup.insertItem("This is amazing, but please quit now!", w.close)
qt.QObject.connect(w, qt.PYSIGNAL("contextMenuRequested(const QPoint&)"), showPopup)
qt.QObject.connect(a,qt.SIGNAL("lastWindowClosed()"),a,qt.SLOT("quit()"))
w.show()
a.exec_loop()
["signature.asc" (application/pgp-signature)]
_______________________________________________
PyKDE mailing list PyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic