mdg583 0 Newbie Poster

Hello, I am relatively new in python, but I am jumping in and trying some things.

I am working through how to write something like PyPanel, and am starting with PyPanel. The complicated part of that python is being extended by a custom c module, and the c module makes use of Xlib to draw onto a window. Further, the python code is also using the python Xlib modules.

My code - test.c (test.so)

#include <Python.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>



/*---------------------------------------------------------*/
static PyObject * _testline(PyObject *self, PyObject *args) {
/*---------------------------------------------------------*/
    Display *dsp = XOpenDisplay(NULL);
    Window win;
    GC gc;
    XGCValues gcv;
    
    if (!PyArg_ParseTuple(args, "l", &win))
        return NULL;
    
    int scr = DefaultScreen(dsp);
    gc = XCreateGC(dsp, RootWindow(dsp, scr), GCGraphicsExposures, &gcv);
    
    int whiteColor = WhitePixel(dsp, DefaultScreen(dsp));
    
    XSetForeground(dsp, gc, whiteColor);
        
    XDrawLine(dsp, win, gc, 10, 60, 180, 20);
    //XFlush(dsp);
    return Py_BuildValue("i", 1);
}

/*-------------------------------*/
static PyMethodDef TestMethods[] = {
/*-------------------------------*/
    {"testline",    _testline,    METH_VARARGS, "Test Line"},
    {NULL, NULL, 0, NULL}
};

/*----------------------*/
void inittest(void) {
/*----------------------*/    
    Py_InitModule("test", TestMethods);
}

My python code - test.py

#!/usr/local/bin/python -OO
"""

"""

#----------------------------------------------------------------------------                
class Obj(object):
#---------------------------------------------------------------------------- 
    """ Multi-purpose class """
    #----------------------------
    def __init__(self, **kwargs):
    #---------------------------- 
        self.__dict__.update(kwargs)


                                              
#----------------------------------------------------------------------------
#                                  Main
#----------------------------------------------------------------------------
from distutils import sysconfig
from test import testline
from Xlib import X, display, error, Xatom, Xutil
import Xlib.protocol.event
import locale, os, pwd, select, sys, time



#---------------------------------------------------------------------------- 
class testPanel():
#---------------------------------------------------------------------------- 
    #---------------------------
    def __init__(self, display):
    #---------------------------
        self.display = display
        self.screen  = display.screen()          # Screen obj
        self.root    = self.screen.root          # Display root
        self.error   = error.CatchError()        # Error Handler/Suppressor
        self.colors  = {}                        # Alloc'd colors
        self.hidden  = 0                         # Panel hidden/minimized
        self.focus   = 0                         # Currently focused window
        self.rpm     = None                      # Root pixmap ID
        
        self.lgc = self.root.create_gc(foreground=self.getColor("0xece9e2"))
        
        self.window = self.screen.root.create_window(0, 0,
            300, 100, 0, self.screen.root_depth, window_class=X.InputOutput,
            visual=X.CopyFromParent, colormap=X.CopyFromParent, 
            event_mask=(X.ExposureMask|X.ButtonPressMask|X.ButtonReleaseMask|X.EnterWindowMask))
        self.root.change_attributes(event_mask=(X.PropertyChangeMask)) 
        self.window.map()
        
        win = self.window
        
        break_all = False
        
        while 1:
            while self.display.pending_events():
                e = self.display.next_event()
                if e.type == X.Expose and e.count == 0:
                    break_all = True
                    break
            if break_all:
                break_all = False
                break
        
        self.display.flush()

        while 1:


            while self.display.pending_events():
                e = self.display.next_event()
                if e.type == X.ButtonRelease:
                    testline(self.window.id)
                    print("Draw")
                    self.display.flush()
    
    #-------------------------
    def getColor(self, color):
    #-------------------------
        """ Function to get/convert/alloc a color given a single hex str """
        if color in self.colors:
            return self.colors[color]
        else:      
            r = int("0x"+color[2:4],0)*257
            g = int("0x"+color[4:6],0)*257
            b = int("0x"+color[6:8],0)*257
            c = self.screen.default_colormap.alloc_color(r, g, b)
        
            if not c:
                sys.stderr.write("Error allocating color: %s\n" % color)
                return self.screen.white_pixel
            else:
                self.colors[color] = c.pixel
                return c.pixel

#-------------------------
if __name__ == "__main__":
#-------------------------
    src  = None
    dst  = None
        
    # Version check
    main   = 2.4
    config = globals().get("VERSION", None)
    
    # Get the startup delay
    delay  = globals().get("STARTUP_DELAY", None)
    
    # Set locale to user's default
    locale.setlocale(locale.LC_ALL, "")
    
    # If delay is set, pause, and let windowmanager load
    if delay:
	    time.sleep(delay)
	
    testPanel(display.Display())

Basically, the issue is that in my code, there has to be an XFlush(dsp); in the c module in order for it to draw, even if self.display.flush() is called in python right after. I assume this is because the Xlib included in my c module has parallel data to the one included by python's Xlib.

So if someone could give me advice on what's the proper way to have different modules draw onto the same window? Even if I restricted all drawing to c modules, I would still like the possibility of 'extensions' - extra c modules which do their own drawing onto the panel. Could create_resource_object be what I'm looking for? Or would it be better to use a subwindow somehow?

Thanks for any help.