From edc47eb5580babdca6547989c1cb5cdf317f4835 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 20 Dec 2002 22:01:40 +0000 Subject: [PATCH] some experimentin with C and python api. part 1. --- otk_c/Makefile | 25 ++++++ otk_c/display.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++ otk_c/display.h | 61 ++++++++++++++ 3 files changed, 306 insertions(+) create mode 100644 otk_c/Makefile create mode 100644 otk_c/display.c create mode 100644 otk_c/display.h diff --git a/otk_c/Makefile b/otk_c/Makefile new file mode 100644 index 00000000..e4dfe122 --- /dev/null +++ b/otk_c/Makefile @@ -0,0 +1,25 @@ +prefix=/tmp/ob +libdir=$(prefix)/lib + +targets = libotk.so libotk.a +sources = display.c +headers = display.h + +CFLAGS+=-I/usr/gwar/include/python2.2 + +.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 $@ $^ diff --git a/otk_c/display.c b/otk_c/display.c new file mode 100644 index 00000000..ab193437 --- /dev/null +++ b/otk_c/display.c @@ -0,0 +1,220 @@ +// -*- mode: C; indent-tabs-mode: nil; -*- + +#include "display.h" + +#include + +#ifdef SHAPE +#include +#endif // SHAPE + +#ifdef HAVE_STDIO_H +# include +#endif // HAVE_STDIO_H + +#ifdef HAVE_STDLIB_H +# include +#endif // HAVE_STDLIB_H + +#ifdef HAVE_FCNTL_H +# include +#endif // HAVE_FCNTL_H + +#ifdef HAVE_UNISTD_H +# include +# include +#endif // HAVE_UNISTD_H + +#include "../src/gettext.h" + +extern PyTypeObject OtkDisplay_Type; + +static int xerrorHandler(Display *d, XErrorEvent *e); + +PyObject *OtkDisplay_New(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; + + // Get information on all the screens which are available. + self->screenInfoList = PyList_New(ScreenCount(self->display)); + for (i = 0; i < ScreenCount(self->display); ++i) + PyList_Append(self->screenInfoList, OtkScreenInfo_New(i)); + + self->gccache = OtkGCCache_New(PyList_Size(self->screenInfoList)); + + return (PyObject*)self; +} + +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); +} + + + +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); + PyObject_Del(((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; +} diff --git a/otk_c/display.h b/otk_c/display.h new file mode 100644 index 00000000..fd9b706f --- /dev/null +++ b/otk_c/display.h @@ -0,0 +1,61 @@ +// -*- mode: C; indent-tabs-mode: nil; -*- +#ifndef __display_h +#define __display_h + +#include +#include + +typedef OtkScreenInfo; +typedef OtkGCCache; + +typedef struct { + 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 + PyObject *screenInfoList; // PyListObject + + //! A cache for re-using GCs, used by the drawing objects + /*! + @see BPen + @see BFont + @see BImage + @see BImageControl + @see BTexture + */ + OtkGCCache *gccache; +} OtkDisplay; + +//! Creates a struct, opens the X display +/*! + @see OBDisplay::display + @param name The name of the X display to open. If it is null, the DISPLAY + environment variable is used instead. +*/ +PyObject *OtkDisplay_New(char *name); + +//! Grabs the display +void OtkDisplay_Grab(OtkDisplay *self); + +//! Ungrabs the display +void OtkDisplay_Ungrab(OtkDisplay *self); + +#endif // __display_h -- 2.45.2