1
0
mirror of https://github.com/gryf/wmdocklib.git synced 2025-12-18 20:10:23 +01:00

1569327 release 1.1 is broken

cleaning up more things.

MANIFEST.in includes ll readmes,
wmdocklib correctly populated.
This commit is contained in:
mfrasca
2006-10-03 08:03:55 +00:00
parent a8bbadde35
commit 5320092e59
7 changed files with 1017 additions and 8 deletions

View File

@@ -1,6 +1,8 @@
README.txt README.txt
setup.py setup.py
examples/README
examples/pywmdatetime.py examples/pywmdatetime.py
examples/pywmgeneric.py
examples/pywmhdmon.py examples/pywmhdmon.py
examples/pywmseti.py examples/pywmseti.py
examples/pywmsysmon.py examples/pywmsysmon.py
@@ -8,12 +10,8 @@ examples/sample.pywmdatetimerc
examples/sample.pywmgenericrc examples/sample.pywmgenericrc
examples/sample.pywmhdmonrc examples/sample.pywmhdmonrc
examples/sample.pywmsetirc examples/sample.pywmsetirc
examples/setup.py wmdocklib/README
pywmgeneral/__init__.py
pywmgeneral/pywmhelpers.py
pywmgeneral/setup.py
wmdocklib/__init__.py wmdocklib/__init__.py
wmdocklib/pywmgeneral.c wmdocklib/pywmgeneral.c
wmdocklib/pywmgeneral.h wmdocklib/pywmgeneral.h
wmdocklib/pywmgeneric.py
wmdocklib/pywmhelpers.py wmdocklib/pywmhelpers.py

View File

@@ -1,2 +1,2 @@
include *.txt include *.txt
include */*.py */*.c */*.h */sample.pywm*rc include */*.py */*.c */*.h */sample.pywm*rc */README

97
examples/README Normal file
View File

@@ -0,0 +1,97 @@
[Pywmdatetime]
Pywmdatetime is a WindowMaker dockapp for displaying time, date and
some other information. The colors and formats are easy to configure
through the configuration file or as command line arguments. Invoke
the program with --help or see the sample rc-file for more information.
[Pywmgeneric]
Pywmgeneric is a dockapp with five entrys that display the first line of
output from an external program, the returned string from an python
method or an static string. Three mouse actions can be associated with
each displayed entry.
[Pywmgeneric -- DETAILED]
Five different entries can be defined in pywmgeneric. Every entry can
have an action, an update_delay and up to three mouse actions associated
with it. Some additional options are also available.
The associated action of an entry is executed with update_delay time
between executions. The output from the action is stored. If no special
display options are defined, the application will display the first line
of output from the action. If it does not fit in the window, it will
slowly scroll in the window. Clicking with the mouse on the text invokes
one of the mouse actions, depending on which button was pressed. The
action can be to execute an external program, to run a python method or
to update the text through performing the action associated with the
entry. The mouse actions can retreive the text genererated by the timed
action.
Python methods that should be executed as actions should be defined in
the class UserMethods. Look in pywmgeneric.py, near the top, for this
class and the documentation of how these methods should be defined.
Note that the methods allready there only are samples and will probably
not work on your system.
Other options in the configuration file include:
scroll = yes|no - en-/disable scrolling of the text when it doesn't fit
display = <text> - display a static string instead of the first line of
the action-generated output.
See the sample configuration file for examples and more information.
Note that this file is only for reference, it is the one I use. Things
will probably not work on your system if you do not change it.
[Pywmgeneric -- USES]
This program is very generic (hence the name ;) ), the uses are many
since it is highly configurable.
I use it for displaying my cpu and system temperatures. I just defined
methods for reading two files in the /proc filesystem on my system.
I also use it for fetching headlines from a newspaper, displaying the
first headline fetched. If I click with my left button, all headlines
will appear in an xmessage. If I rightclick the headlines along with
summaries are displayed, and if I click with my middle button mozilla
will fire up showing the newspaper's website.
I have an external program which displays what's currently on tv,
ideal for use with this program I thought! I modified it a bit so
it printed a summary line at the top, and voila I have all
currently running tv programs scrolling by in an dockapp. And clicking
on it shows me the details.
You could use it as an application launcher, just display the name of
the applications and associate mouse actions to lauch them. The
xterm-entry in the sample shows this.
You could probably come up with much more than this!
[pywmhdmon]
pywmhdmon is a WindowMaker dockapp that displays the available space on
up to four of your filesystems. It also contains a bar showing the
current HD activity. It currently only works on system which has a
/proc/stat like file. The application is easy to configure, invoke it
with --help or see the sample rc-file for more information.
[pywmhdmon -- BUGS]
The activity bar does not work with the proc filesystem that comes with
the 2.6 kernels. It is just a matter of rewriting the app to parse the
new format, but I'm low on time personally.
[Pywmseti]
Pywmseti is an WindowMaker dockapp for monitoring your seti@home progress.
The application displays how many workunits you have done and the progress
on the current one. You start/stop the seti@home process by simply clicking
anywhere in the application. It also displays the time spent on the workunit
(or since you started the program if you restart it in the middle of a
workunit). Invoke the program with --help or see the sample rc-file for
more information about customization.
[pywmsysmon]
pywmsysmon is a WindowMaker dockapp that displays your cpu and memory
usages. The upper graph shows your cpu usage history and the lower
"progress bar" shows your current memory usage excluding cached and
buffered data. This program currently only works on systems which got
the /proc/stat and /proc/meminfo files available. Invoke the program
with --help for information about customization.

596
pywmgeneric/pywmgeneral.c Normal file
View File

@@ -0,0 +1,596 @@
/* pywmgeneral.c
*
* Python bindings to some of the most important functions in the widely used
* wmgeneral.c. Also some added functions. The rc file parser is removed since
* Python provide better facilities for this.
*
* Copyright (C) 2003 Kristoffer Erlandsson
*
* Licensed under the GNU General Public License.
*
* History:
*
* 2003-06-24 Kristoffer Erlandsson
* Added some additional event handling.
*
* 2003-06-16 Kristoffer Erlandsson
* Added checkForMouseClick to make catching of mouse clicks available from
* Python.
*
* 2003-06-14 Kristoffer Erlandsson
* Finished support for "everything" included in wmgeneral by default.
*
* 2003-06-13 Kristoffer Erlandsson
* File created made most of the pure wrapper functions and xpm inclusion.
*
*
*
* Thanks to Martijn Pieterse for createing the original wmgeneral.c
*
*/
#include <Python.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <stdarg.h>
#include <X11/Xlib.h>
#include <X11/xpm.h>
#include <X11/extensions/shape.h>
#include "pywmgeneral.h"
/*****************/
/* X11 Variables */
/*****************/
Window Root;
int screen;
int x_fd;
int d_depth;
XSizeHints mysizehints;
XWMHints mywmhints;
Pixel back_pix, fore_pix;
char *Geometry = "";
Window iconwin, win;
GC NormalGC;
XpmIcon wmgen;
Pixmap pixmask;
Atom deleteAtom; /* Added 2003-06-24 for graceful shutdown. */
/*****************************************************************************/
/* The Python stuff */
/*****************************************************************************/
static char **pixmap; /* Global pixmap, we only support one of these */
static char *maskBits; /* Global maskbits, also only 1 supported */
char **pyListToStrs(PyObject *l) {
/* Convert a python list of strings to a char **. */
int size, i;
char **target;
PyObject *s;
if (!PyList_Check(l)) {
PyErr_SetString(PyExc_TypeError, "List expected.");
return NULL;
}
size = PyList_Size(l);
target = (char **)malloc(size * sizeof(char *));
for (i = 0; i < size; i++) {
s = PySequence_GetItem(l, i);
if (s == NULL)
return NULL; /* Shouldn't happen. */
if (!PyString_Check(s)) {
PyErr_SetString(PyExc_TypeError, "String expected.");
return NULL;
}
target[i] = PyString_AsString(s);
}
return target;
}
static PyObject *
pywmgeneral_includePixmap(PyObject *self, PyObject *args) {
/* Set the global pixmap. */
PyObject *arg;
if (!PyArg_ParseTuple(args, "O", &arg))
return NULL;
if(!(pixmap = pyListToStrs(arg)))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pywmgeneral_openXwindow(PyObject *self, PyObject *args) {
/* This function now uses the global variable pixmap as xpm and creates the
* xbm mask of the given height and width from this one. IOW no other xbm
* masks are supported at the moment. This shouldn't be needed except in
* special cases (I think...)
*/
int argc, width, height;
PyObject *argvTmp;
char **argv;
if (!PyArg_ParseTuple(args, "iOii", &argc, &argvTmp, &width, &height))
return NULL;
if (!(argv = pyListToStrs(argvTmp)))
return NULL;
maskBits = (char *)malloc(width * height * sizeof(char));
createXBMfromXPM(maskBits, pixmap, width, height);
openXwindow(argc, argv, pixmap, maskBits, width, height);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pywmgeneral_redrawWindow(PyObject *self, PyObject *args) {
if (!PyArg_ParseTuple(args, ""))
return NULL;
RedrawWindow();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pywmgeneral_redrawWindowXY(PyObject *self, PyObject *args) {
int x, y;
if (!PyArg_ParseTuple(args, "ii", &x, &y))
return NULL;
RedrawWindowXY(x, y);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pywmgeneral_addMouseRegion(PyObject *self, PyObject *args) {
int index, left, top, right, bottom;
if (!PyArg_ParseTuple(args, "iiiii", &index, &left, &top, &right, &bottom))
return NULL;
AddMouseRegion(index, left, top, right, bottom);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pywmgeneral_checkMouseRegion(PyObject *self, PyObject *args) {
int x, y;
if (!PyArg_ParseTuple(args, "ii", &x, &y))
return NULL;
return Py_BuildValue("i", CheckMouseRegion(x, y));
}
static PyObject *
pywmgeneral_copyXPMArea(PyObject *self, PyObject *args) {
/* x - source x, y - source y
* sx - width, sy - height
* dx - destination x, dy - destination y
*
* Variables named as in the original wmgeneral.c, don't blame me for it :)
*/
int x, y, sx, sy, dx, dy;
if (!PyArg_ParseTuple(args, "iiiiii", &x, &y, &sx, &sy, &dx, &dy))
return NULL;
copyXPMArea(x, y, sx, sy, dx, dy);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pywmgeneral_checkForEvents(PyObject *self, PyObject *args) {
/* If we find an event we handle, return a dicitionary containing some
* information about it. Return None if there are no events we handle.
* Ignore events we don't handle. Also we provide a handler for when the
* window is exposed, redraw it.
*/
XEvent event;
if (!PyArg_ParseTuple(args, ""))
return NULL;
while (XPending(display)) {
XNextEvent(display, &event);
if (event.type == Expose) {
RedrawWindow();
}
else if (event.type == ClientMessage) {
if((Atom)event.xclient.data.l[0] == deleteAtom) {
XCloseDisplay(display);
return Py_BuildValue("{s:s}", "type", "destroynotify");
}
}
else if (event.type == DestroyNotify) {
/* This seems to never happen, why? */
XCloseDisplay(display);
return Py_BuildValue("{s:s}", "type", "destroynotify");
}
else if (event.type == ButtonRelease) {
return Py_BuildValue("{s:s,s:i,s:i,s:i}", "type", "buttonrelease",
"button", event.xbutton.button, "x",
event.xbutton.x, "y", event.xbutton.y);
}
}
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef PyWmgeneralMethods[] = {
{"openXwindow", pywmgeneral_openXwindow, METH_VARARGS,
"Open the X window containing everything."},
{"includePixmap", pywmgeneral_includePixmap, METH_VARARGS,
"Set the global pixmap that will be used as a mask and for everything else."},
{"redrawWindow", pywmgeneral_redrawWindow, METH_VARARGS,
"Redraw the window."},
{"redrawWindowXY", pywmgeneral_redrawWindowXY, METH_VARARGS,
"Redraw a give region of the window."},
{"addMouseRegion", pywmgeneral_addMouseRegion, METH_VARARGS,
"Add a mouse region with a given index."},
{"checkMouseRegion", pywmgeneral_checkMouseRegion, METH_VARARGS,
"Check if the given coordinates are in any mouse region."},
{"copyXPMArea", pywmgeneral_copyXPMArea, METH_VARARGS,
"Copy an area of the global XPM."},
{"checkForEvents", pywmgeneral_checkForEvents, METH_VARARGS,
"Check for some Xevents"},
{NULL, NULL, 0, NULL}
};
void initpywmgeneral(void) {
Py_InitModule("pywmgeneral", PyWmgeneralMethods);
}
/*****************************************************************************/
/* Original C sources (With some modifications) */
/*****************************************************************************/
/*****************/
/* Mouse Regions */
/*****************/
typedef struct {
int enable;
int top;
int bottom;
int left;
int right;
} MOUSE_REGION;
MOUSE_REGION mouse_region[MAX_MOUSE_REGION];
/***********************/
/* Function Prototypes */
/***********************/
static void GetXPM(XpmIcon *, char **);
static Pixel GetColor(char *);
void RedrawWindow(void);
void AddMouseRegion(int, int, int, int, int);
int CheckMouseRegion(int, int);
/*******************************************************************************\
|* GetXPM *|
\*******************************************************************************/
static void GetXPM(XpmIcon *wmgen, char *pixmap_bytes[]) {
XWindowAttributes attributes;
int err;
/* For the colormap */
XGetWindowAttributes(display, Root, &attributes);
wmgen->attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
err = XpmCreatePixmapFromData(display, Root, pixmap_bytes, &(wmgen->pixmap),
&(wmgen->mask), &(wmgen->attributes));
if (err != XpmSuccess) {
fprintf(stderr, "Not enough free colorcells.\n");
exit(1);
}
}
/*******************************************************************************\
|* GetColor *|
\*******************************************************************************/
static Pixel GetColor(char *name) {
XColor color;
XWindowAttributes attributes;
XGetWindowAttributes(display, Root, &attributes);
color.pixel = 0;
if (!XParseColor(display, attributes.colormap, name, &color)) {
fprintf(stderr, "wm.app: can't parse %s.\n", name);
} else if (!XAllocColor(display, attributes.colormap, &color)) {
fprintf(stderr, "wm.app: can't allocate %s.\n", name);
}
return color.pixel;
}
/*******************************************************************************\
|* flush_expose *|
\*******************************************************************************/
static int flush_expose(Window w) {
XEvent dummy;
int i=0;
while (XCheckTypedWindowEvent(display, w, Expose, &dummy))
i++;
return i;
}
/*******************************************************************************\
|* RedrawWindow *|
\*******************************************************************************/
void RedrawWindow(void) {
flush_expose(iconwin);
XCopyArea(display, wmgen.pixmap, iconwin, NormalGC,
0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
flush_expose(win);
XCopyArea(display, wmgen.pixmap, win, NormalGC,
0,0, wmgen.attributes.width, wmgen.attributes.height, 0,0);
}
/*******************************************************************************\
|* RedrawWindowXY *|
\*******************************************************************************/
void RedrawWindowXY(int x, int y) {
flush_expose(iconwin);
XCopyArea(display, wmgen.pixmap, iconwin, NormalGC,
x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
flush_expose(win);
XCopyArea(display, wmgen.pixmap, win, NormalGC,
x,y, wmgen.attributes.width, wmgen.attributes.height, 0,0);
}
/*******************************************************************************\
|* AddMouseRegion *|
\*******************************************************************************/
void AddMouseRegion(int index, int left, int top, int right, int bottom) {
if (index < MAX_MOUSE_REGION) {
mouse_region[index].enable = 1;
mouse_region[index].top = top;
mouse_region[index].left = left;
mouse_region[index].bottom = bottom;
mouse_region[index].right = right;
}
}
/*******************************************************************************\
|* CheckMouseRegion *|
\*******************************************************************************/
int CheckMouseRegion(int x, int y) {
int i;
int found;
found = 0;
for (i=0; i<MAX_MOUSE_REGION && !found; i++) {
if (mouse_region[i].enable &&
x <= mouse_region[i].right &&
x >= mouse_region[i].left &&
y <= mouse_region[i].bottom &&
y >= mouse_region[i].top)
found = 1;
}
if (!found) return -1;
return (i-1);
}
/*******************************************************************************\
|* createXBMfromXPM *|
\*******************************************************************************/
void createXBMfromXPM(char *xbm, char **xpm, int sx, int sy) {
int i,j,k;
int width, height, numcol, depth;
int zero=0;
unsigned char bwrite;
int bcount;
int curpixel;
sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &depth);
for (k=0; k!=depth; k++)
{
zero <<=8;
zero |= xpm[1][k];
}
for (i=numcol+1; i < numcol+sy+1; i++) {
bcount = 0;
bwrite = 0;
for (j=0; j<sx*depth; j+=depth) {
bwrite >>= 1;
curpixel=0;
for (k=0; k!=depth; k++)
{
curpixel <<=8;
curpixel |= xpm[i][j+k];
}
if ( curpixel != zero ) {
bwrite += 128;
}
bcount++;
if (bcount == 8) {
*xbm = bwrite;
xbm++;
bcount = 0;
bwrite = 0;
}
}
}
}
/*******************************************************************************\
|* copyXPMArea *|
\*******************************************************************************/
void copyXPMArea(int x, int y, int sx, int sy, int dx, int dy) {
XCopyArea(display, wmgen.pixmap, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
}
/*******************************************************************************\
|* copyXBMArea *|
\*******************************************************************************/
void copyXBMArea(int x, int y, int sx, int sy, int dx, int dy) {
XCopyArea(display, wmgen.mask, wmgen.pixmap, NormalGC, x, y, sx, sy, dx, dy);
}
/*******************************************************************************\
|* setMaskXY *|
\*******************************************************************************/
void setMaskXY(int x, int y) {
XShapeCombineMask(display, win, ShapeBounding, x, y, pixmask, ShapeSet);
XShapeCombineMask(display, iconwin, ShapeBounding, x, y, pixmask, ShapeSet);
}
/*******************************************************************************\
|* openXwindow *|
\*******************************************************************************/
void openXwindow(int argc, char *argv[], char *pixmap_bytes[], char *pixmask_bits, int pixmask_width, int pixmask_height) {
unsigned int borderwidth = 1;
XClassHint classHint;
char *display_name = NULL;
char *wname = argv[0];
XTextProperty name;
XGCValues gcv;
unsigned long gcm;
char *geometry = NULL;
int dummy=0;
int i, wx, wy;
/* Changed to work better with Python. Changed check in for loop to control
* argc instead of argv.
*/
for (i=1; i < argc; i++) {
if (!strcmp(argv[i], "-display")) {
display_name = argv[i+1];
i++;
}
if (!strcmp(argv[i], "-geometry")) {
geometry = argv[i+1];
i++;
}
}
if (!(display = XOpenDisplay(display_name))) {
fprintf(stderr, "%s: can't open display %s\n",
wname, XDisplayName(display_name));
exit(1);
}
screen = DefaultScreen(display);
Root = RootWindow(display, screen);
d_depth = DefaultDepth(display, screen);
x_fd = XConnectionNumber(display);
/* Convert XPM to XImage */
GetXPM(&wmgen, pixmap_bytes);
/* Create a window to hold the stuff */
mysizehints.flags = USSize | USPosition;
mysizehints.x = 0;
mysizehints.y = 0;
back_pix = GetColor("white");
fore_pix = GetColor("black");
XWMGeometry(display, screen, Geometry, NULL, borderwidth, &mysizehints,
&mysizehints.x, &mysizehints.y,&mysizehints.width,&mysizehints.height, &dummy);
mysizehints.width = 64;
mysizehints.height = 64;
win = XCreateSimpleWindow(display, Root, mysizehints.x, mysizehints.y,
mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
iconwin = XCreateSimpleWindow(display, win, mysizehints.x, mysizehints.y,
mysizehints.width, mysizehints.height, borderwidth, fore_pix, back_pix);
/* Added 2003-06-24 for graceful shutdown. */
deleteAtom = XInternAtom(display, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(display, win, &deleteAtom, 1);
/* Activate hints */
XSetWMNormalHints(display, win, &mysizehints);
classHint.res_name = wname;
classHint.res_class = wname;
XSetClassHint(display, win, &classHint);
XSelectInput(display, win, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
XSelectInput(display, iconwin, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
if (XStringListToTextProperty(&wname, 1, &name) == 0) {
fprintf(stderr, "%s: can't allocate window name\n", wname);
exit(1);
}
XSetWMName(display, win, &name);
/* Create GC for drawing */
gcm = GCForeground | GCBackground | GCGraphicsExposures;
gcv.foreground = fore_pix;
gcv.background = back_pix;
gcv.graphics_exposures = 0;
NormalGC = XCreateGC(display, Root, gcm, &gcv);
/* ONLYSHAPE ON */
pixmask = XCreateBitmapFromData(display, win, pixmask_bits, pixmask_width, pixmask_height);
XShapeCombineMask(display, win, ShapeBounding, 0, 0, pixmask, ShapeSet);
XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, pixmask, ShapeSet);
/* ONLYSHAPE OFF */
mywmhints.initial_state = WithdrawnState;
mywmhints.icon_window = iconwin;
mywmhints.icon_x = mysizehints.x;
mywmhints.icon_y = mysizehints.y;
mywmhints.window_group = win;
mywmhints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
XSetWMHints(display, win, &mywmhints);
XSetCommand(display, win, argv, argc);
XMapWindow(display, win);
if (geometry) {
if (sscanf(geometry, "+%d+%d", &wx, &wy) != 2) {
fprintf(stderr, "Bad geometry string.\n");
exit(1);
}
XMoveWindow(display, win, wx, wy);
}
}

66
pywmgeneric/pywmgeneral.h Normal file
View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2003 Kristoffer Erlandsson
*
* Licensed under the GNU General Public License.
* Copyright (C) 2003 Kristoffer Erlandsson
*
* Licensed under the GNU General Public License.
*/
#ifndef WMGENERAL_H_INCLUDED
#define WMGENERAL_H_INCLUDED
/***********/
/* Defines */
/***********/
#define MAX_MOUSE_REGION (16)
/************/
/* Typedefs */
/************/
typedef struct _rckeys rckeys;
struct _rckeys {
const char *label;
char **var;
};
typedef struct _rckeys2 rckeys2;
struct _rckeys2 {
const char *family;
const char *label;
char **var;
};
typedef struct {
Pixmap pixmap;
Pixmap mask;
XpmAttributes attributes;
} XpmIcon;
/*******************/
/* Global variable */
/*******************/
Display *display;
/***********************/
/* Function Prototypes */
/***********************/
void AddMouseRegion(int index, int left, int top, int right, int bottom);
int CheckMouseRegion(int x, int y);
void openXwindow(int argc, char *argv[], char **, char *, int, int);
void RedrawWindow(void);
void RedrawWindowXY(int x, int y);
void createXBMfromXPM(char *, char **, int, int);
void copyXPMArea(int, int, int, int, int, int);
void copyXBMArea(int, int, int, int, int, int);
void setMaskXY(int, int);
#endif

253
pywmgeneric/pywmhelpers.py Normal file
View File

@@ -0,0 +1,253 @@
"""pywmhelpers.py
Various helper functions when writing wm dockapps in Python. This module
is way better commented than the pywmgeneral one. This is the one
intented for use in applications. Many functions are just wrappers
around the ones in pywmgeneral but with nicer interfaces and better
documentation.
Copyright (C) 2003 Kristoffer Erlandsson
Licensed under the GNU General Public License
Changes:
2003-06-25 Kristoffer Erlandsson
Updated documentation
2003-06-24 Kristoffer Erlandsson
Some changes to handle the additional event handling in pywmgeneral
2003-06-16 Kristoffer Erlandsson
First workingish version
"""
import os
import re
import ConfigParser
import pywmgeneral
def readConfigFile(fileName, errOut):
"""Read the config file fileName.
Return a dictionary with the options and values in the DEFAULT
section. Ignore everything else. The configuration file should not
get so complicated so that sections are needed. errOut is the
file-like object to which error messages will be printed.
"""
if not os.access(fileName, os.R_OK):
if errOut:
errOut.write(
'Configuration file is not readable. Using defaults.\n')
return {}
cp = ConfigParser.ConfigParser()
try:
cp.read(fileName)
except ConfigParser.Error, e:
if errOut:
errOut.write('Error in configuration file:\n')
errOut.write(str(e) + '\nUsing defaults.')
return {}
defaults = cp.defaults()
if defaults == {}:
if errOut:
errOut.write(
'Missing or empty DEFAULT section in the config file.\n')
errOut.write('Using defaults.\n')
return defaults
def getCenterStartPos(s, letterWidth, areaWidth, offset):
"""Get the x starting position if we want to paint s centred."""
w = len(s) * letterWidth
textArea = areaWidth - offset * 2 - 1
return (textArea - w) / 2
def addChar(ch, x, y, letterWidth, letterHeight, lettersStartX, lettersStartY,
letters, digitWidth, digitHeight, digitsStartX, digitsStartY,
digits, xOffset, yOffset, width, height):
"""Paint the character ch at position x, y in the window.
Return the (width, height) of the character painted. Raise
ValueError if we try to paint a char not in letters or digits
or if we get out of bounds during painting. digits is really
just another line of chars, it's unlucky called digits everywhere
I used it since it contained only digits in the start. However,
now it contains various special chars too everywhere I use it. But
the name remains in too many places so I haven't gotten to change
it.
"""
chIndex = letters.find(ch.lower())
if chIndex != -1:
chX = lettersStartX + chIndex * letterWidth
chY = lettersStartY
w = letterWidth
h = letterHeight
else:
chIndex = digits.find(ch)
if chIndex != -1:
chX = digitsStartX + chIndex * digitWidth
chY = digitsStartY
w = digitWidth
h = digitHeight
else:
raise ValueError, "Unsupported char: '%s'" % ch
targX = x + xOffset
targY = y + yOffset
if targX + w > width - xOffset or targY + h > height - yOffset\
or targX < 0 or targY < 0:
raise ValueError, "Out of bounds."
pywmgeneral.copyXPMArea(chX, chY, w, h, targX, targY)
return (w, h)
def addString(s, x, y, letterWidth, letterHeight, lettersStartX, lettersStartY,
letters, digitWidth, digitHeight, digitsStartX, digitsStartY,
digits, xOffset, yOffset, width, height):
"""Add a string at the given x and y positions.
Call addChar repeatedely, so the same exception rules apply."""
lastW = 0
for letter in s:
w, h = addChar(letter, x + lastW, y, letterWidth, letterHeight,
lettersStartX, lettersStartY, letters, digitWidth,
digitHeight, digitsStartX, digitsStartY, digits,
xOffset, yOffset, width, height)
lastW += w
def getVertSpacing(numLines, margin, height, letterHeight, yOffset):
"""Return the optimal spacing between a number of lines.
margin is the space we want between the first line and the top."""
h = height - numLines * letterHeight - yOffset * 2 - margin
return h / (numLines - 1)
def readXPM(fileName):
"""Read the xpm in filename.
Return a list of strings containing the xpm. Raise IOError if we run
into trouble when trying to read the file. This function surely
doesn't handle all XPMs, but it handles the ones I use, so that'll
do.
"""
f = file(fileName, 'r')
lines = [l.rstrip('\n') for l in f.readlines()]
s = ''.join(lines)
res = []
while 1:
nextStrStart = s.find('"')
if nextStrStart != -1:
nextStrEnd = s.find('"', nextStrStart + 1)
if nextStrEnd != -1:
res.append(s[nextStrStart+1:nextStrEnd])
s = s[nextStrEnd+1:]
continue
break
return res
def setColor(xpm, name, newColor):
"""Find the color with comment name and set this color to newColor.
Change the source code of an XPM represented as a list of strings.
I'm certain that this will fail on many XPMs too, but it'll do for
the ones I use. No check is done that the color is valid, this has
to be done elsewhere.
"""
colorRE = re.compile(
r"^(?P<letter>.).*?c (?P<color>#.*?) s (?P<comment>.*)")
index = 1
for line in xpm[1:]:
m = colorRE.match(line)
if not m is None:
comment = m.group('comment')
if comment == name:
letter = m.group('letter')
color = newColor
xpm[index] = '%s\tc %s s %s' % (letter, color, comment)
index += 1
def setDefaultPixmap(xpm):
"""Set the pixmap of the program.
xpm is an XPM represented as a list of strings, possible gotten
from readXPM(). This is what we use all the time later. The XBM
mask is created out of the XPM. If I understand correctly how it
works we use the upper left rectangle as mask. This is the
simplest way to do it and is the desired behaviour in most cases.
"""
pywmgeneral.includePixmap(xpm)
def openXwindow(argv, w, h):
"""Open the X window of given width and height.
The XBM mask is here created from the upper left rectangle of the
XPM using the given width and height."""
pywmgeneral.openXwindow(len(argv), argv, w, h)
def redraw():
"""Redraw the window."""
pywmgeneral.redrawWindow()
def redrawXY(x, y):
"""Redraw a given region of the window."""
pywmgeneral.redrawWindowXY(x, y)
def copyXPMArea(sourceX, sourceY, width, height, targetX, targetY):
"""Copy an area of the global XPM."""
if width > 0 or height > 0:
pywmgeneral.copyXPMArea(sourceX, sourceY, width, height,
targetX, targetY)
def addMouseRegion(index, left, top, right, bottom):
"""Add a mouse region in the window."""
pywmgeneral.addMouseRegion(index, left, top, right, bottom)
def checkMouseRegion(x, y):
"""Check if x,y is in any mouse region. Return that region, otherwise -1.
"""
return pywmgeneral.checkMouseRegion(x, y)
def getEvent():
"""Check for XEvents and return one if found.
Return None if we find no events. There may be events pending still
after this function is called. If an event which we handle is found,
return a dictionary with information about it. All dictionaries
contain a 'type' field identifying the event. Now existing events
with dictionary keys are:
'buttonrelease':
x, y, button
'destroynotify':
"""
return pywmgeneral.checkForEvents()
def getColorCode(colorName, rgbFileName):
"""Convert a color to rgb code usable in an xpm.
We use the file rgbFileName for looking up the colors. Return None
if we find no match. The rgbFileName should be like the one found in
/usr/lib/X11R6/rgb.txt on most sytems.
"""
f = file(rgbFileName, 'r')
lines = f.readlines()
f.close()
for l in lines:
if l[0] != '!':
words = l.split()
if len(words) > 3:
name = ' '.join(words[3:])
if colorName.lower() == name.lower():
# Found the right color, get it's code
try:
r = int(words[0])
g = int(words[1])
b = int(words[2])
except ValueError:
continue
rgbstr = '#' + str(hex(r))[2:].zfill(2) + \
str(hex(g))[2:].zfill(2) + \
str(hex(b))[2:].zfill(2)
return rgbstr
return None

View File

@@ -28,6 +28,5 @@ setup(name="pywmdockapps",
scripts=['examples/pywmdatetime.py', scripts=['examples/pywmdatetime.py',
'examples/pywmhdmon.py', 'examples/pywmhdmon.py',
'examples/pywmseti.py', 'examples/pywmseti.py',
'examples/pywmsysmon.py', 'examples/pywmsysmon.py'],
'examples/setup.py'],
ext_modules = [module1]) ext_modules = [module1])