[Xcb-commit] XcbPythonBinding.mdwn
Eamon Walsh
ewalsh at freedesktop.org
Fri Jun 6 12:55:27 PDT 2008
XcbPythonBinding.mdwn | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 167 insertions(+)
New commits:
commit 47275bdc749d4264a17e4d79b4a6b17a421637b9
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Jun 6 15:52:53 2008 -0400
Add wiki page for XCB Python Binding.
diff --git a/XcbPythonBinding.mdwn b/XcbPythonBinding.mdwn
new file mode 100644
index 0000000..0dcf90c
--- /dev/null
+++ b/XcbPythonBinding.mdwn
@@ -0,0 +1,167 @@
+# Introduction
+
+The Python binding for XCB allows the X protocol to be accessed directly from Python. There are two components:
+
+1. A Python extension written in C. This exposes XCB-specific objects and library functions, as well as providing various base classes used by the generated code.
+2. Python modules which are generated directly from the XCB-XML protocol descriptions.
+
+The Python binding requires libxcb.so to work. The additional extension libraries are not required.
+
+
+# Installation
+
+You need a recent version of xcb/proto that includes the Python generator libraries (xcbgen). As of this writing, no official release has been made incorporating this change. Refer to [[DevelopersGuide]] for information on building XCB from source.
+
+In addition to the prereqs for libxcb, described at the link above, you need Python 2.5 installed on the system. Lower versions may work, but have not been tested.
+
+The X Python binding can be obtained from `git://git.freedesktop.org/git/xcb/xpyb`. After cloning the repo, the standard `./autogen.sh; make; make install` should suffice to build and install it.
+
+Note that the Python has a path that it uses when searching for modules to import. This path must include the place where you install the software. For example if you install with a prefix of `/usr/local` then your Python path must include `/usr/local/lib/python2.5/site-packages`. There are at least three ways to accomplish this:
+
+1. Set a `PYTHONPATH` environment variable containing the path.
+2. Create a file with a `.pth` extension, containing the path, in a place that is on the existing path, such as `/usr/lib/python2.5/site-packages`.
+3. In your Python code, do a `sys.path.append(foo)` before you import the XCB modules.
+
+# Usage
+
+The usage model is essentially an object-oriented version of libxcb. Refer to the [[PublicApi]] and [[ProtocolExtensionApi]] documentation for libxcb.
+
+A note on naming: the Python binding does not attempt to do any significant name normalization. This means that XCB library functions retain the lower-case/underscore convention, while X protocol names retain the CamelCase from the XML. Names that are reserved words in Python, such as the words "class", "def", and "None", are prefixed with underscores as necessary. Enum member names consisting of only numbers are treated likewise, e.g. `ButtonMask._1`.
+
+You always need to import `xcb` and `xcb.xproto` at the start of the program. Also import any other extensions you plan on using.
+
+To connect, use:
+
+ conn = xcb.connect(display=':0.0', fd=3, auth='NAME:binary-data')
+
+The arguments are all optional, with display and fd being mutually exclusive. The returned object has attributes and methods corresponding to the various XCB calls:
+
+ conn.pref_screen
+ conn.flush()
+ conn.wait_for_event()
+ conn.generate_id()
+ conn.get_setup()
+
+Et cetera. To make a core protocol request, use the `conn.core` attribute:
+
+ cookie = conn.core.GetInputFocus()
+ reply = cookie.reply()
+
+ cookie = conn.core.CreateWindowChecked(...)
+ cookie.check()
+
+To make an extension protocol request, call the connection object, passing the extension key you want, and use the returned object. For example:
+
+ render = conn(xcb.render.key)
+ cookie = render.FillRectangles(...)
+
+Protocol errors are always thrown as exceptions, with the actual error object available as the first exception argument:
+
+ try:
+ cookie.check()
+ conn.wait_for_event()
+ except xcb.xproto.BadMatch, e:
+ error = e.args[0]
+ print "Bad match on value %d" % error.bad_value
+
+When making a request, any lists or internal sub-structures must be passed as sequences of cardinal values. These lists can contain arbitrary internal nesting. For example:
+
+ color = [ 65535, 0, 0, 65535 ]
+ rectangles = [ (0, 0, 25, 25), (100, 100, 10, 10), (250, 0, 64, 64) ]
+ render.FillRectangles(op, pid, color, 3, rectangles)
+
+Note that the `rects_len` parameter in this case should always be 3, even if the rectangle list is flattened. The length parameter refers to the number of logical elements.
+
+Reply, event, and error objects have attributes corresponding to each structure field. These objects also implement the buffer interface, allowing them to be addressed as raw binary or written to a file as they appear on the wire.
+
+# Full Example
+
+The following complete program creates a window, sets a property, and does some drawing with Render. There is also a basic event loop.
+
+ import xcb
+ from xcb.xproto import *
+ import xcb.render
+
+ def find_format(screen):
+ for d in screen.depths:
+ if d.depth == depth:
+ for v in d.visuals:
+ if v.visual == visual:
+ return v.format
+
+ raise Exception("Failed to find an appropriate Render pictformat!")
+
+
+ def startup():
+ white = setup.roots[0].white_pixel
+
+ conn.core.CreateWindow(depth, window, root,
+ 0, 0, 640, 480, 0,
+ WindowClass.InputOutput,
+ visual,
+ CW.BackPixel | CW.EventMask,
+ [ white, EventMask.ButtonPress | EventMask.EnterWindow | EventMask.LeaveWindow | EventMask.Exposure ])
+
+ cookie = conn.render.QueryPictFormats()
+ reply = cookie.reply()
+ format = find_format(reply.screens[0])
+
+ name = 'X Python Binding Demo'
+ conn.core.ChangeProperty(PropMode.Replace, window, xcb.XA_WM_NAME, xcb.XA_STRING, 8, len(name), name)
+ conn.render.CreatePicture(pid, window, format, 0, [])
+ conn.core.MapWindow(window)
+ conn.flush()
+
+
+ def paint():
+ conn.core.ClearArea(False, window, 0, 0, 0, 0)
+
+ for x in xrange(0, 7):
+ for y in xrange(0, 5):
+ rectangle = ((x + 1) * 24 + x * 64, (y + 1) * 24 + y * 64, 64, 64)
+ color = (x * 65535 / 7, y * 65535 / 5, (x * y) * 65535 / 35, 65535)
+ conn.render.FillRectangles(xcb.render.PictOp.Src, pid, color, 1, rectangle)
+
+ conn.flush()
+
+
+ def run():
+ startup()
+ print 'Click in window to exit.'
+
+ while True:
+ try:
+ event = conn.wait_for_event()
+ except xcb.ProtocolException, error:
+ print "Protocol error %s received!" % error.__class__.__name__
+ break
+ except:
+ print "Unexpected error received: %s" % error.message
+ break
+
+ if isinstance(event, ExposeEvent):
+ paint()
+ elif isinstance(event, EnterNotifyEvent):
+ print 'Enter (%d, %d)' % (event.event_x, event.event_y)
+ elif isinstance(event, LeaveNotifyEvent):
+ print 'Leave (%d, %d)' % (event.event_x, event.event_y)
+ elif isinstance(event, ButtonPressEvent):
+ print 'Button %d down' % event.detail
+ break
+
+ conn.disconnect()
+
+
+
+ conn = xcb.connect()
+ conn.render = conn(xcb.render.key)
+
+ setup = conn.get_setup()
+ root = setup.roots[0].root
+ depth = setup.roots[0].root_depth
+ visual = setup.roots[0].root_visual
+
+ window = conn.generate_id()
+ pid = conn.generate_id()
+
+ run()
More information about the xcb-commit
mailing list