rm my lucid experiment

This commit is contained in:
Dana Jansens 2003-01-17 06:40:00 +00:00
parent 58ff3f35c2
commit 6188650ce9
21 changed files with 0 additions and 2183 deletions

View file

@ -1,29 +0,0 @@
prefix = /tmp/ob
exec_prefix = $(prefix)
libdir = $(exec_prefix)/lib
targets = libotk.so libotk.a
sources = init.c display.c screeninfo.c rect.c gccache.c color.c font.c \
timer.c timerqueue.c imagecontrol.c
headers = init.h display.h screeninfo.h rect.h gccache.h color.h font.h \
timer.h timerqueue.h imagecontrol.h
CFLAGS += -g -W -Wall -I/usr/gwar/include/python2.2 `pkg-config --cflags xft`
LDFLAGS += `pkg-config --libs xft`
.PHONY: all install clean
all: $(targets)
install: $(targets)
install -d $(libdir)
install $^ $(libdir)
clean:
$(RM) $(targets) *.o core *\~ .\#*
libotk.so: $(sources:.c=.o)
$(CC) -shared -o $@ $^ $(LDFLAGS)
libotk.a: $(sources:.c=.o)
$(AR) -cr $@ $^

View file

@ -1,212 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "color.h"
#include "display.h"
#include "screeninfo.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
static Bool cleancache = False;
static PyObject *colorcache = NULL;
static void parseColorName(OtkColor *self, const char *name) {
XColor xcol;
// get rgb values from colorname
xcol.red = 0;
xcol.green = 0;
xcol.blue = 0;
xcol.pixel = 0;
if (!XParseColor(OBDisplay->display,
OtkDisplay_ScreenInfo(OBDisplay, self->screen)->colormap,
name, &xcol)) {
fprintf(stderr, "OtkColor: color parse error: \"%s\"\n", name);
self->red = self->green = self->blue = 0;
} else {
self->red = xcol.red >> 8;
self->green = xcol.green >> 8;
self->blue = xcol.blue >> 8;
}
}
static void doCacheCleanup() {
unsigned long *pixels;
int i, ppos;
unsigned int count;
PyObject *key; // this is a color too, but i dont need to use it as such
OtkColor *color;
// ### TODO - support multiple displays!
if (!PyDict_Size(colorcache)) return; // nothing to do
pixels = malloc(sizeof(unsigned long) * PyDict_Size(colorcache));
for (i = 0; i < ScreenCount(OBDisplay->display); i++) {
count = 0;
ppos = 0;
while (PyDict_Next(colorcache, &ppos, &key, (PyObject**)&color)) {
// get the screen from the hash
if (color->screen != i) continue; // wrong screen
// does someone other than the cache have a reference? (the cache gets 2)
if (color->ob_refcnt > 2)
continue;
pixels[count++] = color->pixel;
PyDict_DelItem(colorcache, key);
--ppos; // back up one in the iteration
}
if (count > 0)
XFreeColors(OBDisplay->display,
OtkDisplay_ScreenInfo(OBDisplay, i)->colormap,
pixels, count, 0);
}
free(pixels);
cleancache = False;
}
static void allocate(OtkColor *self) {
XColor xcol;
// allocate color from rgb values
xcol.red = self->red | self->red << 8;
xcol.green = self->green | self->green << 8;
xcol.blue = self->blue | self->blue << 8;
xcol.pixel = 0;
if (!XAllocColor(OBDisplay->display,
OtkDisplay_ScreenInfo(OBDisplay, self->screen)->colormap,
&xcol)) {
fprintf(stderr, "OtkColor: color alloc error: rgb:%x/%x/%x\n",
self->red, self->green, self->blue);
xcol.pixel = 0;
}
self->pixel = xcol.pixel;
if (cleancache)
doCacheCleanup();
}
PyObject *OtkColor_FromRGB(int r, int g, int b, int screen)
{
OtkColor *self = PyObject_New(OtkColor, &OtkColor_Type);
PyObject *cached;
assert(screen >= 0); assert(r >= 0); assert(g >= 0); assert(b >= 0);
assert(r <= 0xff); assert(g <= 0xff); assert(b <= 0xff);
if (!colorcache) colorcache = PyDict_New();
self->red = r;
self->green = g;
self->blue = b;
self->screen = screen;
// does this color already exist in the cache?
cached = PyDict_GetItem(colorcache, (PyObject*)self);
if (cached) {
Py_INCREF(cached);
return cached;
}
// add it to the cache
PyDict_SetItem(colorcache, (PyObject*)self, (PyObject*)self);
allocate(self);
return (PyObject*)self;
}
PyObject *OtkColor_FromName(const char *name, int screen)
{
OtkColor *self = PyObject_New(OtkColor, &OtkColor_Type);
PyObject *cached;
assert(screen >= 0); assert(name);
if (!colorcache) colorcache = PyDict_New();
self->red = -1;
self->green = -1;
self->blue = -1;
self->screen = screen;
parseColorName(self, name);
// does this color already exist in the cache?
cached = PyDict_GetItem(colorcache, (PyObject*)self);
if (cached) {
Py_INCREF(cached);
return cached;
}
// add it to the cache
PyDict_SetItem(colorcache, (PyObject*)self, (PyObject*)self);
allocate(self);
return (PyObject*)self;
}
void OtkColor_CleanupColorCache()
{
cleancache = True;
}
static void otkcolor_dealloc(OtkColor* self)
{
// when this is called, the color has already been cleaned out of the cache
PyObject_Del((PyObject*)self);
}
static int otkcolor_compare(OtkColor *c1, OtkColor *c2)
{
long result;
unsigned long p1, p2;
p1 = c1->red << 16 | c1->green << 8 | c1->blue;
p2 = c2->red << 16 | c2->green << 8 | c2->blue;
if (p1 < p2)
result = -1;
else if (p1 > p2)
result = 1;
else
result = 0;
return result;
}
static PyObject *otkcolor_repr(OtkColor *self)
{
return PyString_FromFormat("rgb:%x/%x/%x", self->red, self->green,
self->blue);
}
static long otkcolor_hash(OtkColor *self)
{
return self->screen << 24 | self->red << 16 | self->green << 8 | self->blue;
}
PyTypeObject OtkColor_Type = {
PyObject_HEAD_INIT(NULL)
0,
"OtkColor",
sizeof(OtkColor),
0,
(destructor)otkcolor_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)otkcolor_compare, /*tp_compare*/
(reprfunc)otkcolor_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)otkcolor_hash, /*tp_hash */
};

View file

@ -1,23 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __color_h
#define __color_h
#include <X11/Xlib.h>
#include <Python.h>
extern PyTypeObject OtkColor_Type;
//! OtkColor objects are immutable. DONT CHANGE THEM.
typedef struct OtkColor {
PyObject_HEAD
int red, green, blue;
int screen;
unsigned long pixel;
} OtkColor;
PyObject *OtkColor_FromRGB(int r, int g, int b, int screen);
PyObject *OtkColor_FromName(const char *name, int screen);
void OtkColor_CleanupColorCache();
#endif // __color_h

View file

@ -1,230 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "display.h"
#include "screeninfo.h"
#include <X11/keysym.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif // SHAPE
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif // HAVE_STDIO_H
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif // HAVE_STDLIB_H
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif // HAVE_FCNTL_H
#ifdef HAVE_UNISTD_H
# include <sys/types.h>
# include <unistd.h>
#endif // HAVE_UNISTD_H
#include "../src/gettext.h"
extern PyTypeObject OtkDisplay_Type;
static int xerrorHandler(Display *d, XErrorEvent *e);
struct OtkDisplay *OBDisplay = NULL;
void OtkDisplay_Initialize(char *name)
{
OtkDisplay* self;
PyObject *disp_env;
XModifierKeymap *modmap;
unsigned int NumLockMask = 0, ScrollLockMask = 0;
size_t cnt;
int i;
int junk;
(void) junk;
self = PyObject_New(OtkDisplay, &OtkDisplay_Type);
// Open the X display
if (!(self->display = XOpenDisplay(name))) {
printf(_("Unable to open connection to the X server. Please set the \n\
DISPLAY environment variable approriately, or use the '-display' command \n\
line argument.\n\n"));
exit(1);
}
if (fcntl(ConnectionNumber(self->display), F_SETFD, 1) == -1) {
printf(_("Couldn't mark display connection as close-on-exec.\n\n"));
exit(1);
}
XSetErrorHandler(xerrorHandler);
// set the DISPLAY environment variable for any lauched children, to the
// display we're using, so they open in the right place.
disp_env = PyString_FromFormat("DISPLAY=%s", DisplayString(self->display));
if (putenv(PyString_AsString(disp_env))) {
printf(_("warning: couldn't set environment variable 'DISPLAY'\n"));
perror("putenv()");
}
Py_DECREF(disp_env);
// find the availability of X extensions we like to use
#ifdef SHAPE
self->shape = XShapeQueryExtension(self->display,
&self->shape_event_basep, &junk);
#endif
#ifdef XINERAMA
self->xinerama = XineramaQueryExtension(self->display,
&self->xinerama_event_basep, &junk);
#endif // XINERAMA
// get lock masks that are defined by the display (not constant)
modmap = XGetModifierMapping(self->display);
if (modmap && modmap->max_keypermod > 0) {
const int mask_table[] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
const size_t size = (sizeof(mask_table) / sizeof(mask_table[0])) *
modmap->max_keypermod;
// get the values of the keyboard lock modifiers
// Note: Caps lock is not retrieved the same way as Scroll and Num lock
// since it doesn't need to be.
const KeyCode num_lock = XKeysymToKeycode(self->display, XK_Num_Lock);
const KeyCode scroll_lock = XKeysymToKeycode(self->display,
XK_Scroll_Lock);
for (cnt = 0; cnt < size; ++cnt) {
if (! modmap->modifiermap[cnt]) continue;
if (num_lock == modmap->modifiermap[cnt])
NumLockMask = mask_table[cnt / modmap->max_keypermod];
if (scroll_lock == modmap->modifiermap[cnt])
ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
}
}
if (modmap) XFreeModifiermap(modmap);
self->mask_list[0] = 0;
self->mask_list[1] = LockMask;
self->mask_list[2] = NumLockMask;
self->mask_list[3] = LockMask | NumLockMask;
self->mask_list[4] = ScrollLockMask;
self->mask_list[5] = ScrollLockMask | LockMask;
self->mask_list[6] = ScrollLockMask | NumLockMask;
self->mask_list[7] = ScrollLockMask | LockMask | NumLockMask;
// set the global var, for the new screeninfo's
OBDisplay = self;
// Get information on all the screens which are available.
self->screenInfoList = (PyListObject*)PyList_New(ScreenCount(self->display));
for (i = 0; i < ScreenCount(self->display); ++i)
PyList_SetItem((PyObject*)self->screenInfoList, i, OtkScreenInfo_New(i));
Py_INCREF(OBDisplay); // make sure it stays around!!
}
void OtkDisplay_Grab(OtkDisplay *self)
{
assert(self);
if (self->grab_count == 0)
XGrabServer(self->display);
self->grab_count++;
}
void OtkDisplay_Ungrab(OtkDisplay *self)
{
if (self->grab_count == 0) return;
self->grab_count--;
if (self->grab_count == 0)
XUngrabServer(self->display);
}
OtkScreenInfo *OtkDisplay_ScreenInfo(OtkDisplay *self, int num)
{
assert(num >= 0);
return (OtkScreenInfo*)PyList_GetItem((PyObject*)self->screenInfoList, num);
}
static PyObject *otkdisplay_grab(OtkDisplay* self, PyObject* args)
{
if (!PyArg_ParseTuple(args, ":grab"))
return NULL;
OtkDisplay_Grab(self);
return Py_None;
}
static PyObject *otkdisplay_ungrab(OtkDisplay* self, PyObject* args)
{
if (!PyArg_ParseTuple(args, ":ungrab"))
return NULL;
OtkDisplay_Ungrab(self);
return Py_None;
}
static PyMethodDef get_methods[] = {
{"grab", (PyCFunction)otkdisplay_grab, METH_VARARGS,
"Grab the X display."},
{"ungrab", (PyCFunction)otkdisplay_ungrab, METH_VARARGS,
"Ungrab/Release the X display."},
{NULL, NULL, 0, NULL}
};
static void otkdisplay_dealloc(PyObject* self)
{
XCloseDisplay(((OtkDisplay*) self)->display);
Py_DECREF(((OtkDisplay*) self)->screenInfoList);
PyObject_Del(self);
}
static PyObject *otkdisplay_getattr(PyObject *obj, char *name)
{
return Py_FindMethod(get_methods, obj, name);
}
PyTypeObject OtkDisplay_Type = {
PyObject_HEAD_INIT(NULL)
0,
"OtkDisplay",
sizeof(OtkDisplay),
0,
otkdisplay_dealloc, /*tp_dealloc*/
0, /*tp_print*/
otkdisplay_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
static int xerrorHandler(Display *d, XErrorEvent *e)
{
#ifdef DEBUG
char errtxt[128];
//if (e->error_code != BadWindow)
{
XGetErrorText(d, e->error_code, errtxt, 128);
printf("X Error: %s\n", errtxt);
}
#else
(void)d;
(void)e;
#endif
return False;
}

View file

@ -1,58 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __display_h
#define __display_h
#include <X11/Xlib.h>
#include <Python.h>
struct OtkScreenInfo;
struct OtkDisplay;
extern struct OtkDisplay *OBDisplay; // the global display XXX: move this to app.h and ob.h?
extern PyTypeObject OtkDisplay_Type;
typedef struct OtkDisplay {
PyObject_HEAD
//! The X display
Display *display;
//! Does the display have the Shape extention?
Bool shape;
//! Base for events for the Shape extention
int shape_event_basep;
//! Does the display have the Xinerama extention?
Bool xinerama;
//! Base for events for the Xinerama extention
int xinerama_event_basep;
//! A list of all possible combinations of keyboard lock masks
unsigned int mask_list[8];
//! The number of requested grabs on the display
int grab_count;
//! A list of information for all screens on the display
PyListObject *screenInfoList;
} OtkDisplay;
//! Opens the X display, and sets the global OBDisplay variable
/*!
@see OBDisplay::display
@param name The name of the X display to open. If it is null, the DISPLAY
environment variable is used instead.
*/
void OtkDisplay_Initialize(char *name);
//! Grabs the display
void OtkDisplay_Grab(OtkDisplay *self);
//! Ungrabs the display
void OtkDisplay_Ungrab(OtkDisplay *self);
//! Get the screen info for a specific screen
struct OtkScreenInfo *OtkDisplay_ScreenInfo(OtkDisplay *self, int num);
#endif // __display_h

View file

@ -1,154 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "font.h"
#include "display.h"
#include "color.h"
#include "../src/gettext.h"
static Bool xft_init = False;
static const char *fallback = "fixed";
void OtkFont_Initialize()
{
if (!XftInit(0)) {
printf(_("Couldn't initialize Xft version %d.%d.%d.\n\n"),
XFT_MAJOR, XFT_MINOR, XFT_REVISION);
exit(3);
}
printf(_("Using Xft %d.%d.%d.\n"), XFT_MAJOR, XFT_MINOR, XFT_REVISION);
xft_init = True;
}
PyObject *OtkFont_New(int screen, const char *fontstring, Bool shadow,
unsigned char offset, unsigned char tint)
{
OtkFont *self = PyObject_New(OtkFont, &OtkFont_Type);
assert(xft_init);
assert(screen >= 0);
assert(fontstring);
self->screen = screen;
self->shadow = shadow;
self->offset = offset;
self->tint = tint;
if (!(self->xftfont = XftFontOpenName(OBDisplay->display, screen,
fontstring))) {
printf(_("Unable to load font: %s"), fontstring);
printf(_("Trying fallback font: %s\n"), fallback);
if (!(self->xftfont =
XftFontOpenName(OBDisplay->display, screen, fallback))) {
printf(_("Unable to load font: %s"), fallback);
printf(_("Aborting!.\n"));
exit(3); // can't continue without a font
}
}
return (PyObject*)self;
}
int OtkFont_MeasureString(OtkFont *self, const char *string)//, Bool utf8)
{
XGlyphInfo info;
/* if (utf8)*/
XftTextExtentsUtf8(OBDisplay->display, self->xftfont,
(const FcChar8*)string, strlen(string), &info);
/* else
XftTextExtents8(OBDisplay->display, self->xftfont,
(const FcChar8*)string, strlen(string), &info);*/
return info.xOff + (self->shadow ? self->offset : 0);
}
void OtkFont_DrawString(OtkFont *self, XftDraw *d, int x, int y,
OtkColor *color, const char *string)//, Bool utf8)
{
assert(self);
assert(d);
if (self->shadow) {
XftColor c;
c.color.red = 0;
c.color.green = 0;
c.color.blue = 0;
c.color.alpha = self->tint | self->tint << 8; // transparent shadow
c.pixel = BlackPixel(OBDisplay->display, self->screen);
/* if (utf8)*/
XftDrawStringUtf8(d, &c, self->xftfont, x + self->offset,
self->xftfont->ascent + y + self->offset,
(const FcChar8*)string, strlen(string));
/* else
XftDrawString8(d, &c, self->xftfont, x + self->offset,
self->xftfont->ascent + y + self->offset,
(const FcChar8*)string, strlen(string));*/
}
XftColor c;
c.color.red = color->red | color->red << 8;
c.color.green = color->green | color->green << 8;
c.color.blue = color->blue | color->blue << 8;
c.pixel = color->pixel;
c.color.alpha = 0xff | 0xff << 8; // no transparency in BColor yet
/* if (utf8)*/
XftDrawStringUtf8(d, &c, self->xftfont, x, self->xftfont->ascent + y,
(const FcChar8*)string, strlen(string));
/* else
XftDrawString8(d, &c, self->xftfont, x, self->xftfont->ascent + y,
(const FcChar8*)string, strlen(string));*/
}
static PyObject *otkfont_measurestring(OtkFont* self, PyObject* args)
{
char *s;
if (!PyArg_ParseTuple(args, "s", &s))
return NULL;
return PyInt_FromLong(OtkFont_MeasureString(self, s));
}
static PyMethodDef get_methods[] = {
{"measureString", (PyCFunction)otkfont_measurestring, METH_VARARGS,
"Measure the length of a string with a font."},
{NULL, NULL, 0, NULL}
};
static void otkfont_dealloc(OtkFont* self)
{
// this is always set. cuz if it failed.. the app would exit!
XftFontClose(OBDisplay->display, self->xftfont);
PyObject_Del((PyObject*)self);
}
static PyObject *otkfont_getattr(PyObject *obj, char *name)
{
return Py_FindMethod(get_methods, obj, name);
}
PyTypeObject OtkFont_Type = {
PyObject_HEAD_INIT(NULL)
0,
"OtkFont",
sizeof(OtkFont),
0,
(destructor)otkfont_dealloc, /*tp_dealloc*/
0, /*tp_print*/
otkfont_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};

View file

@ -1,64 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __font_h
#define __font_h
#include <X11/Xlib.h>
#define _XFT_NO_COMPAT_ // no Xft 1 API
#include <X11/Xft/Xft.h>
#include <Python.h>
extern PyTypeObject OtkFont_Type;
struct OtkColor;
struct ScreenInfo;
#define OTKFONTHEIGHT(font) (font->xftfont->height + \
(font->shadow ? font->offset : 0))
#define OTKFONTMAXCHARWIDTH(font) (font->xftfont->max_advance_width)
typedef struct OtkFont {
PyObject_HEAD
int screen;
Bool shadow;
unsigned char offset;
unsigned char tint;
XftFont *xftfont;
} OtkFont;
void OtkFont_Initialize();
PyObject *OtkFont_New(int screen, const char *fontstring, Bool shadow,
unsigned char offset, unsigned char tint);
int OtkFont_MeasureString(OtkFont *self, const char *string);//, Bool utf8);
//! Draws a string into an XftDraw object
/*!
Be Warned: If you use an XftDraw object and a color, or a font from
different screens, you WILL have unpredictable results! :)
*/
void OtkFont_DrawString(OtkFont *self, XftDraw *d, int x, int y,
struct OtkColor *color, const char *string);//, Bool utf8);
/*
bool createXftFont(void);
public:
// loads an Xft font
BFont(int screen_num, const std::string &fontstring, bool shadow,
unsigned char offset, unsigned char tint);
virtual ~BFont();
inline const std::string &fontstring() const { return _fontstring; }
unsigned int height() const;
unsigned int maxCharWidth() const;
unsigned int measureString(const std::string &string,
bool utf8 = false) const;
};
}
*/
#endif // __font_h

View file

@ -1,234 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "gccache.h"
#include "screeninfo.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
static OtkGCCache *gccache = NULL;
OtkGCCacheContext *OtkGCCacheContext_New()
{
OtkGCCacheContext *self = malloc(sizeof(OtkGCCacheContext));
self->gc = 0;
self->pixel = 0ul;
self->fontid = 0ul;
self->function = 0;
self->subwindow = 0;
self->used = False;
self->screen = ~0;
self->linewidth = 0;
return self;
}
void OtkGCCacheContext_Destroy(OtkGCCacheContext *self)
{
if (self->gc)
XFreeGC(OBDisplay->display, self->gc);
free(self);
}
void OtkGCCacheContext_Set(OtkGCCacheContext *self,
OtkColor *color, XFontStruct *font,
int function, int subwindow, int linewidth)
{
XGCValues gcv;
unsigned long mask;
self->pixel = gcv.foreground = color->pixel;
self->function = gcv.function = function;
self->subwindow = gcv.subwindow_mode = subwindow;
self->linewidth = gcv.line_width = linewidth;
gcv.cap_style = CapProjecting;
mask = GCForeground | GCFunction | GCSubwindowMode | GCLineWidth |
GCCapStyle;
if (font) {
self->fontid = gcv.font = font->fid;
mask |= GCFont;
} else {
self->fontid = 0;
}
XChangeGC(OBDisplay->display, self->gc, mask, &gcv);
}
void OtkGCCacheContext_SetFont(OtkGCCacheContext *self,
XFontStruct *font)
{
if (!font) {
self->fontid = 0;
return;
}
XGCValues gcv;
self->fontid = gcv.font = font->fid;
XChangeGC(OBDisplay->display, self->gc, GCFont, &gcv);
}
OtkGCCacheItem *OtkGCCacheItem_New()
{
OtkGCCacheItem *self = malloc(sizeof(OtkGCCacheItem));
self->ctx = 0;
self->count = 0;
self->hits = 0;
self->fault = False;
return self;
}
void OtkGCCache_Initialize()
{
unsigned int i;
gccache = malloc(sizeof(OtkGCCache));
gccache->context_count = 128;
gccache->cache_size = 16;
gccache->cache_buckets = 8 * ScreenCount(OBDisplay->display);
gccache->cache_total_size = gccache->cache_size * gccache->cache_buckets;
gccache->contexts = malloc(sizeof(OtkGCCacheContext*) *
gccache->context_count);
for (i = 0; i < gccache->context_count; ++i)
gccache->contexts[i] = OtkGCCacheContext_New();
gccache->cache = malloc(sizeof(OtkGCCacheItem*) * gccache->cache_total_size);
for (i = 0; i < gccache->cache_total_size; ++i)
gccache->cache[i] = OtkGCCacheItem_New();
}
/*void OtkGCCache_Destroy()
{
unsigned int i;
for (i = 0; i < gccache->context_count; ++i)
OtkGCCacheContext_Destroy(gccache->contexts[i]);
for (i = 0; i < gccache->cache_total_size; ++i)
free(gccache->cache[i]);
free(gccache->contexts);
free(gccache->cache);
free(gccache);
gccache = NULL;
}*/
static OtkGCCacheContext *nextContext(int screen)
{
Window hd = OtkDisplay_ScreenInfo(OBDisplay, screen)->root_window;
OtkGCCacheContext *c;
unsigned int i;
for (i = 0; i < gccache->context_count; ++i) {
c = gccache->contexts[i];
if (! c->gc) {
c->gc = XCreateGC(OBDisplay->display, hd, 0, 0);
c->used = False;
c->screen = screen;
}
if (! c->used && c->screen == screen)
return c;
}
fprintf(stderr, "OtkGCCache: context fault!\n");
abort();
return NULL; // shut gcc up
}
static void OtkGCCache_InternalRelease(OtkGCCacheContext *ctx)
{
ctx->used = False;
}
OtkGCCacheItem *OtkGCCache_Find(OtkColor *color, XFontStruct *font,
int function, int subwindow, int linewidth)
{
const unsigned long pixel = color->pixel;
const int screen = color->screen;
const int key = color->red ^ color->green ^ color->blue;
int k = (key % gccache->cache_size) * gccache->cache_buckets;
unsigned int i = 0; // loop variable
OtkGCCacheItem *c = gccache->cache[k], *prev = 0;
/*
this will either loop cache_buckets times then return/abort or
it will stop matching
*/
while (c->ctx &&
(c->ctx->pixel != pixel || c->ctx->function != function ||
c->ctx->subwindow != subwindow || c->ctx->screen != screen ||
c->ctx->linewidth != linewidth)) {
if (i < (gccache->cache_buckets - 1)) {
prev = c;
c = gccache->cache[++k];
++i;
continue;
}
if (c->count == 0 && c->ctx->screen == screen) {
// use this cache item
OtkGCCacheContext_Set(c->ctx, color, font, function, subwindow,
linewidth);
c->ctx->used = True;
c->count = 1;
c->hits = 1;
return c;
}
// cache fault!
fprintf(stderr, "OtkGCCache: cache fault, count: %d, screen: %d, item screen: %d\n", c->count, screen, c->ctx->screen);
abort();
}
if (c->ctx) {
// reuse existing context
if (font && font->fid && font->fid != c->ctx->fontid)
OtkGCCacheContext_SetFont(c->ctx, font);
c->count++;
c->hits++;
if (prev && c->hits > prev->hits) {
gccache->cache[k] = prev;
gccache->cache[k-1] = c;
}
} else {
c->ctx = nextContext(screen);
OtkGCCacheContext_Set(c->ctx, color, font, function, subwindow, linewidth);
c->ctx->used = True;
c->count = 1;
c->hits = 1;
}
return c;
}
void OtkGCCache_Release(OtkGCCacheItem *item)
{
item->count--;
}
void OtkGCCache_Purge()
{
unsigned int i;
for (i = 0; i < gccache->cache_total_size; ++i) {
OtkGCCacheItem *d = gccache->cache[i];
if (d->ctx && d->count == 0) {
OtkGCCache_InternalRelease(d->ctx);
d->ctx = 0;
}
}
}

View file

@ -1,98 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __gccache_h
#define __gccache_h
#include <X11/Xlib.h>
#include "display.h"
#include "color.h"
struct OtkGCCacheItem;
typedef struct OtkGCCacheContext {
GC gc;
unsigned long pixel;
unsigned long fontid;
int function;
int subwindow;
Bool used;
int screen;
int linewidth;
} OtkGCCacheContext;
OtkGCCacheContext *OtkGCCacheContext_New();
void OtkGCCacheContext_Destroy(OtkGCCacheContext *self);
void OtkGCCacheContext_Set(OtkGCCacheContext *self,
OtkColor *color, XFontStruct *font,
int function, int subwindow, int linewidth);
void OtkGCCacheContext_SetFont(OtkGCCacheContext *self,
XFontStruct *font);
typedef struct OtkGCCacheItem {
OtkGCCacheContext *ctx;
unsigned int count;
unsigned int hits;
Bool fault;
} OtkGCCacheItem;
OtkGCCacheItem *OtkGCCacheItem_New();
typedef struct OtkGCCache {
// this is closely modelled after the Qt GC cache, but with some of the
// complexity stripped out
unsigned int context_count;
unsigned int cache_size;
unsigned int cache_buckets;
unsigned int cache_total_size;
OtkGCCacheContext **contexts;
OtkGCCacheItem **cache;
} OtkGCCache;
void OtkGCCache_Initialize();
//void OtkGCCache_Destroy();
// cleans up the cache
void OtkGCCache_Purge();
OtkGCCacheItem *OtkGCCache_Find(OtkColor *color,
XFontStruct *font, int function,
int subwindow, int linewidth);
void OtkGCCache_Release(OtkGCCacheItem *item);
/*
class BPen {
public:
inline BPen(const BColor &_color, const XFontStruct * const _font = 0,
int _linewidth = 0, int _function = GXcopy,
int _subwindow = ClipByChildren)
: color(_color), font(_font), linewidth(_linewidth), function(_function),
subwindow(_subwindow), cache(OBDisplay::gcCache()), item(0) { }
inline ~BPen(void) { if (item) cache->release(item); }
inline const GC &gc(void) const {
if (! item) item = cache->find(color, font, function, subwindow,
linewidth);
return item->gc();
}
private:
const BColor &color;
const XFontStruct *font;
int linewidth;
int function;
int subwindow;
mutable BGCCache *cache;
mutable BGCCacheItem *item;
};
}*/
#endif // __gccache_h

View file

@ -1,325 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "imagecontrol.h"
#include "timer.h"
#include "screeninfo.h"
#include "display.h"
typedef struct CachedImage {
Pixmap pixmap;
unsigned int count, width, height;
unsigned long pixel1, pixel2, texture;
} CachedImage;
static void timeout(OtkImageControl *self);
static void initColors(OtkImageControl *self, Visual *visual);
PyObject *OtkImageControl_New(int screen)
{
OtkImageControl *self;
int count, i;
XPixmapFormatValues *pmv;
self = PyObject_New(OtkImageControl, &OtkImageControl_Type);
self->screen = OtkDisplay_ScreenInfo(OBDisplay, screen);
self->timer = (OtkTimer*)OtkTimer_New((OtkTimeoutHandler)timeout, self);
self->timer->timeout = 300000;
OtkTimer_Start(self->timer);
self->cache_max = 200;
self->dither = True; // default value
self->cpc = 4; // default value
// get the BPP from the X server
self->bpp = 0;
if ((pmv = XListPixmapFormats(OBDisplay->display, &count))) {
for (i = 0; i < count; i++)
if (pmv[i].depth == self->screen->depth) {
self->bpp = pmv[i].bits_per_pixel;
break;
}
XFree(pmv);
}
if (!self->bpp) self->bpp = self->screen->depth;
if (self->bpp >= 24) self->dither = False; // don't need dither at >= 24 bpp
self->grad_xbuffer = self->grad_ybuffer = NULL;
self->grad_buffer_width = self->grad_buffer_height = 0;
self->sqrt_table = NULL;
initColors(self, self->screen->visual);
return (PyObject*)self;
}
static void initColors(OtkImageControl *self, Visual *visual)
{
// these are not used for !TrueColor
self->red_offset = self->green_offset = self->blue_offset = 0;
// these are not used for TrueColor
self->colors = NULL;
self->ncolors = 0;
// figure out all our color settings based on the visual type
switch (visual->class) {
case TrueColor: {
int i;
unsigned long red_mask, green_mask, blue_mask;
// find the offsets for each color in the visual's masks
red_mask = visual->red_mask;
green_mask = visual->green_mask;
blue_mask = visual->blue_mask;
while (! (red_mask & 1)) { self->red_offset++; red_mask >>= 1; }
while (! (green_mask & 1)) { self->green_offset++; green_mask >>= 1; }
while (! (blue_mask & 1)) { self->blue_offset++; blue_mask >>= 1; }
// use the mask to determine the number of bits for each shade of color
// so, best case, red_mask == 0xff (255), and so each bit is a different
// shade!
self->red_bits = 255 / red_mask;
self->green_bits = 255 / green_mask;
self->blue_bits = 255 / blue_mask;
// compute color tables, based on the number of bits for each shade
for (i = 0; i < 256; i++) {
self->red_color_table[i] = i / self->red_bits;
self->green_color_table[i] = i / self->green_bits;
self->blue_color_table[i] = i / self->blue_bits;
}
break;
}
/*
case PseudoColor:
case StaticColor: {
ncolors = self->cpc * self->cpc * self->cpc; // cpc ^ 3
if (ncolors > (1 << self->screen->depth)) {
self->cpc = (1 << self->screen->depth) / 3;
ncolors = self->cpc * self->cpc * self->cpc; // cpc ^ 3
}
if (self->cpc < 2 || self->ncolors > (1 << self->screen->depth)) {
fprintf(stderr,
"OtkImageControl_New: invalid colormap size %d "
"(%d/%d/%d) - reducing",
self->ncolors, self->cpc, self->cpc, self->cpc);
self->cpc = (1 << self->screen->depth) / 3;
}
self->colors = malloc(sizeof(XColor) * self->ncolors);
if (! self->colors) {
fprintf(stderr, "OtkImageControl_New: error allocating colormap\n");
exit(1);
}
int i = 0, ii, p, r, g, b,
bits = 255 / (colors_per_channel - 1);
red_bits = green_bits = blue_bits = bits;
for (i = 0; i < 256; i++)
red_color_table[i] = green_color_table[i] = blue_color_table[i] =
i / bits;
for (r = 0, i = 0; r < colors_per_channel; r++)
for (g = 0; g < colors_per_channel; g++)
for (b = 0; b < colors_per_channel; b++, i++) {
colors[i].red = (r * 0xffff) / (colors_per_channel - 1);
colors[i].green = (g * 0xffff) / (colors_per_channel - 1);
colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);;
colors[i].flags = DoRed|DoGreen|DoBlue;
}
for (i = 0; i < ncolors; i++) {
if (! XAllocColor(OBDisplay::display, colormap, &colors[i])) {
fprintf(stderr, "couldn't alloc color %i %i %i\n",
colors[i].red, colors[i].green, colors[i].blue);
colors[i].flags = 0;
} else {
colors[i].flags = DoRed|DoGreen|DoBlue;
}
}
XColor icolors[256];
int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth));
for (i = 0; i < incolors; i++)
icolors[i].pixel = i;
XQueryColors(OBDisplay::display, colormap, icolors, incolors);
for (i = 0; i < ncolors; i++) {
if (! colors[i].flags) {
unsigned long chk = 0xffffffff, pixel, close = 0;
p = 2;
while (p--) {
for (ii = 0; ii < incolors; ii++) {
r = (colors[i].red - icolors[i].red) >> 8;
g = (colors[i].green - icolors[i].green) >> 8;
b = (colors[i].blue - icolors[i].blue) >> 8;
pixel = (r * r) + (g * g) + (b * b);
if (pixel < chk) {
chk = pixel;
close = ii;
}
colors[i].red = icolors[close].red;
colors[i].green = icolors[close].green;
colors[i].blue = icolors[close].blue;
if (XAllocColor(OBDisplay::display, colormap,
&colors[i])) {
colors[i].flags = DoRed|DoGreen|DoBlue;
break;
}
}
}
}
}
break;
}
case GrayScale:
case StaticGray: {
if (visual->c_class == StaticGray) {
ncolors = 1 << screen_depth;
} else {
ncolors = colors_per_channel * colors_per_channel * colors_per_channel;
if (ncolors > (1 << screen_depth)) {
colors_per_channel = (1 << screen_depth) / 3;
ncolors =
colors_per_channel * colors_per_channel * colors_per_channel;
}
}
if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) {
fprintf(stderr,
"BImageControl::BImageControl: invalid colormap size %d "
"(%d/%d/%d) - reducing",
ncolors, colors_per_channel, colors_per_channel,
colors_per_channel);
colors_per_channel = (1 << screen_depth) / 3;
}
colors = new XColor[ncolors];
if (! colors) {
fprintf(stderr,
"BImageControl::BImageControl: error allocating colormap\n");
exit(1);
}
int i = 0, ii, p, bits = 255 / (colors_per_channel - 1);
red_bits = green_bits = blue_bits = bits;
for (i = 0; i < 256; i++)
red_color_table[i] = green_color_table[i] = blue_color_table[i] =
i / bits;
for (i = 0; i < ncolors; i++) {
colors[i].red = (i * 0xffff) / (colors_per_channel - 1);
colors[i].green = (i * 0xffff) / (colors_per_channel - 1);
colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);;
colors[i].flags = DoRed|DoGreen|DoBlue;
if (! XAllocColor(OBDisplay::display, colormap,
&colors[i])) {
fprintf(stderr, "couldn't alloc color %i %i %i\n",
colors[i].red, colors[i].green, colors[i].blue);
colors[i].flags = 0;
} else {
colors[i].flags = DoRed|DoGreen|DoBlue;
}
}
XColor icolors[256];
int incolors = (((1 << screen_depth) > 256) ? 256 :
(1 << screen_depth));
for (i = 0; i < incolors; i++)
icolors[i].pixel = i;
XQueryColors(OBDisplay::display, colormap, icolors, incolors);
for (i = 0; i < ncolors; i++) {
if (! colors[i].flags) {
unsigned long chk = 0xffffffff, pixel, close = 0;
p = 2;
while (p--) {
for (ii = 0; ii < incolors; ii++) {
int r = (colors[i].red - icolors[i].red) >> 8;
int g = (colors[i].green - icolors[i].green) >> 8;
int b = (colors[i].blue - icolors[i].blue) >> 8;
pixel = (r * r) + (g * g) + (b * b);
if (pixel < chk) {
chk = pixel;
close = ii;
}
colors[i].red = icolors[close].red;
colors[i].green = icolors[close].green;
colors[i].blue = icolors[close].blue;
if (XAllocColor(OBDisplay::display, colormap,
&colors[i])) {
colors[i].flags = DoRed|DoGreen|DoBlue;
break;
}
}
}
}
}
break;
}
*/
default:
fprintf(stderr, "OtkImageControl: unsupported visual class: %d\n",
visual->class);
exit(1);
}
}
static void timeout(OtkImageControl *self)
{
(void)self;
}
static void otkimagecontrol_dealloc(OtkImageControl* self)
{
Py_DECREF(self->screen);
Py_DECREF(self->timer);
PyObject_Del((PyObject*)self);
}
PyTypeObject OtkImageControl_Type = {
PyObject_HEAD_INIT(NULL)
0,
"OtkImageControl",
sizeof(OtkImageControl),
0,
(destructor)otkimagecontrol_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};

View file

@ -1,115 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __imagecontrol_h
#define __imagecontrol_h
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <Python.h>
struct OtkScreenInfo;
struct OtkTimer;
extern PyTypeObject OtkImageControl_Type;
typedef struct OtkImageControl {
struct OtkScreenInfo *screen;
// for the pixmap cache
struct OtkTimer *timer;
unsigned long cache_max;
Bool dither;
int cpc; // colors-per-channel: must be a value between [2,6]
int bpp; // bits-per-pixel
unsigned int *grad_xbuffer;
unsigned int *grad_ybuffer;
unsigned int grad_buffer_width;
unsigned int grad_buffer_height;
unsigned long *sqrt_table;
// These values are all determined based on a visual
int red_bits; // the number of bits (1-255) that each shade of color
int green_bits; // spans across. best case is 1, which gives 255 shades.
int blue_bits;
unsigned char red_color_table[256];
unsigned char green_color_table[256];
unsigned char blue_color_table[256];
// These are only used for TrueColor visuals
int red_offset; // the offset of each color in a color mask
int green_offset;
int blue_offset;
// These are only used for !TrueColor visuals
XColor *colors;
int ncolors;
} OtkImageControl;
PyObject *OtkImageControl_New(int screen);
/*
inline bool doDither(void) { return dither; }
inline const ScreenInfo* getScreenInfo() const { return screeninfo; }
inline Window getDrawable(void) const { return window; }
inline Visual *getVisual(void) { return screeninfo->visual(); }
inline int getBitsPerPixel(void) const { return bits_per_pixel; }
inline int getDepth(void) const { return screen_depth; }
inline int getColorsPerChannel(void) const
{ return colors_per_channel; }
unsigned long getSqrt(unsigned int x);
Pixmap renderImage(unsigned int width, unsigned int height,
const BTexture &texture);
void installRootColormap(void);
void removeImage(Pixmap pixmap);
void getColorTables(unsigned char **rmt, unsigned char **gmt,
unsigned char **bmt,
int *roff, int *goff, int *boff,
int *rbit, int *gbit, int *bbit);
void getXColorTable(XColor **c, int *n);
void getGradientBuffers(unsigned int w, unsigned int h,
unsigned int **xbuf, unsigned int **ybuf);
void setDither(bool d) { dither = d; }
static void timeout(BImageControl *t);
private:
bool dither;
const ScreenInfo *screeninfo;
OBTimer *timer;
Colormap colormap;
Window window;
XColor *colors;
int colors_per_channel, ncolors, screen_number, screen_depth,
bits_per_pixel, red_offset, green_offset, blue_offset,
red_bits, green_bits, blue_bits;
unsigned char red_color_table[256], green_color_table[256],
blue_color_table[256];
unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width,
grad_buffer_height;
unsigned long *sqrt_table, cache_max;
typedef std::list<CachedImage> CacheContainer;
CacheContainer cache;
Pixmap searchCache(const unsigned int width, const unsigned int height,
const unsigned long texture,
const BColor &c1, const BColor &c2);
};
*/
#endif // __imagecontrol_h

View file

@ -1,41 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "display.h"
#include "screeninfo.h"
#include "color.h"
#include "gccache.h"
#include "font.h"
#include "rect.h"
#include "timer.h"
#include "timerqueue.h"
#include "imagecontrol.h"
#include <X11/Xlib.h>
#include <Python.h>
static PyMethodDef otk_methods[] = {
// {"new_noddy", noddy_new_noddy, METH_VARARGS,
// "Create a new Noddy object."},
{NULL, NULL, 0, NULL}
};
void initotk(char *display)
{
OtkRect_Type.ob_type = &PyType_Type;
OtkDisplay_Type.ob_type = &PyType_Type;
OtkScreenInfo_Type.ob_type = &PyType_Type;
OtkColor_Type.ob_type = &PyType_Type;
OtkFont_Type.ob_type = &PyType_Type;
OtkTimer_Type.ob_type = &PyType_Type;
OtkImageControl_Type.ob_type = &PyType_Type;
Py_InitModule("otk", otk_methods);
OtkTimerQueue_Initialize();
OtkDisplay_Initialize(display);
assert(OBDisplay);
OtkGCCache_Initialize();
OtkFont_Initialize();
}

View file

@ -1,7 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __init_h
#define __init_h
void initotk(char *display);
#endif // __init_h

View file

@ -1,90 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "rect.h"
PyObject *OtkRect_New(int x, int y, int width, int height)
{
OtkRect* self = PyObject_New(OtkRect, &OtkRect_Type);
self->x = x;
self->y = y;
self->width = width;
self->height = height;
return (PyObject*)self;
}
static PyObject *otkrect_getx(OtkRect *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":getX"))
return NULL;
return PyInt_FromLong(self->x);
}
static PyObject *otkrect_gety(OtkRect *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":getY"))
return NULL;
return PyInt_FromLong(self->y);
}
static PyObject *otkrect_getwidth(OtkRect *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":getWidth"))
return NULL;
return PyInt_FromLong(self->width);
}
static PyObject *otkrect_getheight(OtkRect *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":getHeight"))
return NULL;
return PyInt_FromLong(self->height);
}
static PyMethodDef get_methods[] = {
{"getX", (PyCFunction)otkrect_getx, METH_VARARGS,
"Get the X coordinate."},
{"getY", (PyCFunction)otkrect_gety, METH_VARARGS,
"Get the Y coordinate."},
{"getWidth", (PyCFunction)otkrect_getwidth, METH_VARARGS,
"Get the width."},
{"getHeight", (PyCFunction)otkrect_getheight, METH_VARARGS,
"Get the height."},
{NULL, NULL, 0, NULL}
};
static void otkrect_dealloc(PyObject *self)
{
PyObject_Del(self);
}
static PyObject *otkrect_getattr(PyObject *obj, char *name)
{
return Py_FindMethod(get_methods, obj, name);
}
PyTypeObject OtkRect_Type = {
PyObject_HEAD_INIT(NULL)
0,
"OtkRect",
sizeof(OtkRect),
0,
otkrect_dealloc, /*tp_dealloc*/
0, /*tp_print*/
otkrect_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};

View file

@ -1,16 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __rect_h
#define __rect_h
#include <Python.h>
extern PyTypeObject OtkRect_Type;
typedef struct OtkRect {
PyObject_HEAD
int x, y, width, height;
} OtkRect;
PyObject *OtkRect_New(int x, int y, int width, int height);
#endif // __rect_h

View file

@ -1,195 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "screeninfo.h"
#include "display.h"
#include "rect.h"
#include <X11/Xutil.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#include "../src/gettext.h"
extern PyTypeObject OtkScreenInfo_Type;
PyObject *OtkScreenInfo_New(int num)
{
OtkScreenInfo* self;
char *dstr, *dstr2;
int i;
self = PyObject_New(OtkScreenInfo, &OtkScreenInfo_Type);
self->screen = num;
self->root_window = RootWindow(OBDisplay->display, self->screen);
self->rect = (OtkRect*)
OtkRect_New(0, 0, WidthOfScreen(ScreenOfDisplay(OBDisplay->display,
self->screen)),
HeightOfScreen(ScreenOfDisplay(OBDisplay->display,
self->screen)));
/*
If the default depth is at least 8 we will use that,
otherwise we try to find the largest TrueColor visual.
Preference is given to 24 bit over larger depths if 24 bit is an option.
*/
self->depth = DefaultDepth(OBDisplay->display, self->screen);
self->visual = DefaultVisual(OBDisplay->display, self->screen);
self->colormap = DefaultColormap(OBDisplay->display, self->screen);
if (self->depth < 8) {
// search for a TrueColor Visual... if we can't find one...
// we will use the default visual for the screen
XVisualInfo vinfo_template, *vinfo_return;
int vinfo_nitems;
int best = -1;
vinfo_template.screen = self->screen;
vinfo_template.class = TrueColor;
vinfo_return = XGetVisualInfo(OBDisplay->display,
VisualScreenMask | VisualClassMask,
&vinfo_template, &vinfo_nitems);
if (vinfo_return) {
int max_depth = 1;
for (i = 0; i < vinfo_nitems; ++i) {
if (vinfo_return[i].depth > max_depth) {
if (max_depth == 24 && vinfo_return[i].depth > 24)
break; // prefer 24 bit over 32
max_depth = vinfo_return[i].depth;
best = i;
}
}
if (max_depth < self->depth) best = -1;
}
if (best != -1) {
self->depth = vinfo_return[best].depth;
self->visual = vinfo_return[best].visual;
self->colormap = XCreateColormap(OBDisplay->display, self->root_window,
self->visual, AllocNone);
}
XFree(vinfo_return);
}
// get the default display string and strip the screen number
self->display_string = (PyStringObject*)
PyString_FromFormat("DISPLAY=%s",DisplayString(OBDisplay->display));
dstr = PyString_AsString((PyObject*)self->display_string);
dstr2 = strrchr(dstr, '.');
if (dstr2) {
PyObject *str;
_PyString_Resize((PyObject**)&self->display_string, dstr2 - dstr);
str = PyString_FromFormat(".%d", self->screen);
PyString_Concat((PyObject**)&self->display_string, str);
}
#ifdef XINERAMA
self->xinerama_active = False;
if (OtkDisplay->hasXineramaExtensions()) {
if (OtkDisplay->getXineramaMajorVersion() == 1) {
// we know the version 1(.1?) protocol
/*
in this version of Xinerama, we can't query on a per-screen basis, but
in future versions we should be able, so the 'activeness' is checked
on a pre-screen basis anyways.
*/
if (XineramaIsActive(OBDisplay->display)) {
/*
If Xinerama is being used, there there is only going to be one screen
present. We still, of course, want to use the screen class, but that
is why no screen number is used in this function call. There should
never be more than one screen present with Xinerama active.
*/
int num;
XineramaScreenInfo *info = XineramaQueryScreens(OBDisplay->display,
&num);
if (num > 0 && info) {
self->xinerama_areas = PyList_New(num);
for (i = 0; i < num; ++i) {
PyList_SetItem(self->xinerama_areas, i,
OtkRect_New(info[i].x_org, info[i].y_org,
info[i].width, info[i].height));
}
XFree(info);
// if we can't find any xinerama regions, then we act as if it is not
// active, even though it said it was
self->xinerama_active = True;
}
}
}
}
#endif // XINERAMA
return (PyObject*)self;
}
static PyObject *otkscreeninfo_getscreen(OtkScreenInfo* self, PyObject* args)
{
if (!PyArg_ParseTuple(args, ":getScreen"))
return NULL;
return PyInt_FromLong(self->screen);
}
static OtkRect *otkscreeninfo_getrect(OtkScreenInfo* self, PyObject* args)
{
if (!PyArg_ParseTuple(args, ":getRect"))
return NULL;
return self->rect;
}
static PyMethodDef get_methods[] = {
{"getScreen", (PyCFunction)otkscreeninfo_getscreen, METH_VARARGS,
"Get the screen number."},
{"getRect", (PyCFunction)otkscreeninfo_getrect, METH_VARARGS,
"Get the area taken up by the screen."},
{NULL, NULL, 0, NULL}
};
static void otkscreeninfo_dealloc(OtkScreenInfo* self)
{
Py_DECREF(self->display_string);
Py_DECREF(self->rect);
#ifdef XINERAMA
Py_DECREF(self->xinerama_areas);
#endif
PyObject_Del((PyObject*)self);
}
static PyObject *otkscreeninfo_getattr(PyObject *obj, char *name)
{
return Py_FindMethod(get_methods, obj, name);
}
PyTypeObject OtkScreenInfo_Type = {
PyObject_HEAD_INIT(NULL)
0,
"OtkScreenInfo",
sizeof(OtkScreenInfo),
0,
(destructor)otkscreeninfo_dealloc, /*tp_dealloc*/
0, /*tp_print*/
otkscreeninfo_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};

View file

@ -1,36 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __screeninfo_h
#define __screeninfo_h
#include <X11/Xlib.h>
#include <Python.h>
extern PyTypeObject OtkScreenInfo_Type;
struct OtkRect;
typedef struct OtkScreenInfo {
PyObject_HEAD
int screen;
Window root_window;
int depth;
Visual *visual;
Colormap colormap;
PyStringObject *display_string;
struct OtkRect *rect; // OtkRect
#ifdef XINERAMA
PyListObject *xinerama_areas; // holds OtkRect's
Bool xinerama_active;
#endif
} OtkScreenInfo;
//! Creates an OtkScreenInfo for a screen
/*!
@param num The number of the screen on the display for which to fill the
struct with information. Must be a value >= 0.
*/
PyObject *OtkScreenInfo_New(int num);
#endif // __screeninfo_h

View file

@ -1,79 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "timer.h"
#include "timerqueue.h"
PyObject *OtkTimer_New(OtkTimeoutHandler handler, OtkTimeoutData data)
{
OtkTimer *self = PyObject_New(OtkTimer, &OtkTimer_Type);
assert(handler); assert(data);
self->handler = handler;
self->data = data;
self->recur = self->timing = False;
return (PyObject*)self;
}
void OtkTimer_Start(OtkTimer *self)
{
gettimeofday(&(self->start), 0);
self->end.tv_sec = self->start.tv_sec + self->timeout / 1000;
self->end.tv_usec = self->start.tv_usec + self->timeout % 1000 * 1000;
if (! self->timing) {
self->timing = True;
OtkTimerQueue_Add(self);
}
}
void OtkTimer_Stop(OtkTimer *self)
{
if (self->timing) {
self->timing = False;
OtkTimerQueue_Remove(self);
}
}
static void otktimer_dealloc(OtkTimer* self)
{
OtkTimer_Stop(self);
// when this is called, the color has already been cleaned out of the cache
PyObject_Del((PyObject*)self);
}
static int otktimer_compare(OtkTimer *t1, OtkTimer *t2)
{
if (t1->end.tv_sec == t2->end.tv_sec && t1->end.tv_usec == t2->end.tv_usec)
return 0;
else if ((t1->end.tv_sec < t2->end.tv_sec) ||
(t1->end.tv_sec == t2->end.tv_sec &&
t1->end.tv_usec < t2->end.tv_usec))
return -1;
else
return 1;
}
PyTypeObject OtkTimer_Type = {
PyObject_HEAD_INIT(NULL)
0,
"OtkTimer",
sizeof(OtkTimer),
0,
(destructor)otktimer_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc)otktimer_compare, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};

View file

@ -1,52 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __timer_h
#define __timer_h
#include <X11/Xlib.h>
#include <Python.h>
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else // !TIME_WITH_SYS_TIME
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else // !HAVE_SYS_TIME_H
# include <time.h>
# endif // HAVE_SYS_TIME_H
#endif // TIME_WITH_SYS_TIME
extern PyTypeObject OtkTimer_Type;
//! The data passed to the OtkTimeoutHandler function.
/*!
Note: this is a very useful place to put an object instance, and set the
event handler to a static function in the same class.
*/
typedef void *OtkTimeoutData;
//! The type of function which can be set as the callback for an OtkTimer
//! firing
typedef void (*OtkTimeoutHandler)(OtkTimeoutData);
typedef struct OtkTimer {
PyObject_HEAD
OtkTimeoutHandler handler;
OtkTimeoutData data;
Bool recur;
long timeout;
// don't edit these
Bool timing;
struct timeval start;
struct timeval end;
} OtkTimer;
PyObject *OtkTimer_New(OtkTimeoutHandler handler, OtkTimeoutData data);
//! Causes the timer to begin
void OtkTimer_Start(OtkTimer *self);
//! Causes the timer to stop
void OtkTimer_Stop(OtkTimer *self);
#endif // __timer_h

View file

@ -1,98 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#include "../config.h"
#include "timerqueue.h"
#include "display.h"
#include <X11/Xlib.h>
#include <Python.h>
static PyObject *list = NULL; // PyListObject
void OtkTimerQueue_Initialize()
{
list = PyList_New(0);
}
void OtkTimerQueue_Add(OtkTimer* timer)
{
PyList_Append(list, (PyObject*)timer);
PyList_Sort(list);
}
void OtkTimerQueue_Remove(OtkTimer* timer)
{
int index;
index = PySequence_Index(list, (PyObject*)timer);
if (index >= 0)
PySequence_DelItem(list, index);
}
static Bool shouldFire(OtkTimer *timer, const struct timeval *now)
{
return ! ((now->tv_sec < timer->end.tv_sec) ||
(now->tv_sec == timer->end.tv_sec &&
now->tv_usec < timer->end.tv_usec));
}
static void normalizeTimeval(struct timeval *time)
{
while (time->tv_usec < 0) {
if (time->tv_sec > 0) {
--time->tv_sec;
time->tv_usec += 1000000;
} else {
time->tv_usec = 0;
}
}
if (time->tv_usec >= 1000000) {
time->tv_sec += time->tv_usec / 1000000;
time->tv_usec %= 1000000;
}
if (time->tv_sec < 0) time->tv_sec = 0;
}
void OtkTimerQueue_Fire()
{
fd_set rfds;
struct timeval now, tm, *timeout = NULL;
const int xfd = ConnectionNumber(OBDisplay->display);
FD_ZERO(&rfds);
FD_SET(xfd, &rfds); // break on any x events
// check for timer timeout
gettimeofday(&now, 0);
// there is a small chance for deadlock here:
// *IF* the timer list keeps getting refreshed *AND* the time between
// timer->start() and timer->shouldFire() is within the timer's period
// then the timer will keep firing. This should be VERY near impossible.
while (PyList_Size(list)) {
OtkTimer *timer = (OtkTimer*)PyList_GetItem(list, 0);
if (! shouldFire(timer, &now)) {
tm.tv_sec = timer->end.tv_sec - now.tv_sec;
tm.tv_usec = timer->end.tv_usec - now.tv_usec;
normalizeTimeval(&tm);
timeout = &tm; // set the timeout for the select
break; // go on and wait
}
// stop and remove the timer from the queue
PySequence_DelItem(list, 0);
timer->timing = False;
if (timer->handler)
timer->handler(timer->data);
if (timer->recur)
OtkTimer_Start(timer);
}
select(xfd + 1, &rfds, 0, 0, timeout);
}

View file

@ -1,27 +0,0 @@
// -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __timerqueue_h
#define __timerqueue_h
#include "timer.h"
void OtkTimerQueue_Initialize();
//! Will wait for and fire the next timer in the queue.
/*!
The function will stop waiting if an event is received from the X server.
*/
void OtkTimerQueue_Fire();
//! Adds a new timer to the queue
/*!
@param timer An OtkTimer to add to the queue
*/
void OtkTimerQueue_Add(OtkTimer* timer);
//! Removes a timer from the queue
/*!
@param timer An OtkTimer already in the queue to remove
*/
void OtkTimerQueue_Remove(OtkTimer* timer);
#endif // __timerqueue_h