Skip to content

Commit

Permalink
Merge pull request #146 from seebye/drop-python-xlib
Browse files Browse the repository at this point in the history
drop python-xlib
  • Loading branch information
seebye authored Apr 23, 2021
2 parents f5414aa + 11aad51 commit 6c6a795
Show file tree
Hide file tree
Showing 19 changed files with 869 additions and 304 deletions.
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
include ueberzug/lib/lib.sh
include ueberzug/X/*.h
include ueberzug/X/*.c
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Libraries used in the c extension:
- python
- X11
- Xext
- XRes

There are also other direct dependencies,
but they will be installed by pip.
Expand Down
9 changes: 6 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
import distutils.core
import setuptools
import glob

import ueberzug
# To use a consistent encoding
Expand Down Expand Up @@ -34,7 +35,10 @@
},
ext_modules=[
distutils.core.Extension(
"Xshm", ["Xshm/Xshm.c"], libraries=["X11", "Xext"]),
"ueberzug.X",
glob.glob("ueberzug/X/*.c"),
libraries=["X11", "Xext", "XRes"],
include_dirs=["ueberzug/X"]),
],

# Versions should comply with PEP 440:
Expand Down Expand Up @@ -96,8 +100,7 @@
#
# For an analysis of "install_requires" vs pip's requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=['python-xlib', 'pillow', 'docopt',
'attrs>=18.2.0'], # Optional
install_requires=['pillow', 'docopt', 'attrs>=18.2.0'], # Optional
python_requires='>=3.6',

# List additional URLs that are relevant to your project as a dict.
Expand Down
36 changes: 36 additions & 0 deletions ueberzug/X/X.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "python.h"
#include "display.h"
#include "window.h"
#include "Xshm.h"


static PyModuleDef module = {
PyModuleDef_HEAD_INIT,
.m_name = "ueberzug.X",
.m_doc = "Modul which implements the interaction with the Xshm extension.",
.m_size = -1,
};


PyMODINIT_FUNC
PyInit_X(void) {
PyObject *module_instance;
if (PyType_Ready(&DisplayType) < 0 ||
PyType_Ready(&WindowType) < 0 ||
PyType_Ready(&ImageType) < 0) {
return NULL;
}

module_instance = PyModule_Create(&module);
if (module_instance == NULL) {
return NULL;
}

Py_INCREF(&DisplayType);
Py_INCREF(&WindowType);
Py_INCREF(&ImageType);
PyModule_AddObject(module_instance, "Display", (PyObject*)&DisplayType);
PyModule_AddObject(module_instance, "OverlayWindow", (PyObject*)&WindowType);
PyModule_AddObject(module_instance, "Image", (PyObject*)&ImageType);
return module_instance;
}
7 changes: 7 additions & 0 deletions ueberzug/X/X.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef __X_H__
#define __X_H__
#include "python.h"


PyModuleDef module;
#endif
141 changes: 57 additions & 84 deletions Xshm/Xshm.c → ueberzug/X/Xshm.c
Original file line number Diff line number Diff line change
@@ -1,58 +1,38 @@
#define PY_SSIZE_T_CLEAN // Make "s#" use Py_ssize_t rather than int.
#include <Python.h>
#include "python.h"

#include <stdbool.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>

#include "math.h"
#include "util.h"
#include "display.h"

#define INVALID_SHM_ID -1
#define INVALID_SHM_ADDRESS (char*)-1
#define BYTES_PER_PIXEL 4

#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))

#define Py_INIT_ERROR -1
#define Py_INIT_SUCCESS 0

#define __raise(return_value, Exception, message...) { \
char errorMessage[500]; \
snprintf(errorMessage, 500, message); \
PyErr_SetString( \
PyExc_##Exception, \
errorMessage); \
return return_value; \
}
#define raise(Exception, message...) __raise(NULL, Exception, message)
#define raiseInit(Exception, message...) __raise(Py_INIT_ERROR, Exception, message)


static Display* display = NULL;

typedef struct {
PyObject_HEAD
int width;
int height;
int buffer_size;
DisplayObject *display_pyobject;
XShmSegmentInfo segmentInfo;
XImage *image;
} Image;
} ImageObject;

static bool
init_display() {
if (display == NULL) {
display = XOpenDisplay(NULL);
if (display == NULL) {
return false;
}
}

return true;
static inline Display *
get_display(ImageObject *self) {
return self->display_pyobject->event_display;
}

static bool
Image_init_shared_memory(Image *self) {
Image_init_shared_memory(ImageObject *self) {
self->segmentInfo.shmid = shmget(
IPC_PRIVATE,
self->buffer_size,
Expand All @@ -61,7 +41,7 @@ Image_init_shared_memory(Image *self) {
}

static bool
Image_map_shared_memory(Image *self) {
Image_map_shared_memory(ImageObject *self) {
// Map the shared memory segment into the address space of this process
self->segmentInfo.shmaddr = (char*)shmat(self->segmentInfo.shmid, 0, 0);

Expand All @@ -77,7 +57,8 @@ Image_map_shared_memory(Image *self) {
}

static bool
Image_create_shared_image(Image *self) {
Image_create_shared_image(ImageObject *self) {
Display *display = get_display(self);
int screen = XDefaultScreen(display);
// Allocate the memory needed for the XImage structure
self->image = XShmCreateImage(
Expand All @@ -92,44 +73,56 @@ Image_create_shared_image(Image *self) {

// Ask the X server to attach the shared memory segment and sync
XShmAttach(display, &self->segmentInfo);
XSync(display, false);
XFlush(display);
return true;
}
return false;
}

static void
Image_destroy_shared_image(Image *self) {
Image_destroy_shared_image(ImageObject *self) {
if (self->image) {
XShmDetach(display, &self->segmentInfo);
XShmDetach(get_display(self), &self->segmentInfo);
XDestroyImage(self->image);
self->image = NULL;
}
}

static void
Image_free_shared_memory(Image *self) {
Image_free_shared_memory(ImageObject *self) {
if(self->segmentInfo.shmaddr != INVALID_SHM_ADDRESS) {
shmdt(self->segmentInfo.shmaddr);
self->segmentInfo.shmaddr = INVALID_SHM_ADDRESS;
}
}

static void
Image_finalise(ImageObject *self) {
Image_destroy_shared_image(self);
Image_free_shared_memory(self);
Py_CLEAR(self->display_pyobject);
}

static int
Image_init(Image *self, PyObject *args, PyObject *kwds) {
static char *kwlist[] = {"width", "height", NULL};
Image_init(ImageObject *self, PyObject *args, PyObject *kwds) {
static char *kwlist[] = {"display", "width", "height", NULL};
PyObject *display_pyobject;

if (!PyArg_ParseTupleAndKeywords(
args, kwds, "ii", kwlist,
args, kwds, "O!ii", kwlist,
&DisplayType, &display_pyobject,
&self->width, &self->height)) {
return Py_INIT_ERROR;
Py_INIT_RETURN_ERROR;
}

if (self->display_pyobject) {
Image_finalise(self);
}

Py_INCREF(display_pyobject);
self->display_pyobject = (DisplayObject*)display_pyobject;
self->buffer_size = self->width * self->height * BYTES_PER_PIXEL;

if (!init_display()) {
raiseInit(OSError, "could not open a connection to the X server");
}

if (!Image_init_shared_memory(self)) {
raiseInit(OSError, "could not init shared memory");
}
Expand All @@ -143,43 +136,42 @@ Image_init(Image *self, PyObject *args, PyObject *kwds) {
raiseInit(OSError, "could not allocate the XImage structure");
}

return Py_INIT_SUCCESS;
Py_INIT_RETURN_SUCCESS;
}

static void
Image_dealloc(Image *self) {
Image_destroy_shared_image(self);
Image_free_shared_memory(self);
Image_dealloc(ImageObject *self) {
Image_finalise(self);
Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyObject *
Image_copyTo(Image *self, PyObject *args, PyObject *kwds) {
Image_copy_to(ImageObject *self, PyObject *args, PyObject *kwds) {
// draws the image on the surface at x, y
static char *kwlist[] = {"drawable", "x", "y", "width", "height", NULL};
Drawable surface;
GC gc;
int x, y;
int width, height;
unsigned int width, height;
Display *display = get_display(self);

if (!PyArg_ParseTupleAndKeywords(
args, kwds, "liiii", kwlist,
args, kwds, "kiiII", kwlist,
&surface, &x, &y, &width, &height)) {
return NULL;
Py_RETURN_ERROR;
}

gc = XCreateGC(display, surface, 0, NULL);
XShmPutImage(display, surface, gc,
self->image, 0, 0,
x, y, width, height, False);
x, y, width, height, false);
XFreeGC(display, gc);
XSync(display, false);

Py_RETURN_NONE;
}

static PyObject *
Image_draw(Image *self, PyObject *args, PyObject *kwds) {
Image_draw(ImageObject *self, PyObject *args, PyObject *kwds) {
// puts the pixels on the image at x, y
static char *kwlist[] = {"x", "y", "width", "height", "pixels", NULL};
int offset_x, offset_y;
Expand All @@ -195,9 +187,10 @@ Image_draw(Image *self, PyObject *args, PyObject *kwds) {
args, kwds, "iiiis#", kwlist,
&offset_x, &offset_y, &width, &height,
&pixels, &pixels_size)) {
return NULL;
Py_RETURN_ERROR;
}

Py_BEGIN_ALLOW_THREADS
destination_offset_x_bytes = max(0, offset_x) * BYTES_PER_PIXEL;
source_pixels_per_row = width * BYTES_PER_PIXEL;
destination_pixels_per_row = self->width * BYTES_PER_PIXEL;
Expand Down Expand Up @@ -252,12 +245,13 @@ Image_draw(Image *self, PyObject *args, PyObject *kwds) {
memcpy(destination, source, pixels_per_row);
}
}
Py_END_ALLOW_THREADS

Py_RETURN_NONE;
}

static PyMethodDef Image_methods[] = {
{"copy_to", (PyCFunction)Image_copyTo,
{"copy_to", (PyCFunction)Image_copy_to,
METH_VARARGS | METH_KEYWORDS,
"Draws the image on the surface at the passed coordinate.\n"
"\n"
Expand All @@ -282,42 +276,21 @@ static PyMethodDef Image_methods[] = {
{NULL} /* Sentinel */
};

static PyTypeObject ImageType = {
PyTypeObject ImageType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "Xshm.Image",
.tp_name = "ueberzug.X.Image",
.tp_doc =
"An shared memory X11 Image\n"
"\n"
"Args:\n"
" display (ueberzug.X.Display): the X11 display\n"
" width (int): the width of this image\n"
" height (int): the height of this image",
.tp_basicsize = sizeof(Image),
.tp_basicsize = sizeof(ImageObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_new = PyType_GenericNew,
.tp_init = (initproc)Image_init,
.tp_dealloc = (destructor) Image_dealloc,
.tp_methods = Image_methods,
};

static PyModuleDef module = {
PyModuleDef_HEAD_INIT,
.m_name = "Xshm",
.m_doc = "Modul which implements the interaction with the Xshm extension.",
.m_size = -1,
};

PyMODINIT_FUNC
PyInit_Xshm(void) {
PyObject *module_instance;
if (PyType_Ready(&ImageType) < 0)
return NULL;

module_instance = PyModule_Create(&module);
if (module_instance == NULL)
return NULL;

Py_INCREF(&ImageType);
PyModule_AddObject(module_instance, "Image", (PyObject*)&ImageType);
return module_instance;
}
7 changes: 7 additions & 0 deletions ueberzug/X/Xshm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef __XSHM_H__
#define __XSHM_H__
#include "python.h"


PyTypeObject ImageType;
#endif
Loading

0 comments on commit 6c6a795

Please sign in to comment.