diff --git a/.gitignore b/.gitignore index 14f662baef..3befb7b5ee 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ __pycache__ MANIFEST /build /dist +# complied cffi output +libqtile/_ffi_pango.py +libqtile/_ffi_xcursors.py # Files generated by setup.py qtile.egg-info/ .eggs diff --git a/.travis.yml b/.travis.yml index 03de009626..da6e6205f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,9 +39,11 @@ install: - pip install -r requirements.txt - if [[ ${EVENTLOOP} == "trollius" ]]; then pip install trollius; fi - if [[ ${EVENTLOOP} == "tulip" ]]; then pip install asyncio; fi +# build pangocffi module + - python libqtile/ffi_build.py after_success: - coveralls notifications: - - email: false + email: false diff --git a/MANIFEST.in b/MANIFEST.in index 09a733b72c..238e6e4449 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,3 +3,4 @@ include README.rst recursive-include libqtile/resources * recursive-exclude scripts * recursive-exclude test * +exclude libqtile/_ffi*.py diff --git a/docs/manual/hacking.rst b/docs/manual/hacking.rst index 4468d2ec21..03c999e010 100644 --- a/docs/manual/hacking.rst +++ b/docs/manual/hacking.rst @@ -15,6 +15,19 @@ install them from your package manager. On ubuntu, this can be done with ``sudo apt-get install python-nose xserver-xephyr x11-apps``. +Building cffi module +==================== + +Qtile ships with a small in-tree pangocairo binding built using cffi, +``pangocffi.py``, and also binds to xcursor with cffi. The bindings are not +built at run time and will have to be generated manually when the code is +downloaded or when any changes are made to the cffi library. This can be done +by calling: + +.. code-block:: bash + + python libqtile/ffi_build.py + Using Xephyr and the test suite =============================== diff --git a/libqtile/ffi_build.py b/libqtile/ffi_build.py new file mode 100644 index 0000000000..04b025aa5d --- /dev/null +++ b/libqtile/ffi_build.py @@ -0,0 +1,169 @@ +# Copyright (c) 2014-2015 Sean Vig +# Copyright (c) 2014 roger +# Copyright (c) 2014 Tycho Andersen +# Copyright (c) 2015 Craig Barnes +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from cffi import FFI +from xcffib.ffi_build import ffi as xcffib_ffi +from cairocffi.ffi_build import ffi as cairocffi_ffi + +pango_ffi = FFI() +pango_ffi.set_source("libqtile._ffi_pango", None) + +pango_ffi.include(cairocffi_ffi) + +pango_ffi.cdef(""" + typedef ... PangoContext; + typedef ... PangoLayout; + typedef ... PangoFontDescription; + typedef ... PangoAttrList; + typedef enum { + PANGO_ALIGN_LEFT, + PANGO_ALIGN_CENTER, + PANGO_ALIGN_RIGHT + } PangoAlignment; + typedef enum { + PANGO_ELLIPSEIZE_NONE, + PANGO_ELLIPSIZE_START, + PANGO_ELLIPSIZE_MIDDLE, + PANGO_ELLIPSIZE_END + } PangoEllipsizeMode; + + int + pango_units_from_double (double d); + + typedef void* gpointer; + typedef int gboolean; + typedef unsigned int guint32; + typedef guint32 gunichar; + typedef char gchar; + typedef signed long gssize; + typedef ... GError; + typedef int gint; + + void + pango_cairo_show_layout (cairo_t *cr, + PangoLayout *layout); + + gboolean + pango_parse_markup (const char *markup_text, + int length, + gunichar accel_marker, + PangoAttrList **attr_list, + char **text, + gunichar *accel_char, + GError **error); + + // https://developer.gnome.org/pango/stable/pango-Layout-Objects.html + PangoLayout *pango_cairo_create_layout (cairo_t *cr); + void g_object_unref(gpointer object); + + void + pango_layout_set_font_description (PangoLayout *layout, + const PangoFontDescription *desc); + const PangoFontDescription * + pango_layout_get_font_description (PangoLayout *layout); + + void + pango_layout_set_alignment (PangoLayout *layout, + PangoAlignment alignment); + void + pango_layout_set_attributes (PangoLayout *layout, + PangoAttrList *attrs); + void + pango_layout_set_text (PangoLayout *layout, + const char *text, + int length); + const char * + pango_layout_get_text (PangoLayout *layout); + + void + pango_layout_get_pixel_size (PangoLayout *layout, + int *width, + int *height); + + void + pango_layout_set_width (PangoLayout *layout, + int width); + + void + pango_layout_set_ellipsize (PangoLayout *layout, + PangoEllipsizeMode ellipsize); + + PangoEllipsizeMode + pango_layout_get_ellipsize (PangoLayout *layout); + + // https://developer.gnome.org/pango/stable/pango-Fonts.html#PangoFontDescription + PangoFontDescription *pango_font_description_new (void); + void pango_font_description_free (PangoFontDescription *desc); + + PangoFontDescription * + pango_font_description_from_string (const char *str); + + void + pango_font_description_set_family (PangoFontDescription *desc, + const char *family); + const char * + pango_font_description_get_family (const PangoFontDescription *desc); + + void + pango_font_description_set_absolute_size + (PangoFontDescription *desc, + double size); + void + pango_font_description_set_size (PangoFontDescription *desc, + gint size); + + gint + pango_font_description_get_size (const PangoFontDescription *desc); + + // https://developer.gnome.org/glib/stable/glib-Simple-XML-Subset-Parser.html + gchar * + g_markup_escape_text(const gchar *text, + gssize length); +""") + +xcursors_ffi = FFI() +xcursors_ffi.set_source("libqtile._ffi_xcursors", None) + +xcursors_ffi.include(xcffib_ffi) + +xcursors_ffi.cdef(""" + typedef uint32_t xcb_cursor_t; + typedef struct xcb_cursor_context_t xcb_cursor_context_t; + + int xcb_cursor_context_new( + xcb_connection_t *conn, + xcb_screen_t *screen, + xcb_cursor_context_t **ctx + ); + + xcb_cursor_t xcb_cursor_load_cursor( + xcb_cursor_context_t *ctx, + const char *name + ); + + void xcb_cursor_context_free(xcb_cursor_context_t *ctx); +""") + +if __name__ == "__main__": + pango_ffi.compile() + xcursors_ffi.compile() diff --git a/libqtile/pangocffi.py b/libqtile/pangocffi.py index 21e982339b..fcf605e1a2 100644 --- a/libqtile/pangocffi.py +++ b/libqtile/pangocffi.py @@ -46,134 +46,12 @@ # # This is not intended to be a complete cffi-based pango binding. -from __future__ import print_function - -from cffi import FFI -import xcffib -import cairocffi - import six +from libqtile._ffi_pango import ffi -ffi = FFI() - -ffi.include(xcffib.ffi) -ffi.include(cairocffi.ffi) - -# pango/pangocairo -ffi.cdef(""" - typedef ... PangoContext; - typedef ... PangoLayout; - typedef ... PangoFontDescription; - typedef ... PangoAttrList; - typedef enum { - PANGO_ALIGN_LEFT, - PANGO_ALIGN_CENTER, - PANGO_ALIGN_RIGHT - } PangoAlignment; - typedef enum { - PANGO_ELLIPSEIZE_NONE, - PANGO_ELLIPSIZE_START, - PANGO_ELLIPSIZE_MIDDLE, - PANGO_ELLIPSIZE_END - } PangoEllipsizeMode; - - int - pango_units_from_double (double d); - - typedef void* gpointer; - typedef int gboolean; - typedef unsigned int guint32; - typedef guint32 gunichar; - typedef char gchar; - typedef signed long gssize; - typedef ... GError; - typedef int gint; - - void - pango_cairo_show_layout (cairo_t *cr, - PangoLayout *layout); - - gboolean - pango_parse_markup (const char *markup_text, - int length, - gunichar accel_marker, - PangoAttrList **attr_list, - char **text, - gunichar *accel_char, - GError **error); - - // https://developer.gnome.org/pango/stable/pango-Layout-Objects.html - PangoLayout *pango_cairo_create_layout (cairo_t *cr); - void g_object_unref(gpointer object); - - void - pango_layout_set_font_description (PangoLayout *layout, - const PangoFontDescription *desc); - const PangoFontDescription * - pango_layout_get_font_description (PangoLayout *layout); - - void - pango_layout_set_alignment (PangoLayout *layout, - PangoAlignment alignment); - void - pango_layout_set_attributes (PangoLayout *layout, - PangoAttrList *attrs); - void - pango_layout_set_text (PangoLayout *layout, - const char *text, - int length); - const char * - pango_layout_get_text (PangoLayout *layout); - - void - pango_layout_get_pixel_size (PangoLayout *layout, - int *width, - int *height); - - void - pango_layout_set_width (PangoLayout *layout, - int width); - - void - pango_layout_set_ellipsize (PangoLayout *layout, - PangoEllipsizeMode ellipsize); - - PangoEllipsizeMode - pango_layout_get_ellipsize (PangoLayout *layout); - - // https://developer.gnome.org/pango/stable/pango-Fonts.html#PangoFontDescription - PangoFontDescription *pango_font_description_new (void); - void pango_font_description_free (PangoFontDescription *desc); - - PangoFontDescription * - pango_font_description_from_string (const char *str); - - void - pango_font_description_set_family (PangoFontDescription *desc, - const char *family); - const char * - pango_font_description_get_family (const PangoFontDescription *desc); - - void - pango_font_description_set_absolute_size - (PangoFontDescription *desc, - double size); - void - pango_font_description_set_size (PangoFontDescription *desc, - gint size); - - gint - pango_font_description_get_size (const PangoFontDescription *desc); - - // https://developer.gnome.org/glib/stable/glib-Simple-XML-Subset-Parser.html - gchar * - g_markup_escape_text(const gchar *text, - gssize length); -""") - -gobject = ffi.dlopen('gobject-2.0') -pango = ffi.dlopen('pango-1.0') -pangocairo = ffi.dlopen('pangocairo-1.0') +gobject = ffi.dlopen('libgobject-2.0.so') +pango = ffi.dlopen('libpango-1.0.so') +pangocairo = ffi.dlopen('libpangocairo-1.0.so') def CairoContext(cairo_t): diff --git a/libqtile/xcursors.py b/libqtile/xcursors.py index a6b389d564..742564d0ed 100644 --- a/libqtile/xcursors.py +++ b/libqtile/xcursors.py @@ -1,27 +1,6 @@ from logging import getLogger -import xcffib -from cffi import FFI -ffi = FFI() - -ffi.include(xcffib.ffi) -ffi.cdef(""" - typedef uint32_t xcb_cursor_t; - typedef struct xcb_cursor_context_t xcb_cursor_context_t; - - int xcb_cursor_context_new( - xcb_connection_t *conn, - xcb_screen_t *screen, - xcb_cursor_context_t **ctx - ); - - xcb_cursor_t xcb_cursor_load_cursor( - xcb_cursor_context_t *ctx, - const char *name - ); - - void xcb_cursor_context_free(xcb_cursor_context_t *ctx); -""") +from ._ffi_xcursors import ffi # Stolen from samurai-x @@ -124,7 +103,7 @@ def __init__(self, conn): def _setup_xcursor_binding(self): try: - xcursor = ffi.dlopen('xcb-cursor') + xcursor = ffi.dlopen('libxcb-cursor.so') except OSError: self.log.warning("xcb-cursor not found, fallback to font pointer") return False diff --git a/requirements.txt b/requirements.txt index 4af836179b..33a8a2a738 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -cairocffi>=0.6 -cffi>=0.8.2,<1.0.0 +cairocffi>=0.7 +cffi>=1.1 flake8 nose-cov python-coveralls six -xcffib>=0.2.5,<0.3.0 +xcffib>=0.3.0 diff --git a/setup.py b/setup.py index 4f443d2950..48759970cc 100755 --- a/setup.py +++ b/setup.py @@ -51,7 +51,7 @@ unit-tested window mangers around. """ -dependencies = ['cairocffi>=0.6', 'cffi>=0.8.2,<1', 'six>=1.4.1', 'xcffib>=0.2.5,<3'] +dependencies = ['xcffib>=0.3.2', 'cairocffi>=0.7[xcb]', 'cffi>=1.1.0', 'six>=1.4.1'] if sys.version_info >= (3, 4): pass @@ -90,6 +90,10 @@ 'libqtile.resources' ], package_data={'libqtile.resources': ['battery-icons/*.png']}, + cffi_modules=[ + 'libqtile/ffi_build.py:pango_ffi', + 'libqtile/ffi_build.py:xcursors_ffi' + ], scripts=[ "bin/qsh", "bin/qtile", diff --git a/test/flake8.cfg b/test/flake8.cfg index 5f28e7bfde..4b67003f64 100644 --- a/test/flake8.cfg +++ b/test/flake8.cfg @@ -4,3 +4,4 @@ # E128 continuation line under-indented for visual indent [flake8] ignore = E301,E302,E501,E128 +exclude = libqtile/_ffi*.py