From e5c5b4bf700f9bf00dd88bd4b6a471ac1ccefaff Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 20 Dec 2002 23:19:07 +0000 Subject: [PATCH] add screeninfo --- otk_c/Makefile | 4 +- otk_c/display.c | 4 +- otk_c/display.h | 11 ++- otk_c/rect.h | 5 ++ otk_c/screeninfo.c | 195 +++++++++++++++++++++++++++++++++++++++++++++ otk_c/screeninfo.h | 31 +++++++ 6 files changed, 243 insertions(+), 7 deletions(-) create mode 100644 otk_c/rect.h create mode 100644 otk_c/screeninfo.c create mode 100644 otk_c/screeninfo.h diff --git a/otk_c/Makefile b/otk_c/Makefile index f84be310..28c1488a 100644 --- a/otk_c/Makefile +++ b/otk_c/Makefile @@ -3,8 +3,8 @@ exec_prefix=$(prefix) libdir=$(exec_prefix)/lib targets = libotk.so libotk.a -sources = display.c -headers = display.h +sources = display.c screeninfo.c +headers = display.h screeninfo.h CFLAGS+=-I/usr/gwar/include/python2.2 diff --git a/otk_c/display.c b/otk_c/display.c index ab193437..85965210 100644 --- a/otk_c/display.c +++ b/otk_c/display.c @@ -1,6 +1,8 @@ // -*- mode: C; indent-tabs-mode: nil; -*- +#include "../config.h" #include "display.h" +#include "screeninfo.h" #include @@ -118,7 +120,7 @@ line argument.\n\n")); // 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)); + PyList_SetItem(self->screenInfoList, i, OtkScreenInfo_New(i)); self->gccache = OtkGCCache_New(PyList_Size(self->screenInfoList)); diff --git a/otk_c/display.h b/otk_c/display.h index fd9b706f..87574b76 100644 --- a/otk_c/display.h +++ b/otk_c/display.h @@ -5,10 +5,13 @@ #include #include -typedef OtkScreenInfo; -typedef OtkGCCache; +struct OtkScreenInfo; +struct OtkGCCache; +struct OtkDisplay; -typedef struct { +struct OtkDisplay *OBDisplay; // the global display XXX: move this to app.h and ob.h? + +typedef struct OtkDisplay { PyObject_HEAD //! The X display @@ -41,7 +44,7 @@ typedef struct { @see BImageControl @see BTexture */ - OtkGCCache *gccache; + struct OtkGCCache *gccache; } OtkDisplay; //! Creates a struct, opens the X display diff --git a/otk_c/rect.h b/otk_c/rect.h new file mode 100644 index 00000000..4d08828c --- /dev/null +++ b/otk_c/rect.h @@ -0,0 +1,5 @@ +typedef struct { + int x, y, width, height; +} OtkRect; + +PyObject *OtkRect_New(int x, int y, int width, int height); diff --git a/otk_c/screeninfo.c b/otk_c/screeninfo.c new file mode 100644 index 00000000..0153d7f7 --- /dev/null +++ b/otk_c/screeninfo.c @@ -0,0 +1,195 @@ +// -*- mode: C; indent-tabs-mode: nil; -*- + +#include "../config.h" +#include "screeninfo.h" +#include "display.h" +#include "rect.h" + +#include + +#ifdef HAVE_STRING_H +# include +#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_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 = + PyString_FromFormat("DISPLAY=%s",DisplayString(OBDisplay->display)); + dstr = PyString_AsString(self->display_string); + dstr2 = strrchr(dstr, '.'); + if (dstr2) { + PyObject *str; + + PyString_Resize(self->display_string, dstr2 - dstr); + str = PyString_FromFormat(".%d", self->screen); + PyString_Concat(&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 PyObject *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(PyObject* self) +{ + PyObject_Del(((OtkScreenInfo*) self)->display_string); + PyObject_Del(((OtkScreenInfo*) self)->rect); +#ifdef XINERAMA + PyObject_Del(((OtkScreenInfo*) self)->xinerama_areas); +#endif + PyObject_Del(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, + 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 */ +}; diff --git a/otk_c/screeninfo.h b/otk_c/screeninfo.h new file mode 100644 index 00000000..5114a37c --- /dev/null +++ b/otk_c/screeninfo.h @@ -0,0 +1,31 @@ +// -*- mode: C; indent-tabs-mode: nil; -*- +#ifndef __screeninfo_h +#define __screeninfo_h + +#include +#include + +typedef struct OtkScreenInfo { + int screen; + Window root_window; + + int depth; + Visual *visual; + Colormap colormap; + + PyObject *display_string; // PyStringObject + PyObject *rect; // OtkRect +#ifdef XINERAMA + PyObject *xinerama_areas; // PyListObject[OtkRect] + 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 -- 2.39.2