rm my lucid experiment
This commit is contained in:
parent
58ff3f35c2
commit
6188650ce9
21 changed files with 0 additions and 2183 deletions
|
@ -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 $@ $^
|
212
otk_c/color.c
212
otk_c/color.c
|
@ -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 */
|
||||
};
|
|
@ -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
|
230
otk_c/display.c
230
otk_c/display.c
|
@ -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;
|
||||
}
|
|
@ -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
|
154
otk_c/font.c
154
otk_c/font.c
|
@ -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 */
|
||||
};
|
64
otk_c/font.h
64
otk_c/font.h
|
@ -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
|
234
otk_c/gccache.c
234
otk_c/gccache.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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 */
|
||||
};
|
|
@ -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
|
41
otk_c/init.c
41
otk_c/init.c
|
@ -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();
|
||||
}
|
|
@ -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
|
90
otk_c/rect.c
90
otk_c/rect.c
|
@ -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 */
|
||||
};
|
16
otk_c/rect.h
16
otk_c/rect.h
|
@ -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
|
|
@ -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 */
|
||||
};
|
|
@ -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
|
|
@ -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 */
|
||||
};
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
Loading…
Reference in a new issue