Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge commit 'refs/pull/39/head' of github.com:SimonSapin/cairocffi
Conflicts: cairocffi/__init__.py cairocffi/constants.py utils/mkconstants.py
- Loading branch information
Showing
8 changed files
with
305 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
# coding: utf8 | ||
""" | ||
cairocffi.test_xcb | ||
~~~~~~~~~~~~~~~~~~ | ||
Test suite for cairocffi.xcb. | ||
:copyright: Copyright 2014 by Simon Sapin | ||
:license: BSD, see LICENSE for details. | ||
""" | ||
|
||
import os | ||
import time | ||
import xcffib | ||
import xcffib.xproto | ||
from xcffib.xproto import ConfigWindow, CW, EventMask, GC | ||
|
||
import pytest | ||
|
||
from . import Context, XCBSurface | ||
|
||
@pytest.fixture | ||
def xcb_conn(request): | ||
""" | ||
Fixture that will setup and take down a xcffib.Connection object running on | ||
a display spawned by xvfb | ||
""" | ||
display = os.environ.get('DISPLAY') | ||
if display: | ||
conn = xcffib.connect(display) | ||
def teardown_conn(): | ||
conn.disconnect() | ||
else: | ||
pytest.skip('DISPLAY environment variable not set') | ||
|
||
request.addfinalizer(teardown_conn) | ||
return conn | ||
|
||
def find_root_visual(conn): | ||
"""Find the xcffib.xproto.VISUALTYPE corresponding to the root visual""" | ||
default_screen = conn.setup.roots[conn.pref_screen] | ||
for i in default_screen.allowed_depths: | ||
for v in i.visuals: | ||
if v.visual_id == default_screen.root_visual: | ||
return v | ||
|
||
def create_window(conn, width, height): | ||
"""Creates a window of the given dimensions and returns the XID""" | ||
wid = conn.generate_id() | ||
default_screen = conn.setup.roots[conn.pref_screen] | ||
|
||
conn.core.CreateWindow( | ||
default_screen.root_depth, # depth | ||
wid, # id | ||
default_screen.root, # parent | ||
0, 0, width, height, 0, # x, y, w, h, border width | ||
xcffib.xproto.WindowClass.InputOutput, # window class | ||
default_screen.root_visual, # visual | ||
CW.BackPixel | CW.EventMask, # value mask | ||
[ # value list | ||
default_screen.black_pixel, | ||
EventMask.Exposure | EventMask.StructureNotify | ||
] | ||
) | ||
|
||
return wid | ||
|
||
def create_pixmap(conn, wid, width, height): | ||
"""Creates a window of the given dimensions and returns the XID""" | ||
pixmap = conn.generate_id() | ||
default_screen = conn.setup.roots[conn.pref_screen] | ||
|
||
conn.core.CreatePixmap( | ||
default_screen.root_depth, # depth | ||
pixmap, wid, # pixmap id, drawable id (window) | ||
width, height | ||
) | ||
|
||
return pixmap | ||
|
||
def create_gc(conn): | ||
"""Creates a simple graphics context""" | ||
gc = conn.generate_id() | ||
default_screen = conn.setup.roots[conn.pref_screen] | ||
|
||
conn.core.CreateGC( | ||
gc, default_screen.root, # gc id, drawable | ||
GC.Foreground | GC.Background, # value mask | ||
[ # value list | ||
default_screen.black_pixel, | ||
default_screen.white_pixel | ||
] | ||
) | ||
|
||
return gc | ||
|
||
def test_xcb_pixmap(xcb_conn): | ||
width = 10 | ||
height = 10 | ||
|
||
# create a new window | ||
wid = create_window(xcb_conn, width, height) | ||
# create the pixmap used to draw with cairo | ||
pixmap = create_pixmap(xcb_conn, wid, width, height) | ||
# create graphics context to copy pixmap on window | ||
gc = create_gc(xcb_conn) | ||
|
||
# create XCB surface on pixmap | ||
root_visual = find_root_visual(xcb_conn) | ||
surface = XCBSurface(xcb_conn, pixmap, root_visual, width, height) | ||
assert surface | ||
|
||
# use xcb surface to create context, draw white | ||
ctx = Context(surface) | ||
ctx.set_source_rgb(1, 1, 1) | ||
ctx.paint() | ||
|
||
# map the window and wait for it to appear | ||
xcb_conn.core.MapWindow(wid) | ||
xcb_conn.flush() | ||
|
||
start = time.time() | ||
while time.time() < start + 10: | ||
event = xcb_conn.wait_for_event() | ||
if isinstance(event, xcffib.xproto.ExposeEvent): | ||
break | ||
else: | ||
pytest.fail("Never received ExposeEvent") | ||
|
||
# copy the pixmap to the window | ||
xcb_conn.core.CopyArea( | ||
pixmap, # source | ||
wid, # dest | ||
gc, # gc | ||
0, 0, # source x, source y | ||
0, 0, # dest x, dest y | ||
width, height | ||
) | ||
|
||
# flush the connection, make sure no errors were thrown | ||
xcb_conn.flush() | ||
while event: | ||
event = xcb_conn.poll_for_event() | ||
|
||
|
||
def test_xcb_window(xcb_conn): | ||
width = 10 | ||
height = 10 | ||
|
||
# create a new window used to draw with cairo | ||
wid = create_window(xcb_conn, width, height) | ||
|
||
# map the window and wait for it to appear | ||
xcb_conn.core.MapWindow(wid) | ||
xcb_conn.flush() | ||
|
||
start = time.time() | ||
while time.time() < start + 10: | ||
event = xcb_conn.wait_for_event() | ||
if isinstance(event, xcffib.xproto.ExposeEvent): | ||
break | ||
else: | ||
pytest.fail("Never received ExposeEvent") | ||
|
||
# create XCB surface on window | ||
root_visual = find_root_visual(xcb_conn) | ||
surface = XCBSurface(xcb_conn, wid, root_visual, width, height) | ||
assert surface | ||
|
||
# use xcb surface to create context, draw white | ||
ctx = Context(surface) | ||
ctx.set_source_rgb(1, 1, 1) | ||
ctx.paint() | ||
|
||
xcb_conn.flush() | ||
|
||
# now move the window and change its size | ||
xcb_conn.core.ConfigureWindow( | ||
wid, | ||
ConfigWindow.X | ConfigWindow.Y | ConfigWindow.Width | ConfigWindow.Height, | ||
[ | ||
5, 5, # x, y | ||
width * 2, height * 2 # width, height | ||
] | ||
) | ||
xcb_conn.flush() | ||
|
||
# wait for the notification of the size change | ||
start = time.time() | ||
while time.time() < start + 10: | ||
event = xcb_conn.wait_for_event() | ||
|
||
if isinstance(event, xcffib.xproto.ConfigureNotifyEvent): | ||
assert event.width == 2*width | ||
assert event.height == 2*height | ||
width = event.width | ||
height = event.height | ||
break | ||
else: | ||
pytest.fail("Never received ConfigureNotifyEvent") | ||
|
||
# re-size and re-draw the surface | ||
surface.set_size(width, height) | ||
ctx = Context(surface) | ||
ctx.set_source_rgb(1, 1, 1) | ||
ctx.paint() | ||
|
||
# flush the connection, make sure no errors were thrown | ||
xcb_conn.flush() | ||
while event: | ||
event = xcb_conn.poll_for_event() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# coding: utf8 | ||
""" | ||
cairocffi.xcb | ||
~~~~~~~~~~~~~ | ||
Bindings for XCB surface objects using xcffib. | ||
:copyright: Copyright 2014 by Simon Sapin | ||
:license: BSD, see LICENSE for details. | ||
""" | ||
from xcffib import ffi as xcb_ffi, visualtype_to_c_struct | ||
|
||
from . import ffi, dlopen, constants | ||
from .surfaces import Surface, SURFACE_TYPE_TO_CLASS | ||
|
||
ffi.include(xcb_ffi) | ||
ffi.cdef(constants._CAIRO_XCB_HEADERS) | ||
cairo_xcb = dlopen(ffi, 'libcairo.so.2', 'libcairo.2.dylib', 'libcairo-2.dll', | ||
'cairo', 'libcairo-2') | ||
|
||
class XCBSurface(Surface): | ||
"""The XCB surface is used to render cairo graphics to X Window System | ||
windows and pixmaps using the XCB library. | ||
Creates a cairo surface that targets the given drawable (pixmap or window). | ||
.. note:: | ||
This class works using objects and libraries in :mod:`xcffib` | ||
:param conn: The :class:`xcffib.Connection` for an open XCB connection | ||
:param drawable: | ||
An XID corresponding to an XCB drawable (a pixmap or a window) | ||
:param visual: An :class:`xcffib.xproto.VISUALTYPE` object. | ||
:param width: integer | ||
:param height: integer | ||
""" | ||
def __init__(self, conn, drawable, visual, width, height): | ||
c_visual = visualtype_to_c_struct(visual) | ||
|
||
p = cairo_xcb.cairo_xcb_surface_create( | ||
conn._conn, drawable, c_visual, width, height) | ||
Surface.__init__(self, p) | ||
|
||
def set_size(self, width, height): | ||
""" | ||
Informs cairo of the new size of the X Drawable underlying the surface. | ||
For a surface created for a Window (rather than a Pixmap), this | ||
function must be called each time the size of the window changes (for | ||
a subwindow, you are normally resizing the window yourself, but for a | ||
toplevel window, it is necessary to listen for | ||
:class:`xcffib.xproto.ConfigureNotifyEvent`'s). | ||
A Pixmap can never change size, so it is never necessary to call this | ||
function on a surface created for a Pixmap. | ||
:param width: integer | ||
:param height: integer | ||
""" | ||
cairo_xcb.cairo_xcb_surface_set_size(self._pointer, width, height) | ||
self._check_status() | ||
|
||
SURFACE_TYPE_TO_CLASS[constants.SURFACE_TYPE_XCB] = XCBSurface |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,5 +9,6 @@ Documentation | |
overview | ||
api | ||
pixbuf | ||
xcb | ||
cffi_api | ||
changelog |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.. module:: cairocffi.xcb | ||
|
||
Using XCB surfaces with xcffib | ||
============================== | ||
|
||
The :mod:`cairocffi.xcb` module uses xcffib_ as the XCB library to create | ||
graphics for X windows and pixmaps. | ||
|
||
.. autoclass:: XCBSurface | ||
|
||
.. _xcffib: https://github.com/tych0/xcffib/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,4 +37,5 @@ | |
], | ||
packages=find_packages(), | ||
install_requires=['cffi>=0.6'], | ||
extras_require={'xcb': ['xcffib']} | ||
) |