diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..6ff3f52068bc2566b4ff0bb49a012d7bee05c5f7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM debian:sid-slim +RUN apt-get update +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y flatpak-builder +RUN useradd -mUd /var/lib/builder builder +USER builder +WORKDIR /var/lib/builder diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9d11c45474d15ad4f3bc57d5585fb4b576da8ad9 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Flatpak in Docker example + +> An example of building a Flatpak inside a Docker container + +## Scenario + +An Ubuntu Xenial instance running the HWE kernel (from the +`linux-virtual-hwe-16.04` package, version 4.15 at the time of writing) and +Docker from the `docker.io` package in the Ubuntu repos (version 18.09 at the +time of writing). + +## Example + +To build the container and run it: + +``` +docker build -t flatpak-builder https://raw.githubusercontent.com/adarnimrod/flatpak-docker-example/master/Dockerfile +docker run -it --security-opt seccomp=unconfined --security-opt apparmor=unconfined -v '/proc:/proc' -v '/var/cache/flatpak:/var/lib/builder/.local/share/flatpak' flatpak-builder +``` + +To pull the dependencies and build the Endless SDK inside the container: + +``` +flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo +for dep in org.freedesktop.Sdk/x86_64/1.6 org.freedesktop.Platform/x86_64/1.6 org.gnome.Sdk/x86_64/3.28 org.gnome.Sdk.Debug/x86_64/3.28 org.gnome.Sdk.Docs/x86_64/3.28 org.gnome.Platform/x86_64/3.28 ; do \ + flatpak install -y --user flathub $dep ; \ + flatpak update -y --user $dep ; \ +done +flatpak list --user --runtime --show-details +for dep in org.gnome.Platform.Locale/x86_64/3.28 org.gnome.Sdk.Locale/x86_64/3.28 ; do \ + flatpak uninstall -y --user $dep || true ; \ + flatpak install -y --user --reinstall flathub $dep ; \ +done +flatpak install --user flathub org.gnome.Sdk.Debug +flatpak list --user --runtime --all --show-details + +flatpak-builder --verbose --disable-rofiles-fuse --from-git=https://github.com/adarnimrod/flatpak-docker-example builddir com.endlessm.apps.Sdk.json +``` diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000000000000000000000000000000000000..9aae5503993450d66432fc87d25e57c4459adafe --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure("2") do |config| + config.vm.box = "ubuntu/xenial64" + config.disksize.size = "64GB" + config.vm.provision "shell", inline: <<-SHELL + apt-get update + apt-get install -y linux-virtual-hwe-16.04 docker.io + usermod -aG docker vagrant + install -d -m 777 -o root -g root /var/cache/flatpak + systemctl reboot + SHELL +end diff --git a/com.endlessm.apps.Platform.appdata.xml b/com.endlessm.apps.Platform.appdata.xml new file mode 100644 index 0000000000000000000000000000000000000000..865223dcfa4c3d1848d0f1b2e88dc19a12f47bd4 --- /dev/null +++ b/com.endlessm.apps.Platform.appdata.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright 2017 Endless --> +<component type="runtime"> + <id>com.endlessm.apps.Platform</id> + <metadata_license>CC0</metadata_license> + <!-- FIXME --> + <project_license>LGPL-2.1+</project_license> + <name>Endless Application Platform version master</name> + <summary>Shared libraries used by Endless applications</summary> + <url type="homepage">https://endlessos.com/</url> +</component> + diff --git a/com.endlessm.apps.Sdk.appdata.xml b/com.endlessm.apps.Sdk.appdata.xml new file mode 100644 index 0000000000000000000000000000000000000000..80a79c2d7b2f5d744413abc68cc7b759d0040ef8 --- /dev/null +++ b/com.endlessm.apps.Sdk.appdata.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright 2017 Endless --> +<component type="runtime"> + <id>com.endlessm.apps.Sdk</id> + <metadata_license>CC0</metadata_license> + <!-- FIXME --> + <project_license>LGPL-2.1+</project_license> + <name>Endless Software Development Kit version master</name> + <summary>Tools and headers for developing applications using the Endless application platform</summary> + <url type="homepage">https://endlessos.com/</url> +</component> + diff --git a/com.endlessm.apps.Sdk.json b/com.endlessm.apps.Sdk.json new file mode 100644 index 0000000000000000000000000000000000000000..dd441bd2755fbe731dcf220bc0b6c98a0607ec3e --- /dev/null +++ b/com.endlessm.apps.Sdk.json @@ -0,0 +1,761 @@ +{ + "build-runtime": true, + "id": "com.endlessm.apps.Sdk", + "id-platform": "com.endlessm.apps.Platform", + "branch": "master", + "runtime": "org.gnome.Platform", + "sdk": "org.gnome.Sdk", + "runtime-version": "3.28", + "sdk-extensions": [ + "org.gnome.Sdk.Debug", + "org.gnome.Sdk.Docs", + "org.gnome.Sdk.Locale" + ], + "platform-extensions": [ + "org.gnome.Platform.Locale" + ], + "inherit-extensions": [ + "org.freedesktop.Platform.GL", + "org.freedesktop.Platform.Timezones", + "org.freedesktop.Platform.GStreamer", + "org.freedesktop.Platform.Icontheme", + "org.freedesktop.Platform.VAAPI.Intel", + "org.freedesktop.Sdk.Extension" + ], + "add-extensions": { + "org.gnome.Sdk.Docs": { + "version": "3.28", + "directory": "share/runtime/docs", + "bundle": true, + "autodelete": true, + "no-autodownload": true + } + }, + "finish-args": [ + "--env=GI_TYPELIB_PATH=/app/lib/girepository-1.0", + "--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0:/usr/lib/extensions/gstreamer-1.0:/usr/lib/gstreamer-1.0", + "--env=XDG_DATA_DIRS=/app/share:/usr/share:/usr/share/runtime/share:/run/host/share", + "--sdk=com.endlessm.apps.Sdk//master", + "--runtime=com.endlessm.apps.Platform//master" + ], + "cleanup": [ + "/man", + "/share/man", + "/lib/systemd", + "*.la", + "*.a" + ], + "cleanup-commands": [ + "update-desktop-database", + "/usr/libexec/freedesktop-post.sh" + ], + "cleanup-platform": [ + "/include", + "/share/aclocal", + "/share/pkgconfig", + "/lib/pkgconfig", + "/share/gir-1.0", + "/share/vala" + ], + "cleanup-platform-commands": [ + "/usr/libexec/freedesktop-post.sh" + ], + "build-options": { + "cflags": "-O2 -g", + "cxxflags": "-O2 -g", + "env": { + "V": "1" + } + }, + "modules": [ + { + "name": "gtk3", + "config-opts": [ + "--enable-xkb", + "--enable-xinerama", + "--enable-xrandr", + "--enable-xfixes", + "--enable-xcomposite", + "--enable-xdamage", + "--enable-x11-backend", + "--enable-wayland-backend" + ], + "cleanup-platform": [ + "/bin/gtk3-*", + "/bin/gtk-builder-tool", + "/bin/gtk-encode-symbolic-svg" + ], + "sources": [ + { + "type": "archive", + "url": "https://download.gnome.org/sources/gtk+/3.22/gtk+-3.22.30.tar.xz", + "sha256": "a1a4a5c12703d4e1ccda28333b87ff462741dc365131fbc94c218ae81d9a6567" + }, + { + "type": "shell", + "commands": [ + "rm gtk/gtkmarshalers.c gtk/gtkmarshalers.h" + ] + }, + { + "type": "patch", + "path": "gtk3-fix-atk-gjs-crash.patch" + }, + { + "type": "patch", + "path": "gtk3-CSS-eos-cairo-filter-property.patch" + } + ], + "rm-configure": true, + "ensure-writable": [ + "/lib/gtk-3.0/3.0.0/immodules.cache" + ] + }, + { + "name": "python-polib", + "no-autogen": true, + "ensure-writable": [ + "/lib/python*/site-packages/easy-install.pth" + ], + "cleanup-platform": [ + "*" + ], + "build-options": { + "env": { + "PYTHON": "/usr/bin/python3" + } + }, + "sources": [ + { + "type": "archive", + "url": "https://pypi.python.org/packages/fb/64/ad3dbcc052d92fedd535a80b9866a9334afaf136cb5d89a673ac36d16b5a/polib-1.0.8.tar.gz#md5=4e7c8a8e6851279ebb7c5813ca48d452", + "sha256": "5affe3d915eb5b4773f4ce164817e383eea0306115cdaf9b64008b3aea8202df" + }, + { + "type": "file", + "path": "polib-makefile", + "dest-filename": "Makefile" + } + ] + }, + { + "name": "python-dbus", + "cleanup-platform": [ + "*" + ], + "buildsystem": "simple", + "build-commands": [ + "pip3 install --no-index --find-links \"file://${PWD}\" dbus-python" + ], + "sources": [ + { + "type": "file", + "url": "https://pypi.python.org/packages/ad/1b/76adc363212c642cabbf9329457a918308c0b9b5d38ce04d541a67255174/dbus-python-1.2.4.tar.gz", + "sha256": "e2f1d6871f74fba23652e51d10873e54f71adab0525833c19bad9e99b1b2f9cc" + } + ] + }, + { + "name": "python-dbusmock", + "cleanup-platform": [ + "*" + ], + "buildsystem": "simple", + "build-commands": [ + "pip3 install --no-index --find-links \"file://${PWD}\" python-dbusmock" + ], + "sources": [ + { + "type": "file", + "url": "https://pypi.python.org/packages/4d/cd/a5f571ef37addb45a86eca2e66a6b4789d915dbb9170a997dba02b7a0a89/python-dbusmock-0.17.tar.gz", + "sha256": "58f802ef4c659a1adbca31eb6c26688f1c09599b5832354eb258340b66673346" + } + ] + }, + { + "name": "libyaml", + "sources": [ + { + "type": "archive", + "url": "https://github.com/yaml/libyaml/archive/0.1.7.tar.gz", + "sha256": "e1884d0fa1eec8cf869ac6bebbf25391e81956aa2970267f974a9fa5e0b968e2" + } + ] + }, + { + "name": "python3-pyyaml", + "no-autogen": true, + "build-options": { + "env": { + "PYTHON": "/usr/bin/python3" + } + }, + "sources": [ + { + "type": "archive", + "url": "http://pyyaml.org/download/pyyaml/PyYAML-3.12.tar.gz", + "sha256": "592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab" + }, + { + "type": "file", + "path": "setuptools-makefile", + "dest-filename": "Makefile" + } + ] + }, + { + "name": "tcl", + "no-autogen": true, + "cleanup": [ + "*" + ], + "builddir": false, + "subdir": "unix", + "config-opts": [ + "--disable-symbols" + ], + "sources": [ + { + "type": "archive", + "url": "https://sunsite.icm.edu.pl/pub/programming/tcl/tcl8_6/tcl8.6.6-src.tar.gz", + "sha256": "a265409781e4b3edcc4ef822533071b34c3dc6790b893963809b9fe221befe07" + }, + { + "type": "patch", + "path": "tcl-no-docs.patch" + } + ], + "post-install": [ + "chmod 0755 /usr/lib/libtcl8.6.so", + "ln -sfr /usr/bin/tclsh8.6 /usr/bin/tclsh" + ] + }, + { + "name": "eos-metrics", + "config-opts": [ + "--disable-gtk-doc", + "--disable-gir-doc" + ], + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/eos-metrics" + } + ] + }, + { + "name": "xapian-core", + "builddir": false, + "build-options": { + "config-opts": [ + "--enable-maintainer-mode", + "--disable-documentation" + ], + "arch": { + "arm": { + "cxxflags": "-O2 -g -Wno-error=cast-align" + } + } + }, + "sources": [ + { + "type": "git", + "url": "https://git.xapian.org/xapian", + "commit": "6851942c7820b410679e68a92fad55325c7164ef" + }, + { + "type": "shell", + "commands": [ + "./bootstrap --download-tools=never xapian-core" + ] + } + ] + }, + { + "name": "xapian-glib", + "buildsystem": "meson", + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/xapian-glib" + } + ] + }, + { + "name": "jasmine-gjs", + "cleanup-platform": [ + "*" + ], + "sources": [ + { + "type": "git", + "url": "https://github.com/ptomato/jasmine-gjs" + } + ] + }, + { + "name": "eos-sdk", + "build-options": { + "env": { + "PYTHON": "python3" + }, + "config-opts": [ + "--disable-gtk-doc", + "--disable-gir-doc", + "--disable-js-doc", + "--disable-webhelper" + ] + }, + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/eos-sdk" + } + ] + }, + { + "name": "libsass", + "sources": [ + { + "type": "archive", + "url": "https://github.com/sass/libsass/archive/3.4.4.tar.gz", + "sha256": "1dc4d49a9a53b891b7e98935709e625f1d68782d87aef4304a41e6d590abb480" + }, + { + "type": "shell", + "commands": [ + "autoreconf --verbose --force --install" + ] + } + ] + }, + { + "name": "sassc", + "sources": [ + { + "type": "archive", + "url": "https://github.com/sass/sassc/archive/3.4.2.tar.gz", + "sha256": "ad805f2d404d17cf2980c8079a7413cd58d2f2085120167997b85420a722e079" + }, + { + "type": "shell", + "commands": [ + "autoreconf --verbose --force --install" + ] + } + ] + }, + { + "name": "eos-shard", + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/eos-shard.git" + } + ] + }, + { + "name": "libdmodel", + "buildsystem": "meson", + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/libdmodel.git" + } + ] + }, + { + "name": "basin", + "cleanup-platform": [ + "/bin/basin", + "/bin/basin-helper", + "/bin/basin-processor", + "/share/basin" + ], + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/basin.git" + } + ] + }, + { + "name": "mathjax-js", + "no-autogen": true, + "sources": [ + { + "type": "archive", + "url": "https://github.com/mathjax/MathJax/archive/2.4.0.tar.gz", + "sha256": "cd7175e1e352793942a976bf40692b954b5169bd28533921a8a8dd4ec865d855" + }, + { + "type": "file", + "path": "mathjax-makefile", + "dest-filename": "Makefile" + } + ] + }, + { + "name": "appstream", + "builddir": true, + "buildsystem": "cmake", + "build-options": { + "config-opts": [ + "-DCMAKE_INSTALL_LIBDIR=/usr/lib", + "-DQT=OFF", + "-DAPT_SUPPORT=ON", + "-DVAPI=OFF", + "-DSTEMMING=OFF" + ] + }, + "sources": [ + { + "type": "archive", + "url": "https://github.com/ximion/appstream/archive/APPSTREAM_0_10_4.tar.gz", + "sha256": "0f506ef1146d2bc96c9215368de7e3248a110f4a8b90c6cc80cfe058e9abe33e" + }, + { + "type": "patch", + "path": "endless-appstream-cache.patch" + }, + { + "type": "patch", + "path": "endless-appstream-no-docs.patch" + } + ] + }, + { + "name": "emeus", + "buildsystem": "meson", + "builddir": true, + "build-options": { + "config-opts": [ + "--libdir=/usr/lib", + "-Denable-gtk-doc=false" + ] + }, + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/emeus.git" + } + ] + }, + { + "name": "maxwell", + "buildsystem": "meson", + "builddir": true, + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/maxwell.git" + } + ] + }, + { + "name": "popplerdata", + "no-autogen": true, + "make-install-args": [ + "prefix=/usr" + ], + "sources": [ + { + "type": "archive", + "url": "https://poppler.freedesktop.org/poppler-data-0.4.8.tar.gz", + "sha256": "1096a18161f263cccdc6d8a2eb5548c41ff8fcf9a3609243f1b6296abdf72872" + } + ] + }, + { + "name": "poppler", + "config-opts": [ + "--enable-libopenjpeg=none" + ], + "cleanup": [ + "/bin" + ], + "sources": [ + { + "type": "archive", + "url": "https://poppler.freedesktop.org/poppler-0.59.0.tar.xz", + "sha256": "a3d626b24cd14efa9864e12584b22c9c32f51c46417d7c10ca17651f297c9641" + } + ] + }, + { + "name": "evince", + "config-opts": [ + "--disable-nautilus", + "--enable-introspection" + ], + "cleanup": [ + "/bin" + ], + "sources": [ + { + "type": "archive", + "url": "https://download.gnome.org/sources/evince/3.28/evince-3.28.2.tar.xz", + "sha256": "0955d22d85c9f6d322b6cbb464f1cc4c352db619017ec95dad4cc5c3440f73e1" + }, + { + "type": "patch", + "path": "evince-EvView-fix-transformation-functions-to-document-coor.patch" + } + ] + }, + { + "name": "python3-lxml", + "no-autogen": true, + "cleanup-platform": [ + "*" + ], + "ensure-writable": [ + "/lib/python*/site-packages/easy-install.pth" + ], + "build-options": { + "cflags": "-I/usr/include", + "env": { + "XSLT_CONFIG": "pkg-config libxslt", + "XML2_CONFIG": "pkg-config libxml-2.0" + } + }, + "sources": [ + { + "type": "archive", + "url": "https://pypi.python.org/packages/20/b3/9f245de14b7696e2d2a386c0b09032a2ff6625270761d6543827e667d8de/lxml-3.8.0.tar.gz", + "sha256": "736f72be15caad8116891eb6aa4a078b590d231fdc63818c40c21624ac71db96" + }, + { + "type": "file", + "path": "setuptools-makefile", + "dest-filename": "Makefile" + }, + { + "type": "patch", + "path": "lxml-Fix-getting-lib-version-when-using-pkg-config.patch" + } + ] + }, + { + "name": "hotdoc", + "cleanup-platform": [ + "*" + ], + "buildsystem": "simple", + "build-commands": [ + "pip3 install --no-index --find-links \"file://${PWD}\" hotdoc" + ], + "sources": [ + { + "type": "file", + "url": "https://pypi.python.org/packages/f6/f7/875e23067652488ae40603336fdd63510a1e1853672b5b829a78452fd31c/toposort-1.4.tar.gz", + "sha256": "c190b9d9a9e53ae2835f4d524130147af601fbd63677d19381c65067a80fa903" + }, + { + "type": "file", + "url": "https://pypi.python.org/packages/b1/94/311326207d43dd0bcc7c98b9abef223a38841d2baf1a3bb53b09b7f5f625/SQLAlchemy-1.2.1.tar.gz", + "sha256": "9ede7070d6fd18f28058be88296ed67893e2637465516d6a596cd9afea97b154" + }, + { + "type": "file", + "url": "https://pypi.python.org/packages/b1/67/7f0a14a4cc9bd949b8d22383c26fec83a00e7bd428e15c697f998e3e37ba/wheezy.template-0.1.167.tar.gz", + "sha256": "a2ee933452f0352fb8587d79bf6fc66dbf3a14779ef7d17b9fa75e80c0003f19" + }, + { + "type": "file", + "url": "https://pypi.python.org/packages/ad/fd/07c85c70803465df171340d88b12b7f41f5181777053a5cd8d75ce2f4b89/schema-0.6.7.tar.gz", + "sha256": "410f44cb025384959d20deef00b4e1595397fa30959947a4f0d92e9c84616f35" + }, + { + "type": "file", + "url": "https://pypi.python.org/packages/48/69/d87c60746b393309ca30761f8e2b49473d43450b150cb08f3c6df5c11be5/appdirs-1.4.3.tar.gz", + "sha256": "9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92" + }, + { + "type": "file", + "url": "https://pypi.python.org/packages/0b/8e/07d19b56d5e4fc79d86f2dff69674841c8dec30a008dbda36d0d2dbc6e50/hotdoc-0.8.92.tar.gz", + "sha256": "b9c7141ae71696e5da11974e2b012814d9cf76569a9934b184195237ada767bd" + } + ] + }, + { + "name": "hotdoc-modular-framework", + "cleanup-platform": [ + "*" + ], + "buildsystem": "simple", + "build-commands": [ + "pip3 install ." + ], + "test-commands": [ + "python setup.py test" + ], + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/hotdoc-modular-framework", + "branch": "master" + } + ] + }, + { + "name": "eos-hotdoc-theme", + "cleanup-platform": [ + "*" + ], + "buildsystem": "simple", + "build-commands": [], + "sources": [ + { + "type": "file", + "url": "https://endlessm.github.io/eos-hotdoc-theme/releases/eos-hotdoc-theme-0.0.0.tar.xz", + "sha256": "38c0e9b4e30636fcc595e5f45504c08a912505a7c31b0d2ab1a27f0947c9b41e" + } + ], + "post-install": [ + "mkdir -p /usr/share/eos-hotdoc-theme", + "tar -C /usr/share/eos-hotdoc-theme -xJf eos-hotdoc-theme-0.0.0.tar.xz" + ] + }, + { + "name": "mustache-c", + "sources": [ + { + "type": "git", + "url": "https://github.com/x86-64/mustache-c.git", + "commit": "01f1e4732c4862071bbf07242128abf1e28cc105" + } + ] + }, + { + "name": "eos-knowledge-content-renderer", + "buildsystem": "meson", + "cleanup": [ + "/include/*", + "/share/gir-1.0/*" + ], + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/eos-knowledge-content-renderer.git" + } + ] + }, + { + "name": "eos-knowledge-lib", + "cleanup-platform": [ + "*.po", + "*.scss", + "/bin/autobahn", + "/bin/eminem", + "/bin/introspect", + "/bin/kermit", + "/bin/picard" + ], + "build-options": { + "config-opts": [ + "--disable-js-doc", + "--disable-documentation", + "--with-mathjax-dir=/usr/share/javascript/mathjax" + ], + "env": { + "HOTDOC": "/usr/bin/python3 /usr/bin/hotdoc" + } + }, + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/eos-knowledge-lib.git" + } + ] + }, + { + "name": "default-theme-fonts", + "buildsystem": "simple", + "build-commands": [ + "mkdir -p /usr/share/fonts", + "for font in *.zip; do unzip $font -d /usr/share/fonts/${font%.*}; done" + ], + "sources": [ + { + "type": "file", + "path": "fonts/Fira+Sans.zip", + "dest-filename": "Fira-Sans.zip", + "sha256": "72dffb20a8cdaebafa707a69049f27086b4d74007fcbbc675dccd9fa7df950af" + }, + { + "type": "file", + "path": "fonts/Lato.zip", + "dest-filename": "Lato.zip", + "sha256": "2797e3ee749f572a506a1b9c2536ac45bb266dba093cffff30542eeb24c29f9c" + }, + { + "type": "file", + "path": "fonts/Libre+Baskerville.zip", + "dest-filename": "Libre-Baskerville.zip", + "sha256": "f55e2d802e947c8d565f617871ce83bfee7f95c723cb095f483452f40536b5b6" + }, + { + "type": "file", + "path": "fonts/Merriweather.zip", + "dest-filename": "Merriweather.zip", + "sha256": "5eaf3ba2fe1af3a5db38679e7df946038301a1f2ce18d587d19e2e2f1307c6e8" + }, + { + "type": "file", + "path": "fonts/Noto+Sans.zip", + "dest-filename": "Noto-Sans.zip", + "sha256": "abec8b6e2f8cd368331d994d139bf9ff08e263b7409dc13638203c49e875e17a" + }, + { + "type": "file", + "path": "fonts/Noto+Serif.zip", + "dest-filename": "Noto-Serif.zip", + "sha256": "f281f11ab5bf01f6e4262d2b5c2fe89a7b4e83210673b9859a65911ff4f9de7e" + }, + { + "type": "file", + "path": "fonts/Raleway.zip", + "dest-filename": "Raleway.zip", + "sha256": "04d293c9cfa08e501267297f1d649b055d8a8ca5745f2154f2643e67da880852" + }, + { + "type": "file", + "path": "fonts/Roboto.zip", + "dest-filename": "Roboto.zip", + "sha256": "3d0a957f7070355aa776cd0b09e26d002d4bb141962b53ef6daa893572d45d48" + } + ] + }, + { + "name": "os-release", + "sources": [ + { + "type": "file", + "path": "os-release" + }, + { + "type": "file", + "path": "issue" + }, + { + "type": "file", + "path": "issue.net" + }, + { + "type": "file", + "path": "com.endlessm.apps.Sdk.appdata.xml" + }, + { + "type": "file", + "path": "com.endlessm.apps.Platform.appdata.xml" + }, + { + "type": "file", + "path": "os-release-configure", + "dest-filename": "configure" + } + ] + } + ] +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..9ae0ea78af1cea8572934c3fca97bc27ed038daa --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +# vim:ff=unix:ts=2:sw=2:ai:expandtab +--- +version: '3.5' +services: + flatpak-builder: + build: + context: . + #cap_add: + # - SYS_ADMIN + image: flatpak-builder + privileged: true + #security_opt: + #- seccomp=flatpak-seccomp.json + #- seccomp=unconfined + #- apparmor=unconfined + volumes: + - /proc:/proc + - /var/cache/flatpak:/var/lib/builder/.local/share/flatpak diff --git a/endless-appstream-cache.patch b/endless-appstream-cache.patch new file mode 100644 index 0000000000000000000000000000000000000000..a04c1024b1d5bf4c42b5ccecfcd81f15934b9231 --- /dev/null +++ b/endless-appstream-cache.patch @@ -0,0 +1,34 @@ +Description: Don't write cache if there are no valid components +Author: Matthias Klumpp <matthias@tenstral.net> + +--- appstream-0.10.4.orig/src/as-cache-file.c ++++ appstream-0.10.4/src/as-cache-file.c +@@ -185,6 +185,7 @@ as_cache_file_save (const gchar *fname, + g_autoptr(GFileOutputStream) file_out = NULL; + g_autoptr(GOutputStream) zout = NULL; + g_autoptr(GZlibCompressor) compressor = NULL; ++ gboolean serializable_components_found = FALSE; + GError *tmp_error = NULL; + guint cindex; + +@@ -218,6 +219,8 @@ as_cache_file_save (const gchar *fname, + continue; + } + ++ serializable_components_found = TRUE; ++ + /* start serializing our component */ + g_variant_builder_init (&cb, G_VARIANT_TYPE_VARDICT); + +@@ -486,6 +489,11 @@ as_cache_file_save (const gchar *fname, + g_variant_builder_add_value (builder, g_variant_builder_end (&cb)); + } + ++ /* check if we actually have some valid components serialized to a GVariant */ ++ if (!serializable_components_found) { ++ g_debug ("Skipped writing cache file: No valid components found for serialization."); ++ return; ++ } + + /* write basic information and add components */ + g_variant_builder_add (main_builder, "{sv}", diff --git a/endless-appstream-no-docs.patch b/endless-appstream-no-docs.patch new file mode 100644 index 0000000000000000000000000000000000000000..7e366a0463ddf8fe9b6f6be413f4e94e61bbdfb0 --- /dev/null +++ b/endless-appstream-no-docs.patch @@ -0,0 +1,31 @@ +diff -Nuarp appstream-APPSTREAM_0_10_4.old/docs/CMakeLists.txt appstream-APPSTREAM_0_10_4.new/docs/CMakeLists.txt +--- appstream-APPSTREAM_0_10_4.old/docs/CMakeLists.txt 2016-11-27 17:59:18.000000000 +0000 ++++ appstream-APPSTREAM_0_10_4.new/docs/CMakeLists.txt 2017-03-16 14:51:00.997136311 +0000 +@@ -1,18 +1,18 @@ + # CMakeLists for documentation + +-find_program (XMLTO xmlto) +-mark_as_advanced (XMLTO) +-if (XMLTO STREQUAL "XMLTO-NOTFOUND") +- message (FATAL_ERROR "Xmlto was not found! Please install it to continue!") +-endif (XMLTO STREQUAL "XMLTO-NOTFOUND") ++if (DOCUMENTATION) ++ find_program (XMLTO xmlto) ++ mark_as_advanced (XMLTO) ++ if (XMLTO STREQUAL "XMLTO-NOTFOUND") ++ message (FATAL_ERROR "Xmlto was not found! Please install it to continue!") ++ endif (XMLTO STREQUAL "XMLTO-NOTFOUND") + +-include (${CMAKE_SOURCE_DIR}/data/cmake/documentation.cmake) ++ include (${CMAKE_SOURCE_DIR}/data/cmake/documentation.cmake) + +-add_xml_manpages(doc-man-asi "sources/man/appstreamcli.1" "" "") ++ add_xml_manpages(doc-man-asi "sources/man/appstreamcli.1" "" "") + +-set(DOC_HTML_EXPORT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/html") ++ set(DOC_HTML_EXPORT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/html") + +-if (DOCUMENTATION) + ######################### + # General project documentation + find_program (PUBLICAN publican) diff --git a/evince-EvView-fix-transformation-functions-to-document-coor.patch b/evince-EvView-fix-transformation-functions-to-document-coor.patch new file mode 100644 index 0000000000000000000000000000000000000000..5cdbe7b683b0b072babb54f66524a32cddad1b91 --- /dev/null +++ b/evince-EvView-fix-transformation-functions-to-document-coor.patch @@ -0,0 +1,37 @@ +From 22c31d6049b82b1aa52b2ba8843612515aeeba2c Mon Sep 17 00:00:00 2001 +From: Juan Pablo Ugarte <ugarte@endlessm.com> +Date: Tue, 12 Jun 2018 10:51:06 -0300 +Subject: [PATCH] EvView: fix transformation functions to document coordinates. + +Use top border value instead of right in transformation functions. + +Fixes issue #914 "Text selection broken with different border widths" +--- + libview/ev-view.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libview/ev-view.c b/libview/ev-view.c +index e99ee5dc..e6758944 100644 +--- a/libview/ev-view.c ++++ b/libview/ev-view.c +@@ -1375,7 +1375,7 @@ _ev_view_transform_view_point_to_doc_point (EvView *view, + double *doc_point_y) + { + *doc_point_x = MAX ((double) (view_point->x - page_area->x - border->left) / view->scale, 0); +- *doc_point_y = MAX ((double) (view_point->y - page_area->y - border->right) / view->scale, 0); ++ *doc_point_y = MAX ((double) (view_point->y - page_area->y - border->top) / view->scale, 0); + } + + void +@@ -1386,7 +1386,7 @@ _ev_view_transform_view_rect_to_doc_rect (EvView *view, + EvRectangle *doc_rect) + { + doc_rect->x1 = MAX ((double) (view_rect->x - page_area->x - border->left) / view->scale, 0); +- doc_rect->y1 = MAX ((double) (view_rect->y - page_area->y - border->right) / view->scale, 0); ++ doc_rect->y1 = MAX ((double) (view_rect->y - page_area->y - border->top) / view->scale, 0); + doc_rect->x2 = doc_rect->x1 + (double) view_rect->width / view->scale; + doc_rect->y2 = doc_rect->y1 + (double) view_rect->height / view->scale; + } +-- +2.17.1 + diff --git a/fonts/Fira+Sans.zip b/fonts/Fira+Sans.zip new file mode 100644 index 0000000000000000000000000000000000000000..13ebf60b8f5440d6e30bb2d1a4a8c29ec34926f7 Binary files /dev/null and b/fonts/Fira+Sans.zip differ diff --git a/fonts/Lato.zip b/fonts/Lato.zip new file mode 100644 index 0000000000000000000000000000000000000000..9cb19d135c96ca05e9e841455f07811f711b8b55 Binary files /dev/null and b/fonts/Lato.zip differ diff --git a/fonts/Libre+Baskerville.zip b/fonts/Libre+Baskerville.zip new file mode 100644 index 0000000000000000000000000000000000000000..dfa11e83f126be5adbbc66fe29f8c1dcdba453d6 Binary files /dev/null and b/fonts/Libre+Baskerville.zip differ diff --git a/fonts/Merriweather.zip b/fonts/Merriweather.zip new file mode 100644 index 0000000000000000000000000000000000000000..d9658eb6758551b065b4e43d0d4ff88d74ae2a92 Binary files /dev/null and b/fonts/Merriweather.zip differ diff --git a/fonts/Noto+Sans.zip b/fonts/Noto+Sans.zip new file mode 100644 index 0000000000000000000000000000000000000000..f8659bd2e35a658fbe5df15436d9ad1aa923d0b8 Binary files /dev/null and b/fonts/Noto+Sans.zip differ diff --git a/fonts/Noto+Serif.zip b/fonts/Noto+Serif.zip new file mode 100644 index 0000000000000000000000000000000000000000..01ef0d022f4a8c79a2cacb71d1ced93254503308 Binary files /dev/null and b/fonts/Noto+Serif.zip differ diff --git a/fonts/Raleway.zip b/fonts/Raleway.zip new file mode 100644 index 0000000000000000000000000000000000000000..357d3cc551d23448880ad501db8954961eeaeaea Binary files /dev/null and b/fonts/Raleway.zip differ diff --git a/fonts/Roboto.zip b/fonts/Roboto.zip new file mode 100644 index 0000000000000000000000000000000000000000..a4da31718667aa6990f5f4718b96878b6402c9c6 Binary files /dev/null and b/fonts/Roboto.zip differ diff --git a/gtk3-CSS-eos-cairo-filter-property.patch b/gtk3-CSS-eos-cairo-filter-property.patch new file mode 100644 index 0000000000000000000000000000000000000000..b9a5a4eb94fa026e4870e4046e7a35b711aa7b84 --- /dev/null +++ b/gtk3-CSS-eos-cairo-filter-property.patch @@ -0,0 +1,232 @@ +From 5f6b84d234898d3d9fdac6e42b633c43c1e7b969 Mon Sep 17 00:00:00 2001 +From: Juan Pablo Ugarte <ugarte@endlessm.com> +Date: Thu, 11 Jan 2018 17:21:24 -0300 +Subject: [PATCH] CSS: add vendor specific -eos-cairo-filter property + +This property is used to provide a hint about the algorithm it should be use to scale CSS images. +--- + gtk/gtkcssenumvalue.c | 55 +++++++++++++++++++++++++++++++++++++++++ + gtk/gtkcssenumvalueprivate.h | 4 +++ + gtk/gtkcssimagesurface.c | 9 +++++++ + gtk/gtkcssimagesurfaceprivate.h | 4 +++ + gtk/gtkcssstylepropertyimpl.c | 20 +++++++++++++++ + gtk/gtkcsstypesprivate.h | 1 + + gtk/gtkrenderbackground.c | 9 +++++++ + 7 files changed, 102 insertions(+) + +diff --git a/gtk/gtkcssenumvalue.c b/gtk/gtkcssenumvalue.c +index 784f97e3e6..9af3078f7d 100644 +--- a/gtk/gtkcssenumvalue.c ++++ b/gtk/gtkcssenumvalue.c +@@ -1070,3 +1070,58 @@ _gtk_css_icon_style_value_get (const GtkCssValue *value) + + return value->value; + } ++ ++/* GtkCssEosCairoFilter */ ++ ++static const GtkCssValueClass GTK_CSS_VALUE_EOS_CAIRO_FILTER = { ++ gtk_css_value_enum_free, ++ gtk_css_value_enum_compute, ++ gtk_css_value_enum_equal, ++ gtk_css_value_enum_transition, ++ gtk_css_value_enum_print ++}; ++ ++static GtkCssValue cairo_filter_values[] = { ++ { >K_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_FAST, "-eos-fast" }, ++ { >K_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_GOOD, "-eos-good" }, ++ { >K_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_BEST, "-eos-best" }, ++ { >K_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_NEAREST, "-eos-nearest" }, ++ { >K_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_BILINEAR, "-eos-bilinear" } ++}; ++ ++GtkCssValue * ++_gtk_css_eos_cairo_filter_value_new (cairo_filter_t filter) ++{ ++ guint i; ++ ++ for (i = 0; i < G_N_ELEMENTS (cairo_filter_values); i++) ++ { ++ if (cairo_filter_values[i].value == filter) ++ return _gtk_css_value_ref (&cairo_filter_values[i]); ++ } ++ ++ g_return_val_if_reached (NULL); ++} ++ ++GtkCssValue * ++_gtk_css_eos_cairo_filter_value_try_parse (GtkCssParser *parser) ++{ ++ guint i; ++ ++ g_return_val_if_fail (parser != NULL, NULL); ++ ++ for (i = 0; i < G_N_ELEMENTS (cairo_filter_values); i++) ++ { ++ if (_gtk_css_parser_try (parser, cairo_filter_values[i].name, TRUE)) ++ return _gtk_css_value_ref (&cairo_filter_values[i]); ++ } ++ ++ return NULL; ++} ++ ++cairo_filter_t ++_gtk_css_eos_cairo_filter_get (const GtkCssValue *value) ++{ ++ g_return_val_if_fail (value->class == >K_CSS_VALUE_EOS_CAIRO_FILTER, CAIRO_FILTER_GOOD); ++ return value->value; ++} +diff --git a/gtk/gtkcssenumvalueprivate.h b/gtk/gtkcssenumvalueprivate.h +index deb145cb2e..705a00c373 100644 +--- a/gtk/gtkcssenumvalueprivate.h ++++ b/gtk/gtkcssenumvalueprivate.h +@@ -91,6 +91,10 @@ GtkCssValue * _gtk_css_icon_style_value_new (GtkCssIconStyle icon_s + GtkCssValue * _gtk_css_icon_style_value_try_parse (GtkCssParser *parser); + GtkCssIconStyle _gtk_css_icon_style_value_get (const GtkCssValue *value); + ++GtkCssValue * _gtk_css_eos_cairo_filter_value_new (cairo_filter_t filter); ++GtkCssValue * _gtk_css_eos_cairo_filter_value_try_parse (GtkCssParser *parser); ++cairo_filter_t _gtk_css_eos_cairo_filter_get (const GtkCssValue *value); ++ + G_END_DECLS + + #endif /* __GTK_CSS_ENUM_VALUE_PRIVATE_H__ */ +diff --git a/gtk/gtkcssimagesurface.c b/gtk/gtkcssimagesurface.c +index 8c439c9a52..c76522ba63 100644 +--- a/gtk/gtkcssimagesurface.c ++++ b/gtk/gtkcssimagesurface.c +@@ -57,6 +57,7 @@ gtk_css_image_surface_draw (GtkCssImage *image, + + /* Update cache image if size is different */ + if (surface->cache == NULL || ++ surface->cache_filter != surface->filter || + ABS (width - surface->width) > 0.001 || + ABS (height - surface->height) > 0.001) + { +@@ -78,6 +79,8 @@ gtk_css_image_surface_draw (GtkCssImage *image, + cairo_rectangle (cache, 0, 0, width, height); + cairo_scale (cache, width / image_width, height / image_height); + cairo_set_source_surface (cache, surface->surface, 0, 0); ++ cairo_pattern_set_filter (cairo_get_source (cache), surface->filter); ++ surface->cache_filter = surface->filter; + cairo_fill (cache); + + cairo_destroy (cache); +@@ -153,6 +156,7 @@ _gtk_css_image_surface_class_init (GtkCssImageSurfaceClass *klass) + static void + _gtk_css_image_surface_init (GtkCssImageSurface *image_surface) + { ++ image_surface->filter = CAIRO_FILTER_GOOD; + } + + GtkCssImage * +@@ -185,3 +189,8 @@ _gtk_css_image_surface_new_for_pixbuf (GdkPixbuf *pixbuf) + return image; + } + ++void ++_gtk_css_image_surface_set_filter (GtkCssImageSurface *image, cairo_filter_t filter) ++{ ++ image->filter = filter; ++} +diff --git a/gtk/gtkcssimagesurfaceprivate.h b/gtk/gtkcssimagesurfaceprivate.h +index 9619d8483d..ee758425af 100644 +--- a/gtk/gtkcssimagesurfaceprivate.h ++++ b/gtk/gtkcssimagesurfaceprivate.h +@@ -42,6 +42,8 @@ struct _GtkCssImageSurface + cairo_surface_t *cache; /* the scaled surface - to avoid scaling every time we need to draw */ + double width; /* original cache width */ + double height; /* original cache height */ ++ cairo_filter_t filter; ++ cairo_filter_t cache_filter; + }; + + struct _GtkCssImageSurfaceClass +@@ -53,6 +55,8 @@ GType _gtk_css_image_surface_get_type (void) G_GNUC_CONST; + + GtkCssImage * _gtk_css_image_surface_new (cairo_surface_t *surface); + GtkCssImage * _gtk_css_image_surface_new_for_pixbuf (GdkPixbuf *pixbuf); ++void _gtk_css_image_surface_set_filter (GtkCssImageSurface *image, ++ cairo_filter_t filter); + + G_END_DECLS + +diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c +index 9fd506a0ca..1491dde99b 100644 +--- a/gtk/gtkcssstylepropertyimpl.c ++++ b/gtk/gtkcssstylepropertyimpl.c +@@ -719,6 +719,17 @@ css_image_value_parse_with_builtin (GtkCssStyleProperty *property, + return css_image_value_parse (property, parser); + } + ++static GtkCssValue * ++cairo_filter_parse (GtkCssStyleProperty *property, GtkCssParser *parser) ++{ ++ GtkCssValue *value = _gtk_css_eos_cairo_filter_value_try_parse (parser); ++ ++ if (value == NULL) ++ _gtk_css_parser_error (parser, "unknown value for property"); ++ ++ return value; ++} ++ + static void + css_image_value_query (GtkCssStyleProperty *property, + const GtkCssValue *css_value, +@@ -1869,4 +1880,13 @@ G_GNUC_END_IGNORE_DEPRECATIONS + color_query, + color_assign, + _gtk_css_color_value_new_current_color ()); ++ gtk_css_style_property_register ("-eos-cairo-filter", ++ GTK_CSS_PROPERTY_EOS_CAIRO_FILTER, ++ G_TYPE_NONE, ++ GTK_STYLE_PROPERTY_INHERIT, ++ GTK_CSS_AFFECTS_BACKGROUND, ++ cairo_filter_parse, ++ NULL, ++ NULL, ++ _gtk_css_eos_cairo_filter_value_new (CAIRO_FILTER_GOOD)); + } +diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h +index 59f392a032..e9abbb0f34 100644 +--- a/gtk/gtkcsstypesprivate.h ++++ b/gtk/gtkcsstypesprivate.h +@@ -227,6 +227,7 @@ enum { /*< skip >*/ + GTK_CSS_PROPERTY_GTK_KEY_BINDINGS, + GTK_CSS_PROPERTY_CARET_COLOR, + GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR, ++ GTK_CSS_PROPERTY_EOS_CAIRO_FILTER, + /* add more */ + GTK_CSS_PROPERTY_N_PROPERTIES + }; +diff --git a/gtk/gtkrenderbackground.c b/gtk/gtkrenderbackground.c +index 992cf20522..0931bd3d1b 100644 +--- a/gtk/gtkrenderbackground.c ++++ b/gtk/gtkrenderbackground.c +@@ -22,6 +22,7 @@ + #include "config.h" + + #include "gtkrenderbackgroundprivate.h" ++#include "gtkcssimagesurfaceprivate.h" + + #include "gtkcssarrayvalueprivate.h" + #include "gtkcssbgsizevalueprivate.h" +@@ -148,6 +149,14 @@ _gtk_theming_background_paint_layer (GtkThemingBackground *bg, + + cairo_save (cr); + ++ if (GTK_IS_CSS_IMAGE_SURFACE (image)) ++ { ++ const GtkCssValue *value; ++ value = gtk_css_style_get_value (bg->style, GTK_CSS_PROPERTY_EOS_CAIRO_FILTER); ++ _gtk_css_image_surface_set_filter (GTK_CSS_IMAGE_SURFACE (image), ++ _gtk_css_eos_cairo_filter_get (value)); ++ } ++ + _gtk_rounded_box_path ( + &bg->boxes[ + _gtk_css_area_value_get ( +-- +2.15.1 + diff --git a/gtk3-egl-x11.patch b/gtk3-egl-x11.patch new file mode 100644 index 0000000000000000000000000000000000000000..4a6e349b1d27227fcffb4635cdd3eeb571d473bc --- /dev/null +++ b/gtk3-egl-x11.patch @@ -0,0 +1,2850 @@ +diff -Nuarp gtk+-3.22.20.old/configure.ac gtk+-3.22.20.new/configure.ac +--- gtk+-3.22.20.old/configure.ac 2017-09-04 18:02:49.000000000 +0100 ++++ gtk+-3.22.20.new/configure.ac 2017-09-21 16:26:15.905417603 +0100 +@@ -321,6 +321,10 @@ AC_ARG_ENABLE(xdamage, + [AS_HELP_STRING([--enable-xdamage], + [support X Damage extension [default=maybe]])],, + [enable_xdamage="maybe"]) ++AC_ARG_ENABLE(egl-x11, ++ [AS_HELP_STRING([--enable-egl-x11], ++ [Use EGL and XLib instead of GLX [default=no]])],, ++ [enable_egl_x11=no]) + + AC_ARG_ENABLE(x11-backend, + [AS_HELP_STRING([--enable-x11-backend], +@@ -1285,6 +1289,20 @@ if test "x$enable_x11_backend" = xyes; t + fi + fi + ++ # Checks whether to use EGL-X11 or GLX ++ ++ if test x"$enable_egl_x11" != xno; then ++ if $PKG_CONFIG --exists egl ; then ++ AC_DEFINE(HAVE_EGL_X11, 1, [Use EGL-X11 instead of GLX]) ++ ++ X_PACKAGES="$X_PACKAGES egl" ++ elif test x"$enable_egl_x11" = xyes; then ++ AC_MSG_ERROR([EGL-X11 support requested but egl not found]) ++ fi ++ fi ++ ++ AM_CONDITIONAL(USE_EGL_X11, test "x$enable_egl_x11" != xno) ++ + if $have_base_x_pc ; then + GDK_EXTRA_LIBS="$x_extra_libs" + else +diff -Nuarp gtk+-3.22.20.old/gdk/gdkgl.c gtk+-3.22.20.new/gdk/gdkgl.c +--- gtk+-3.22.20.old/gdk/gdkgl.c 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/gdkgl.c 2017-09-21 16:29:28.276896598 +0100 +@@ -640,18 +640,6 @@ gdk_cairo_draw_from_gl (cairo_t + else + { + /* Software fallback */ +- int major, minor, version; +- +- gdk_gl_context_get_version (paint_context, &major, &minor); +- version = major * 100 + minor; +- +- /* TODO: Use glTexSubImage2D() and do a row-by-row copy to replace +- * the GL_UNPACK_ROW_LENGTH support +- */ +- if (gdk_gl_context_get_use_es (paint_context) && +- !(version >= 300 || gdk_gl_context_has_unpack_subimage (paint_context))) +- goto out; +- + /* TODO: avoid reading back non-required data due to dest clip */ + image = cairo_surface_create_similar_image (cairo_get_target (cr), + (alpha_size == 0) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32, +@@ -675,24 +663,15 @@ gdk_cairo_draw_from_gl (cairo_t + GL_TEXTURE_2D, source, 0); + } + +- glPixelStorei (GL_PACK_ALIGNMENT, 4); +- glPixelStorei (GL_PACK_ROW_LENGTH, cairo_image_surface_get_stride (image) / 4); +- +- /* The implicit format conversion is going to make this path slower */ +- if (!gdk_gl_context_get_use_es (paint_context)) +- glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, +- cairo_image_surface_get_data (image)); +- else +- glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, +- cairo_image_surface_get_data (image)); +- +- glPixelStorei (GL_PACK_ROW_LENGTH, 0); ++ gdk_gl_context_download_texture (paint_context, ++ x, y, width, height, ++ image); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); + + cairo_surface_mark_dirty (image); + +- /* Invert due to opengl having different origin */ ++ /* Invert due to GL framebuffers having different origin */ + cairo_scale (cr, 1, -1); + cairo_translate (cr, 0, -height / buffer_scale); + +@@ -703,10 +682,8 @@ gdk_cairo_draw_from_gl (cairo_t + cairo_surface_destroy (image); + } + +-out: + if (clip_region) + cairo_region_destroy (clip_region); +- + } + + /* This is always called with the paint context current */ +diff -Nuarp gtk+-3.22.20.old/gdk/gdkglcontext.c gtk+-3.22.20.new/gdk/gdkglcontext.c +--- gtk+-3.22.20.old/gdk/gdkglcontext.c 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/gdkglcontext.c 2017-09-21 16:29:50.148951058 +0100 +@@ -236,6 +236,123 @@ gdk_gl_context_get_property (GObject + } + } + ++/* Based on gdk_cairo_surface_paint_pixbuf() */ ++static inline void ++image_surface_rgba_to_argb (cairo_surface_t *image) ++{ ++ gint i, width, height, stride; ++ cairo_format_t format; ++ guint t1,t2,t3; ++ guchar *data; ++ ++ width = cairo_image_surface_get_width (image); ++ height = cairo_image_surface_get_height (image); ++ stride = cairo_image_surface_get_stride (image); ++ format = cairo_image_surface_get_format (image); ++ data = cairo_image_surface_get_data (image); ++ ++#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x80; d = ((t >> 8) + t) >> 8; } G_STMT_END ++ ++ for (i = 0; i < height; i++) ++ { ++ guchar *q = data + i * stride; ++ guchar *end = q + 4 * width; ++ ++ if (format == CAIRO_FORMAT_RGB24) ++ while (q < end) ++ { ++ guint32 data = *((guint32*)q); ++ guchar *p = (guchar*) &data; ++ ++#if G_BYTE_ORDER == G_LITTLE_ENDIAN ++ q[0] = p[2]; ++ q[1] = p[1]; ++ q[2] = p[0]; ++#else ++ q[1] = p[0]; ++ q[2] = p[1]; ++ q[3] = p[2]; ++#endif ++ q += 4; ++ } ++ else if (format == CAIRO_FORMAT_ARGB32) ++ while (q < end) ++ { ++ guint32 data = *((guint32*)q); ++ guchar *p = (guchar*) &data; ++ ++#if G_BYTE_ORDER == G_LITTLE_ENDIAN ++ MULT(q[0], p[2], p[3], t1); ++ MULT(q[1], p[1], p[3], t2); ++ MULT(q[2], p[0], p[3], t3); ++ q[3] = p[3]; ++#else ++ q[0] = p[3]; ++ MULT(q[1], p[0], p[3], t1); ++ MULT(q[2], p[1], p[3], t2); ++ MULT(q[3], p[2], p[3], t3); ++#endif ++ q += 4; ++ } ++ } ++ ++#undef MULT ++} ++ ++void ++gdk_gl_context_download_texture (GdkGLContext *context, ++ int x, ++ int y, ++ int width, ++ int height, ++ cairo_surface_t *image_surface) ++{ ++ GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); ++ ++ g_return_if_fail (GDK_IS_GL_CONTEXT (context)); ++ ++ /* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if ++ * the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available ++ */ ++ if (!priv->use_es || ++ (priv->use_es && (priv->gl_version >= 30 || priv->has_unpack_subimage))) ++ { ++ glPixelStorei (GL_PACK_ALIGNMENT, 4); ++ glPixelStorei (GL_PACK_ROW_LENGTH, cairo_image_surface_get_stride (image_surface) / 4); ++ ++ if (priv->use_es) ++ glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ++ cairo_image_surface_get_data (image_surface)); ++ else ++ glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, ++ cairo_image_surface_get_data (image_surface)); ++ ++ glPixelStorei (GL_PACK_ROW_LENGTH, 0); ++ } ++ else ++ { ++ GLvoid *data = cairo_image_surface_get_data (image_surface); ++ int stride = cairo_image_surface_get_stride (image_surface); ++ int i; ++ ++ if (priv->use_es) ++ { ++ for (i = y; i < height; i++) ++ glReadPixels (x, i, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ++ (unsigned char *) data + (i * stride)); ++ } ++ else ++ { ++ for (i = y; i < height; i++) ++ glReadPixels (x, i, width, 1, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, ++ (unsigned char *) data + (i * stride)); ++ } ++ } ++ ++ if (priv->use_es) ++ image_surface_rgba_to_argb (image_surface); ++} ++ + void + gdk_gl_context_upload_texture (GdkGLContext *context, + cairo_surface_t *image_surface, +diff -Nuarp gtk+-3.22.20.old/gdk/gdkglcontextprivate.h gtk+-3.22.20.new/gdk/gdkglcontextprivate.h +--- gtk+-3.22.20.old/gdk/gdkglcontextprivate.h 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/gdkglcontextprivate.h 2017-09-21 16:29:28.277896601 +0100 +@@ -81,6 +81,12 @@ void gdk_gl_context_u + int width, + int height, + guint texture_target); ++void gdk_gl_context_download_texture (GdkGLContext *context, ++ int x, ++ int y, ++ int width, ++ int height, ++ cairo_surface_t *image_surface); + GdkGLContextPaintData * gdk_gl_context_get_paint_data (GdkGLContext *context); + gboolean gdk_gl_context_use_texture_rectangle (GdkGLContext *context); + gboolean gdk_gl_context_has_framebuffer_blit (GdkGLContext *context); +diff -Nuarp gtk+-3.22.20.old/gdk/x11/gdkdisplay-x11.c gtk+-3.22.20.new/gdk/x11/gdkdisplay-x11.c +--- gtk+-3.22.20.old/gdk/x11/gdkdisplay-x11.c 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/x11/gdkdisplay-x11.c 2017-09-21 16:30:39.667074356 +0100 +@@ -430,6 +430,37 @@ get_event_xwindow (XEvent *x + return xwindow; + } + ++static inline void ++gdk_check_window_unredirected (GdkDisplay *display, ++ GdkToplevelX11 *toplevel, ++ GdkWindow *window, ++ Atom property) ++{ ++ Atom type = None; ++ gint format; ++ gulong nitems; ++ gulong bytes_after; ++ guchar *data; ++ ++ gdk_x11_display_error_trap_push (display); ++ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), ++ GDK_WINDOW_XID (window), ++ property, ++ 0, G_MAXLONG, ++ False, XA_CARDINAL, ++ &type, &format, &nitems, ++ &bytes_after, &data); ++ gdk_x11_display_error_trap_pop_ignored (display); ++ ++ if (type != None) ++ { ++ toplevel->unredirected = *((gint*)data) ? TRUE : FALSE; ++ XFree (data); ++ } ++ else ++ toplevel->unredirected = FALSE; ++} ++ + static gboolean + gdk_x11_display_translate_event (GdkEventTranslator *translator, + GdkDisplay *display, +@@ -881,6 +912,9 @@ gdk_x11_display_translate_event (GdkEven + gdk_check_wm_desktop_changed (window); + } + ++ if (toplevel && xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_GTK_WINDOW_UNREDIRECTED")) ++ gdk_check_window_unredirected (display, toplevel, window, xevent->xproperty.atom); ++ + if (window->event_mask & GDK_PROPERTY_CHANGE_MASK) + { + event->property.type = GDK_PROPERTY_NOTIFY; +diff -Nuarp gtk+-3.22.20.old/gdk/x11/gdkdisplay-x11.h gtk+-3.22.20.new/gdk/x11/gdkdisplay-x11.h +--- gtk+-3.22.20.old/gdk/x11/gdkdisplay-x11.h 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/x11/gdkdisplay-x11.h 2017-09-21 16:30:12.462006616 +0100 +@@ -137,18 +137,20 @@ struct _GdkX11Display + + guint server_time_is_monotonic_time : 1; + +- guint have_glx : 1; ++ guint supports_gl : 1; + +- /* GLX extensions we check */ +- guint has_glx_swap_interval : 1; +- guint has_glx_create_context : 1; +- guint has_glx_texture_from_pixmap : 1; +- guint has_glx_video_sync : 1; +- guint has_glx_buffer_age : 1; +- guint has_glx_sync_control : 1; +- guint has_glx_multisample : 1; +- guint has_glx_visual_rating : 1; +- guint has_glx_create_es2_context : 1; ++ /* Platform-specific GL extensions we check */ ++ guint has_swap_interval : 1; ++ guint has_create_context : 1; ++ guint has_texture_from_pixmap : 1; ++ guint has_video_sync : 1; ++ guint has_buffer_age : 1; ++ guint has_sync_control : 1; ++ guint has_multisample : 1; ++ guint has_visual_rating : 1; ++ guint has_create_es2_context : 1; ++ guint has_swap_buffers_with_damage : 1; ++ guint has_image_pixmap : 1; + }; + + struct _GdkX11DisplayClass +diff -Nuarp gtk+-3.22.20.old/gdk/x11/gdkglcontext-x11.c gtk+-3.22.20.new/gdk/x11/gdkglcontext-x11.c +--- gtk+-3.22.20.old/gdk/x11/gdkglcontext-x11.c 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/x11/gdkglcontext-x11.c 2017-09-21 16:26:15.909417613 +0100 +@@ -39,17 +39,38 @@ + + #include <cairo/cairo-xlib.h> + ++#include <epoxy/gl.h> + #include <epoxy/glx.h> + ++struct _GdkX11GLContext ++{ ++ GdkGLContext parent_instance; ++ ++ GLXContext glx_context; ++ GLXFBConfig glx_config; ++ GLXDrawable drawable; ++ ++ guint is_attached : 1; ++ guint is_direct : 1; ++ guint do_frame_sync : 1; ++ ++ guint do_blit_swap : 1; ++}; ++ ++struct _GdkX11GLContextClass ++{ ++ GdkGLContextClass parent_class; ++}; ++ + G_DEFINE_TYPE (GdkX11GLContext, gdk_x11_gl_context, GDK_TYPE_GL_CONTEXT) + + typedef struct { + GdkDisplay *display; + + GLXDrawable glx_drawable; ++ GLXWindow dummy_glx; + + Window dummy_xwin; +- GLXWindow dummy_glx; + + guint32 last_frame_counter; + } DrawableInfo; +@@ -100,7 +121,7 @@ maybe_wait_for_vblank (GdkDisplay *disp + GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); + Display *dpy = gdk_x11_display_get_xdisplay (display); + +- if (display_x11->has_glx_sync_control) ++ if (display_x11->has_sync_control) + { + gint64 ust, msc, sbc; + +@@ -109,7 +130,7 @@ maybe_wait_for_vblank (GdkDisplay *disp + 0, 2, (msc + 1) % 2, + &ust, &msc, &sbc); + } +- else if (display_x11->has_glx_video_sync) ++ else if (display_x11->has_video_sync) + { + guint32 current_count; + +@@ -140,7 +161,7 @@ gdk_x11_window_invalidate_for_new_frame + + context_x11->do_blit_swap = FALSE; + +- if (display_x11->has_glx_buffer_age) ++ if (display_x11->has_buffer_age) + { + gdk_gl_context_make_current (window->gl_paint_context); + glXQueryDrawable(dpy, context_x11->drawable, +@@ -248,13 +269,13 @@ gdk_x11_gl_context_end_frame (GdkGLConte + if (context_x11->do_frame_sync) + { + guint32 end_frame_counter = 0; +- gboolean has_counter = display_x11->has_glx_video_sync; +- gboolean can_wait = display_x11->has_glx_video_sync || display_x11->has_glx_sync_control; ++ gboolean has_counter = display_x11->has_video_sync; ++ gboolean can_wait = display_x11->has_video_sync || display_x11->has_sync_control; + +- if (display_x11->has_glx_video_sync) ++ if (display_x11->has_video_sync) + glXGetVideoSyncSGI (&end_frame_counter); + +- if (context_x11->do_frame_sync && !display_x11->has_glx_swap_interval) ++ if (context_x11->do_frame_sync && !display_x11->has_swap_interval) + { + glFinish (); + +@@ -284,7 +305,7 @@ gdk_x11_gl_context_end_frame (GdkGLConte + else + glXSwapBuffers (dpy, drawable); + +- if (context_x11->do_frame_sync && info != NULL && display_x11->has_glx_video_sync) ++ if (context_x11->do_frame_sync && info != NULL && display_x11->has_video_sync) + glXGetVideoSyncSGI (&info->last_frame_counter); + } + +@@ -439,7 +460,7 @@ gdk_x11_gl_context_texture_from_surface + GdkX11Display *display_x11; + + display_x11 = GDK_X11_DISPLAY (gdk_gl_context_get_display (paint_context)); +- if (!display_x11->has_glx_texture_from_pixmap) ++ if (!display_x11->has_texture_from_pixmap) + return FALSE; + + if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB) +@@ -640,12 +661,12 @@ gdk_x11_gl_context_realize (GdkGLContext + compat_bit = gdk_gl_context_get_forward_compatible (context); + + /* If there is no glXCreateContextAttribsARB() then we default to legacy */ +- legacy_bit = !display_x11->has_glx_create_context || ++ legacy_bit = !display_x11->has_create_context || + (_gdk_gl_flags & GDK_GL_LEGACY) != 0; + + es_bit = ((_gdk_gl_flags & GDK_GL_GLES) != 0 || + (share != NULL && gdk_gl_context_get_use_es (share))) && +- (display_x11->has_glx_create_context && display_x11->has_glx_create_es2_context); ++ (display_x11->has_create_context && display_x11->has_create_es2_context); + + /* We cannot share legacy contexts with core profile ones, so the + * shared context is the one that decides if we're going to create +@@ -672,7 +693,7 @@ gdk_x11_gl_context_realize (GdkGLContext + * a compatibility profile; if we don't, then we have to fall back to the + * old GLX 1.3 API. + */ +- if (legacy_bit && !GDK_X11_DISPLAY (display)->has_glx_create_context) ++ if (legacy_bit && !GDK_X11_DISPLAY (display)->has_create_context) + { + GDK_NOTE (OPENGL, g_message ("Creating legacy GL context on request")); + context_x11->glx_context = create_legacy_context (display, context_x11->glx_config, share); +@@ -848,7 +869,7 @@ gdk_x11_screen_init_gl (GdkScreen *scree + int error_base, event_base; + int screen_num; + +- if (display_x11->have_glx) ++ if (display_x11->supports_gl) + return TRUE; + + if (_gdk_gl_flags & GDK_GL_DISABLE) +@@ -861,29 +882,29 @@ gdk_x11_screen_init_gl (GdkScreen *scree + + screen_num = GDK_X11_SCREEN (screen)->screen_num; + +- display_x11->have_glx = TRUE; ++ display_x11->supports_gl = TRUE; + + display_x11->glx_version = epoxy_glx_version (dpy, screen_num); + display_x11->glx_error_base = error_base; + display_x11->glx_event_base = event_base; + +- display_x11->has_glx_create_context = ++ display_x11->has_create_context = + epoxy_has_glx_extension (dpy, screen_num, "GLX_ARB_create_context_profile"); +- display_x11->has_glx_create_es2_context = ++ display_x11->has_create_es2_context = + epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_create_context_es2_profile"); +- display_x11->has_glx_swap_interval = ++ display_x11->has_swap_interval = + epoxy_has_glx_extension (dpy, screen_num, "GLX_SGI_swap_control"); +- display_x11->has_glx_texture_from_pixmap = ++ display_x11->has_texture_from_pixmap = + epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_texture_from_pixmap"); +- display_x11->has_glx_video_sync = ++ display_x11->has_video_sync = + epoxy_has_glx_extension (dpy, screen_num, "GLX_SGI_video_sync"); +- display_x11->has_glx_buffer_age = ++ display_x11->has_buffer_age = + epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_buffer_age"); +- display_x11->has_glx_sync_control = ++ display_x11->has_sync_control = + epoxy_has_glx_extension (dpy, screen_num, "GLX_OML_sync_control"); +- display_x11->has_glx_multisample = ++ display_x11->has_multisample = + epoxy_has_glx_extension (dpy, screen_num, "GLX_ARB_multisample"); +- display_x11->has_glx_visual_rating = ++ display_x11->has_visual_rating = + epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_visual_rating"); + + GDK_NOTE (OPENGL, +@@ -900,13 +921,13 @@ gdk_x11_screen_init_gl (GdkScreen *scree + display_x11->glx_version / 10, + display_x11->glx_version % 10, + glXGetClientString (dpy, GLX_VENDOR), +- display_x11->has_glx_create_context ? "yes" : "no", +- display_x11->has_glx_create_es2_context ? "yes" : "no", +- display_x11->has_glx_swap_interval ? "yes" : "no", +- display_x11->has_glx_texture_from_pixmap ? "yes" : "no", +- display_x11->has_glx_video_sync ? "yes" : "no", +- display_x11->has_glx_buffer_age ? "yes" : "no", +- display_x11->has_glx_sync_control ? "yes" : "no")); ++ display_x11->has_create_context ? "yes" : "no", ++ display_x11->has_create_es2_context ? "yes" : "no", ++ display_x11->has_swap_interval ? "yes" : "no", ++ display_x11->has_texture_from_pixmap ? "yes" : "no", ++ display_x11->has_video_sync ? "yes" : "no", ++ display_x11->has_buffer_age ? "yes" : "no", ++ display_x11->has_sync_control ? "yes" : "no")); + + return TRUE; + } +@@ -1232,10 +1253,10 @@ _gdk_x11_screen_update_visuals_for_gl (G + glXGetConfig (dpy, &visual_list[0], GLX_DEPTH_SIZE, &gl_info[i].depth_size); + glXGetConfig (dpy, &visual_list[0], GLX_STENCIL_SIZE, &gl_info[i].stencil_size); + +- if (display_x11->has_glx_multisample) ++ if (display_x11->has_multisample) + glXGetConfig(dpy, &visual_list[0], GLX_SAMPLE_BUFFERS_ARB, &gl_info[i].num_multisample); + +- if (display_x11->has_glx_visual_rating) ++ if (display_x11->has_visual_rating) + glXGetConfig(dpy, &visual_list[0], GLX_VISUAL_CAVEAT_EXT, &gl_info[i].visual_caveat); + else + gl_info[i].visual_caveat = GLX_NONE_EXT; +@@ -1327,7 +1348,7 @@ gdk_x11_display_make_gl_context_current + return FALSE; + } + +- if (context_x11->is_attached && GDK_X11_DISPLAY (display)->has_glx_swap_interval) ++ if (context_x11->is_attached && GDK_X11_DISPLAY (display)->has_swap_interval) + { + window = gdk_gl_context_get_window (context); + +diff -Nuarp gtk+-3.22.20.old/gdk/x11/gdkglcontext-x11-eglx.c gtk+-3.22.20.new/gdk/x11/gdkglcontext-x11-eglx.c +--- gtk+-3.22.20.old/gdk/x11/gdkglcontext-x11-eglx.c 1970-01-01 01:00:00.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/x11/gdkglcontext-x11-eglx.c 2017-09-21 16:30:39.668074358 +0100 +@@ -0,0 +1,1022 @@ ++/* GDK - The GIMP Drawing Kit ++ * ++ * gdkglcontext-x11.c: X11 specific OpenGL wrappers ++ * ++ * Copyright © 2014 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include "config.h" ++ ++#include "gdkglcontext-x11.h" ++#include "gdkdisplay-x11.h" ++#include "gdkscreen-x11.h" ++ ++#include "gdkx11display.h" ++#include "gdkx11glcontext.h" ++#include "gdkx11screen.h" ++#include "gdkx11window.h" ++#include "gdkx11visual.h" ++#include "gdkvisualprivate.h" ++#include "gdkx11property.h" ++#include <X11/Xatom.h> ++ ++#ifdef HAVE_XCOMPOSITE ++#include <X11/extensions/Xcomposite.h> ++#endif ++ ++#include "gdkinternals.h" ++#include "gdkwindow-x11.h" ++ ++#include "gdkintl.h" ++ ++#include <cairo/cairo-xlib.h> ++ ++#include <epoxy/egl.h> ++ ++struct _GdkX11GLContext ++{ ++ GdkGLContext parent_instance; ++ ++ EGLDisplay egl_display; ++ EGLContext egl_context; ++ EGLConfig egl_config; ++ ++ guint is_attached : 1; ++ guint do_frame_sync : 1; ++}; ++ ++struct _GdkX11GLContextClass ++{ ++ GdkGLContextClass parent_class; ++}; ++ ++typedef struct { ++ EGLDisplay egl_display; ++ EGLConfig egl_config; ++ EGLSurface egl_surface; ++} DrawableInfo; ++ ++static gboolean gdk_x11_display_init_gl (GdkDisplay *display); ++ ++G_DEFINE_TYPE (GdkX11GLContext, gdk_x11_gl_context, GDK_TYPE_GL_CONTEXT) ++ ++static EGLDisplay ++gdk_x11_display_get_egl_display (GdkDisplay *display) ++{ ++ EGLDisplay dpy = NULL; ++ ++ dpy = g_object_get_data (G_OBJECT (display), "-gdk-x11-egl-display"); ++ if (dpy != NULL) ++ return dpy; ++ ++ if (epoxy_has_egl_extension (NULL, "EGL_KHR_platform_base")) ++ { ++ PFNEGLGETPLATFORMDISPLAYPROC getPlatformDisplay = ++ (void *) eglGetProcAddress ("eglGetPlatformDisplay"); ++ ++ if (getPlatformDisplay) ++ dpy = getPlatformDisplay (EGL_PLATFORM_X11_KHR, ++ gdk_x11_display_get_xdisplay (display), ++ NULL); ++ if (dpy != NULL) ++ goto out; ++ } ++ ++ if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base")) ++ { ++ PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = ++ (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT"); ++ ++ if (getPlatformDisplay) ++ dpy = getPlatformDisplay (EGL_PLATFORM_X11_EXT, ++ gdk_x11_display_get_xdisplay (display), ++ NULL); ++ if (dpy != NULL) ++ goto out; ++ } ++ ++ dpy = eglGetDisplay ((EGLNativeDisplayType) gdk_x11_display_get_xdisplay (display)); ++ ++out: ++ if (dpy != NULL) ++ g_object_set_data (G_OBJECT (display), "-gdk-x11-egl-display", dpy); ++ ++ return dpy; ++} ++ ++typedef struct { ++ EGLDisplay egl_display; ++ EGLConfig egl_config; ++ EGLSurface egl_surface; ++ ++ Display *xdisplay; ++ Window dummy_xwin; ++ XVisualInfo *xvisinfo; ++} DummyInfo; ++ ++static void ++dummy_info_free (gpointer data) ++{ ++ DummyInfo *info = data; ++ ++ if (data == NULL) ++ return; ++ ++ if (info->egl_surface != NULL) ++ { ++ eglDestroySurface (info->egl_display, info->egl_surface); ++ info->egl_surface = NULL; ++ } ++ ++ if (info->dummy_xwin != None) ++ { ++ XDestroyWindow (info->xdisplay, info->dummy_xwin); ++ info->dummy_xwin = None; ++ } ++ ++ if (info->xvisinfo != NULL) ++ { ++ XFree (info->xvisinfo); ++ info->xvisinfo = NULL; ++ } ++ ++ g_slice_free (DummyInfo, info); ++} ++ ++static XVisualInfo * ++get_visual_info_for_egl_config (GdkDisplay *display, ++ EGLConfig egl_config) ++{ ++ XVisualInfo visinfo_template; ++ int template_mask = 0; ++ XVisualInfo *visinfo = NULL; ++ int visinfos_count; ++ EGLint visualid, red_size, green_size, blue_size, alpha_size; ++ EGLDisplay egl_display = gdk_x11_display_get_egl_display (display); ++ ++ eglGetConfigAttrib (egl_display, egl_config, EGL_NATIVE_VISUAL_ID, &visualid); ++ ++ if (visualid != 0) ++ { ++ visinfo_template.visualid = visualid; ++ template_mask |= VisualIDMask; ++ } ++ else ++ { ++ /* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID ++ * attribute, so attempt to find the closest match. ++ */ ++ ++ eglGetConfigAttrib (egl_display, egl_config, EGL_RED_SIZE, &red_size); ++ eglGetConfigAttrib (egl_display, egl_config, EGL_GREEN_SIZE, &green_size); ++ eglGetConfigAttrib (egl_display, egl_config, EGL_BLUE_SIZE, &blue_size); ++ eglGetConfigAttrib (egl_display, egl_config, EGL_ALPHA_SIZE, &alpha_size); ++ ++ visinfo_template.depth = red_size + green_size + blue_size + alpha_size; ++ template_mask |= VisualDepthMask; ++ ++ visinfo_template.screen = DefaultScreen (gdk_x11_display_get_xdisplay (display)); ++ template_mask |= VisualScreenMask; ++ } ++ ++ visinfo = XGetVisualInfo (gdk_x11_display_get_xdisplay (display), ++ template_mask, ++ &visinfo_template, ++ &visinfos_count); ++ ++ if (visinfos_count < 1) ++ return NULL; ++ ++ return visinfo; ++} ++ ++static EGLSurface ++gdk_x11_display_get_egl_dummy_surface (GdkDisplay *display, ++ EGLConfig egl_config) ++{ ++ DummyInfo *info; ++ XVisualInfo *xvisinfo; ++ XSetWindowAttributes attrs; ++ ++ info = g_object_get_data (G_OBJECT (display), "-gdk-x11-egl-dummy-surface"); ++ if (info != NULL) ++ return info->egl_surface; ++ ++ xvisinfo = get_visual_info_for_egl_config (display, egl_config); ++ if (xvisinfo == NULL) ++ return NULL; ++ ++ info = g_slice_new (DummyInfo); ++ info->xdisplay = gdk_x11_display_get_xdisplay (display); ++ info->xvisinfo = xvisinfo; ++ info->egl_display = gdk_x11_display_get_egl_display (display); ++ info->egl_config = egl_config; ++ ++ attrs.override_redirect = True; ++ attrs.colormap = XCreateColormap (info->xdisplay, ++ DefaultRootWindow (info->xdisplay), ++ xvisinfo->visual, ++ AllocNone); ++ attrs.border_pixel = 0; ++ ++ info->dummy_xwin = ++ XCreateWindow (info->xdisplay, ++ DefaultRootWindow (info->xdisplay), ++ -100, -100, 1, 1, ++ 0, ++ xvisinfo->depth, ++ CopyFromParent, ++ xvisinfo->visual, ++ CWOverrideRedirect | CWColormap | CWBorderPixel, ++ &attrs); ++ ++ info->egl_surface = ++ eglCreateWindowSurface (info->egl_display, ++ info->egl_config, ++ (EGLNativeWindowType) info->dummy_xwin, ++ NULL); ++ ++ g_object_set_data_full (G_OBJECT (display), "-gdk-x11-egl-dummy-surface", ++ info, ++ dummy_info_free); ++ ++ return info->egl_surface; ++} ++ ++static void ++drawable_info_free (gpointer data) ++{ ++ DrawableInfo *info = data; ++ ++ if (data == NULL) ++ return; ++ ++ if (info->egl_surface != NULL) ++ { ++ eglDestroySurface (info->egl_display, info->egl_surface); ++ info->egl_surface = NULL; ++ } ++ ++ g_slice_free (DrawableInfo, data); ++} ++ ++static EGLSurface ++gdk_x11_window_get_egl_surface (GdkWindow *window, ++ EGLConfig config) ++{ ++ GdkDisplay *display = gdk_window_get_display (window); ++ EGLDisplay egl_display = gdk_x11_display_get_egl_display (display); ++ DrawableInfo *info; ++ ++ info = g_object_get_data (G_OBJECT (window), "-gdk-x11-egl-drawable"); ++ if (info != NULL) ++ return info->egl_surface; ++ ++ info = g_slice_new (DrawableInfo); ++ info->egl_display = egl_display; ++ info->egl_config = config; ++ info->egl_surface = ++ eglCreateWindowSurface (info->egl_display, config, ++ (EGLNativeWindowType) gdk_x11_window_get_xid (window), ++ NULL); ++ ++ g_object_set_data_full (G_OBJECT (window), "-gdk-x11-egl-drawable", ++ info, ++ drawable_info_free); ++ ++ return info->egl_surface; ++} ++ ++void ++gdk_x11_window_invalidate_for_new_frame (GdkWindow *window, ++ cairo_region_t *update_area) ++{ ++ cairo_rectangle_int_t window_rect; ++ GdkDisplay *display = gdk_window_get_display (window); ++ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); ++ GdkX11GLContext *context_x11; ++ EGLint buffer_age; ++ gboolean invalidate_all; ++ ++ /* Minimal update is ok if we're not drawing with gl */ ++ if (window->gl_paint_context == NULL) ++ return; ++ ++ context_x11 = GDK_X11_GL_CONTEXT (window->gl_paint_context); ++ ++ buffer_age = 0; ++ ++ if (display_x11->has_buffer_age) ++ { ++ gdk_gl_context_make_current (window->gl_paint_context); ++ ++ eglQuerySurface (gdk_x11_display_get_egl_display (display), ++ gdk_x11_window_get_egl_surface (window, context_x11->egl_config), ++ EGL_BUFFER_AGE_EXT, ++ &buffer_age); ++ } ++ ++ ++ invalidate_all = FALSE; ++ if (buffer_age == 0 || buffer_age >= 4) ++ { ++ invalidate_all = TRUE; ++ } ++ else ++ { ++ if (buffer_age >= 2) ++ { ++ if (window->old_updated_area[0]) ++ cairo_region_union (update_area, window->old_updated_area[0]); ++ else ++ invalidate_all = TRUE; ++ } ++ if (buffer_age >= 3) ++ { ++ if (window->old_updated_area[1]) ++ cairo_region_union (update_area, window->old_updated_area[1]); ++ else ++ invalidate_all = TRUE; ++ } ++ } ++ ++ if (invalidate_all) ++ { ++ window_rect.x = 0; ++ window_rect.y = 0; ++ window_rect.width = gdk_window_get_width (window); ++ window_rect.height = gdk_window_get_height (window); ++ ++ /* If nothing else is known, repaint everything so that the back ++ buffer is fully up-to-date for the swapbuffer */ ++ cairo_region_union_rectangle (update_area, &window_rect); ++ } ++} ++ ++static void ++gdk_x11_gl_context_end_frame (GdkGLContext *context, ++ cairo_region_t *painted, ++ cairo_region_t *damage) ++{ ++ GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context); ++ GdkWindow *window = gdk_gl_context_get_window (context); ++ GdkDisplay *display = gdk_window_get_display (window); ++ EGLDisplay edpy = gdk_x11_display_get_egl_display (display); ++ EGLSurface esurface; ++ ++ gdk_gl_context_make_current (context); ++ ++ esurface = gdk_x11_window_get_egl_surface (window, context_x11->egl_config); ++ ++ if (GDK_X11_DISPLAY (display)->has_swap_buffers_with_damage) ++ { ++ int i, j, n_rects = cairo_region_num_rectangles (damage); ++ int window_height = gdk_window_get_height (window); ++ gboolean free_rects = FALSE; ++ cairo_rectangle_int_t rect; ++ EGLint *rects; ++ ++ if (n_rects < 16) ++ rects = g_newa (EGLint, n_rects * 4); ++ else ++ { ++ rects = g_new (EGLint, n_rects * 4); ++ free_rects = TRUE; ++ } ++ ++ for (i = 0, j = 0; i < n_rects; i++) ++ { ++ cairo_region_get_rectangle (damage, i, &rect); ++ rects[j++] = rect.x; ++ rects[j++] = window_height - rect.height - rect.y; ++ rects[j++] = rect.width; ++ rects[j++] = rect.height; ++ } ++ ++ eglSwapBuffersWithDamageEXT (edpy, esurface, rects, n_rects); ++ ++ if (free_rects) ++ g_free (rects); ++ } ++ else ++ eglSwapBuffers (edpy, esurface); ++} ++ ++static gboolean ++gdk_x11_gl_context_texture_from_surface (GdkGLContext *context, ++ cairo_surface_t *surface, ++ cairo_region_t *region) ++{ ++ GdkWindow *window = gdk_gl_context_get_window (context); ++ GdkDisplay *display = gdk_window_get_display (window); ++ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); ++ EGLDisplay edpy = gdk_x11_display_get_egl_display (display); ++ EGLImageKHR img = EGL_NO_IMAGE_KHR; ++ const EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; ++ double device_x_offset, device_y_offset; ++ cairo_rectangle_int_t rect; ++ int n_rects, i; ++ int unscaled_window_height; ++ int window_scale; ++ unsigned int texture_id; ++ double sx, sy; ++ float uscale, vscale; ++ GdkTexturedQuad *quads; ++ ++ if (!display_x11->has_image_pixmap || ++ cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB) ++ return FALSE; ++ ++ img = eglCreateImageKHR (edpy, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, ++ (EGLClientBuffer)cairo_xlib_surface_get_drawable (surface), ++ attribs); ++ ++ if (img == EGL_NO_IMAGE_KHR) ++ return FALSE; ++ ++ GDK_NOTE (OPENGL, g_message ("Using eglCreateImageKHR() to draw surface")); ++ ++ window_scale = gdk_window_get_scale_factor (window); ++ gdk_window_get_unscaled_size (window, NULL, &unscaled_window_height); ++ ++ sx = sy = 1; ++ cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy); ++ cairo_surface_get_device_offset (surface, &device_x_offset, &device_y_offset); ++ ++ glGenTextures (1, &texture_id); ++ glBindTexture (GL_TEXTURE_2D, texture_id); ++ ++ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); ++ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ++ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ++ ++ glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, img); ++ ++ glEnable (GL_SCISSOR_TEST); ++ ++ n_rects = cairo_region_num_rectangles (region); ++ quads = g_new (GdkTexturedQuad, n_rects); ++ ++#define FLIP_Y(_y) (unscaled_window_height - (_y)) ++ ++ cairo_region_get_extents (region, &rect); ++ glScissor (rect.x * window_scale, FLIP_Y((rect.y + rect.height) * window_scale), ++ rect.width * window_scale, rect.height * window_scale); ++ ++ for (i = 0; i < n_rects; i++) ++ { ++ int src_x, src_y, src_height, src_width; ++ ++ cairo_region_get_rectangle (region, i, &rect); ++ ++ src_x = rect.x * sx + device_x_offset; ++ src_y = rect.y * sy + device_y_offset; ++ src_width = rect.width * sx; ++ src_height = rect.height * sy; ++ ++ uscale = 1.0 / cairo_xlib_surface_get_width (surface); ++ vscale = 1.0 / cairo_xlib_surface_get_height (surface); ++ ++ { ++ GdkTexturedQuad quad = { ++ rect.x * window_scale, FLIP_Y(rect.y * window_scale), ++ (rect.x + rect.width) * window_scale, FLIP_Y((rect.y + rect.height) * window_scale), ++ uscale * src_x, vscale * src_y, ++ uscale * (src_x + src_width), vscale * (src_y + src_height), ++ }; ++ ++ quads[i] = quad; ++ } ++ } ++ ++#undef FLIP_Y ++ ++ gdk_gl_texture_quads (context, GL_TEXTURE_2D, n_rects, quads, FALSE); ++ g_free (quads); ++ ++ glDisable (GL_SCISSOR_TEST); ++ ++ eglDestroyImageKHR (edpy, img); ++ ++ glDeleteTextures (1, &texture_id); ++ ++ return TRUE; ++} ++ ++#define N_EGL_ATTRS 16 ++ ++static gboolean ++gdk_x11_gl_context_realize (GdkGLContext *context, ++ GError **error) ++{ ++ GdkX11Display *display_x11; ++ GdkDisplay *display; ++ GdkX11GLContext *context_x11; ++ GdkGLContext *share; ++ GdkWindow *window; ++ gboolean debug_bit, compat_bit, legacy_bit, es_bit; ++ int major, minor; ++ EGLint context_attrs[N_EGL_ATTRS]; ++ ++ window = gdk_gl_context_get_window (context); ++ display = gdk_window_get_display (window); ++ ++ if (!gdk_x11_display_init_gl (display)) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, ++ _("No GL implementation available")); ++ return FALSE; ++ } ++ ++ context_x11 = GDK_X11_GL_CONTEXT (context); ++ display_x11 = GDK_X11_DISPLAY (display); ++ share = gdk_gl_context_get_shared_context (context); ++ ++ gdk_gl_context_get_required_version (context, &major, &minor); ++ debug_bit = gdk_gl_context_get_debug_enabled (context); ++ compat_bit = gdk_gl_context_get_forward_compatible (context); ++ ++ legacy_bit = !display_x11->has_create_context || ++ (_gdk_gl_flags & GDK_GL_LEGACY) != 0; ++ ++ /* XXX: Force GLES */ ++ es_bit = TRUE; ++ ++ if (es_bit) ++ { ++ /* XXX: Force GLES 2.0 */ ++ context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION; ++ context_attrs[1] = 2; ++ context_attrs[2] = EGL_NONE; ++ ++ eglBindAPI (EGL_OPENGL_ES_API); ++ } ++ else ++ { ++ int flags = 0; ++ ++ if (!display_x11->has_create_context) ++ { ++ context_attrs[0] = EGL_NONE; ++ } ++ else ++ { ++ if (debug_bit) ++ flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; ++ if (compat_bit) ++ flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; ++ ++ context_attrs[0] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; ++ context_attrs[1] = legacy_bit ++ ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR ++ : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; ++ context_attrs[2] = EGL_CONTEXT_MAJOR_VERSION_KHR; ++ context_attrs[3] = legacy_bit ? 3 : major; ++ context_attrs[4] = EGL_CONTEXT_MINOR_VERSION_KHR; ++ context_attrs[5] = legacy_bit ? 0 : minor; ++ context_attrs[6] = EGL_CONTEXT_FLAGS_KHR; ++ context_attrs[7] = flags; ++ context_attrs[8] = EGL_NONE; ++ } ++ ++ eglBindAPI (EGL_OPENGL_API); ++ } ++ ++ GDK_NOTE (OPENGL, ++ g_message ("Creating EGL context (version:%d.%d, debug:%s, forward:%s, legacy:%s, es:%s)", ++ 2, 0, ++ debug_bit ? "yes" : "no", ++ compat_bit ? "yes" : "no", ++ legacy_bit ? "yes" : "no", ++ es_bit ? "yes" : "no")); ++ ++ context_x11->egl_context = ++ eglCreateContext (gdk_x11_display_get_egl_display (display), ++ context_x11->egl_config, ++ share != NULL ? GDK_X11_GL_CONTEXT (share)->egl_context ++ : EGL_NO_CONTEXT, ++ context_attrs); ++ ++ /* If we're not asking for a GLES context, and we don't have the legacy bit set ++ * already, try again with a legacy context ++ */ ++ if (context_x11->egl_context == NULL && !es_bit && !legacy_bit) ++ { ++ context_attrs[1] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; ++ context_attrs[3] = 3; ++ context_attrs[5] = 0; ++ ++ legacy_bit = TRUE; ++ es_bit = FALSE; ++ ++ GDK_NOTE (OPENGL, ++ g_message ("Context creation failed; trying legacy EGL context")); ++ ++ context_x11->egl_context = ++ eglCreateContext (gdk_x11_display_get_egl_display (display), ++ context_x11->egl_config, ++ share != NULL ? GDK_X11_GL_CONTEXT (share)->egl_context ++ : EGL_NO_CONTEXT, ++ context_attrs); ++ } ++ ++ if (context_x11->egl_context == NULL) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, ++ _("Unable to create a GL context")); ++ return FALSE; ++ } ++ ++ gdk_gl_context_set_is_legacy (context, legacy_bit); ++ gdk_gl_context_set_use_es (context, es_bit); ++ ++ GDK_NOTE (OPENGL, ++ g_message ("Realized EGL context[%p]", ++ context_x11->egl_context)); ++ ++ return TRUE; ++} ++ ++static void ++gdk_x11_gl_context_dispose (GObject *gobject) ++{ ++ GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (gobject); ++ ++ if (context_x11->egl_context != NULL) ++ { ++ GdkGLContext *context = GDK_GL_CONTEXT (gobject); ++ GdkDisplay *display = gdk_gl_context_get_display (context); ++ ++ if (eglGetCurrentContext () != context_x11->egl_context) ++ eglMakeCurrent (gdk_x11_display_get_egl_display (display), ++ EGL_NO_SURFACE, ++ EGL_NO_SURFACE, ++ EGL_NO_CONTEXT); ++ ++ GDK_NOTE (OPENGL, g_message ("Destroying EGL context")); ++ eglDestroyContext (gdk_x11_display_get_egl_display (display), ++ context_x11->egl_context); ++ context_x11->egl_context = NULL; ++ } ++ ++ G_OBJECT_CLASS (gdk_x11_gl_context_parent_class)->dispose (gobject); ++} ++ ++static void ++gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass) ++{ ++ GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass); ++ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ++ ++ context_class->realize = gdk_x11_gl_context_realize; ++ context_class->end_frame = gdk_x11_gl_context_end_frame; ++ context_class->texture_from_surface = gdk_x11_gl_context_texture_from_surface; ++ ++ gobject_class->dispose = gdk_x11_gl_context_dispose; ++} ++ ++static void ++gdk_x11_gl_context_init (GdkX11GLContext *self) ++{ ++ self->do_frame_sync = TRUE; ++} ++ ++static gboolean ++gdk_x11_display_init_gl (GdkDisplay *display) ++{ ++ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); ++ EGLDisplay edpy; ++ int major, minor; ++ ++ if (display_x11->supports_gl) ++ return TRUE; ++ ++ if (_gdk_gl_flags & GDK_GL_DISABLE) ++ return FALSE; ++ ++ edpy = gdk_x11_display_get_egl_display (display); ++ if (edpy == NULL) ++ return FALSE; ++ ++ if (!eglInitialize (edpy, &major, &minor)) ++ return FALSE; ++ ++ if (!eglBindAPI (EGL_OPENGL_ES_API)) ++ return FALSE; ++ ++ display_x11->supports_gl = TRUE; ++ ++ display_x11->glx_version = major * 10 + minor; ++ display_x11->glx_error_base = 0; ++ display_x11->glx_event_base = 0; ++ ++ display_x11->has_create_context = ++ epoxy_has_egl_extension (edpy, "EGL_KHR_create_context"); ++ display_x11->has_create_es2_context = FALSE; ++ display_x11->has_swap_interval = TRUE; ++ display_x11->has_texture_from_pixmap = FALSE; ++ display_x11->has_image_pixmap = ++ epoxy_has_egl_extension (edpy, "EGL_KHR_image_pixmap"); ++ display_x11->has_video_sync = FALSE; ++ display_x11->has_buffer_age = ++ epoxy_has_egl_extension (edpy, "EGL_EXT_buffer_age"); ++ display_x11->has_sync_control = FALSE; ++ display_x11->has_multisample = FALSE; ++ display_x11->has_visual_rating = FALSE; ++ display_x11->has_swap_buffers_with_damage = ++ epoxy_has_egl_extension (edpy, "EGL_EXT_swap_buffers_with_damage"); ++ ++ GDK_NOTE (OPENGL, ++ g_message ("EGL X11 found\n" ++ " - Vendor: %s\n" ++ " - Version: %s\n" ++ " - Client APIs: %s\n" ++ " - Checked extensions:\n" ++ "\t* EGL_KHR_create_context: %s\n" ++ "\t* EGL_EXT_buffer_age: %s\n" ++ "\t* EGL_EXT_swap_buffers_with_damage: %s\n" ++ "\t* EGL_KHR_image_pixmap: %s", ++ eglQueryString (edpy, EGL_VENDOR), ++ eglQueryString (edpy, EGL_VERSION), ++ eglQueryString (edpy, EGL_CLIENT_APIS), ++ display_x11->has_create_context ? "yes" : "no", ++ display_x11->has_buffer_age ? "yes" : "no", ++ display_x11->has_swap_buffers_with_damage ? "yes" : "no", ++ display_x11->has_image_pixmap ? "yes" : "no")); ++ ++ return TRUE; ++} ++ ++void ++_gdk_x11_screen_update_visuals_for_gl (GdkScreen *screen) ++{ ++ /* No-op; there's just no way to do the same trick we use ++ * with GLX to select an appropriate visual and cache it. ++ * For EGL-X11 we always pick the first visual and stick ++ * with it. ++ */ ++} ++ ++#define MAX_EGL_ATTRS 30 ++ ++static gboolean ++find_egl_config_for_window (GdkWindow *window, ++ EGLConfig *config_out, ++ GError **error) ++{ ++ GdkDisplay *display = gdk_window_get_display (window); ++ GdkVisual *visual = gdk_window_get_visual (window); ++ EGLint attrs[MAX_EGL_ATTRS]; ++ EGLint count; ++ EGLDisplay egl_display; ++ EGLConfig *configs; ++ gboolean use_rgba; ++ int i = 0; ++ ++ attrs[i++] = EGL_SURFACE_TYPE; ++ attrs[i++] = EGL_WINDOW_BIT; ++ ++ attrs[i++] = EGL_COLOR_BUFFER_TYPE; ++ attrs[i++] = EGL_RGB_BUFFER; ++ ++ attrs[i++] = EGL_RED_SIZE; ++ attrs[i++] = 1; ++ attrs[i++] = EGL_GREEN_SIZE; ++ attrs[i++] = 1; ++ attrs[i++] = EGL_BLUE_SIZE; ++ attrs[i++] = 1; ++ ++ use_rgba = (visual == gdk_screen_get_rgba_visual (gdk_window_get_screen (window))); ++ ++ if (use_rgba) ++ { ++ attrs[i++] = EGL_ALPHA_SIZE; ++ attrs[i++] = 1; ++ } ++ else ++ { ++ attrs[i++] = EGL_ALPHA_SIZE; ++ attrs[i++] = EGL_DONT_CARE; ++ } ++ ++ attrs[i++] = EGL_NONE; ++ g_assert (i < MAX_EGL_ATTRS); ++ ++ egl_display = gdk_x11_display_get_egl_display (display); ++ if (!eglChooseConfig (egl_display, attrs, NULL, 0, &count) || count < 1) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, ++ GDK_GL_ERROR_UNSUPPORTED_FORMAT, ++ _("No available configurations for the given pixel format")); ++ return FALSE; ++ } ++ ++ configs = g_new (EGLConfig, count); ++ if (!eglChooseConfig (egl_display, attrs, configs, count, &count) || count < 1) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, ++ GDK_GL_ERROR_UNSUPPORTED_FORMAT, ++ _("No available configurations for the given pixel format")); ++ g_free (configs); ++ return FALSE; ++ } ++ ++ if (config_out != NULL) ++ *config_out = configs[0]; ++ ++ g_free (configs); ++ ++ return TRUE; ++} ++ ++GdkGLContext * ++gdk_x11_window_create_gl_context (GdkWindow *window, ++ gboolean attached, ++ GdkGLContext *share, ++ GError **error) ++{ ++ GdkDisplay *display; ++ GdkX11GLContext *context; ++ EGLConfig config; ++ ++ display = gdk_window_get_display (window); ++ ++ if (!gdk_x11_display_init_gl (display)) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, ++ GDK_GL_ERROR_NOT_AVAILABLE, ++ _("No GL implementation is available")); ++ return NULL; ++ } ++ ++ if (!find_egl_config_for_window (window, &config, error)) ++ return NULL; ++ ++ context = g_object_new (GDK_TYPE_X11_GL_CONTEXT, ++ "display", display, ++ "window", window, ++ "shared-context", share, ++ NULL); ++ ++ context->egl_config = config; ++ context->is_attached = attached; ++ ++ return GDK_GL_CONTEXT (context); ++} ++ ++static inline gboolean ++window_is_composited (GdkDisplay *display, ++ GdkWindow *window) ++{ ++#ifdef HAVE_XCOMPOSITE ++ Display *dpy = GDK_DISPLAY_XDISPLAY (display); ++ Pixmap pixmap; ++ ++ gdk_x11_display_error_trap_push (display); ++ ++ /* This is kind of an expensive check, because there's no XComposite ++ * API to check if a Window has been unredirected. We check if there's ++ * a named Pixmap for it, and if we fail it means that the screen is ++ * not composited or the window is unredirected or not visible ++ */ ++ pixmap = XCompositeNameWindowPixmap (dpy, GDK_WINDOW_XID (window)); ++ ++ XSync (dpy, False); ++ ++ if (gdk_x11_display_error_trap_pop (display)) ++ return FALSE; ++ ++ XFreePixmap (dpy, pixmap); ++ ++ return TRUE; ++#else ++ return FALSE; ++#endif ++} ++ ++ ++gboolean ++gdk_x11_display_make_gl_context_current (GdkDisplay *display, ++ GdkGLContext *context) ++{ ++ GdkX11GLContext *context_x11; ++ GdkWindow *window; ++ gboolean do_frame_sync = FALSE; ++ EGLSurface surface; ++ EGLDisplay egl_display; ++ ++ egl_display = gdk_x11_display_get_egl_display (display); ++ ++ if (context == NULL) ++ { ++ eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); ++ return TRUE; ++ } ++ ++ window = gdk_gl_context_get_window (context); ++ context_x11 = GDK_X11_GL_CONTEXT (context); ++ if (context_x11->egl_context == NULL) ++ { ++ g_critical ("No EGL context associated to the GdkGLContext; you must " ++ "call gdk_gl_context_realize() first."); ++ return FALSE; ++ } ++ ++ GDK_NOTE (OPENGL, ++ g_message ("Making EGL context current")); ++ ++ if (context_x11->is_attached) ++ surface = gdk_x11_window_get_egl_surface (window, context_x11->egl_config); ++ else ++ surface = gdk_x11_display_get_egl_dummy_surface (display, context_x11->egl_config); ++ ++ if (!eglMakeCurrent (egl_display, surface, surface, context_x11->egl_context)) ++ { ++ GDK_NOTE (OPENGL, ++ g_message ("Making EGL context current failed")); ++ return FALSE; ++ } ++ ++ if (context_x11->is_attached) ++ { ++ GdkScreen *screen = gdk_window_get_screen (window); ++ gboolean is_composited = gdk_screen_is_composited (screen); ++ GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window); ++ ++ /* If the WM is compositing and the window is redirected there is no ++ * particular need to delay the swap when drawing on the offscreen, ++ * rendering to the screen happens later anyway, and its up to the ++ * compositor to sync that to the vblank. ++ */ ++ if (is_composited) ++ { ++ GdkAtom atom = gdk_atom_intern_static_string ("_GTK_WINDOW_UNREDIRECTED"); ++ ++ if (toplevel && gdk_x11_screen_supports_net_wm_hint (screen, atom)) ++ is_composited = !toplevel->unredirected; ++ else if (gdk_window_get_state (window) & GDK_WINDOW_STATE_FULLSCREEN) ++ is_composited = window_is_composited (display, window->impl_window); ++ } ++ ++ do_frame_sync = !is_composited; ++ ++ if (do_frame_sync != context_x11->do_frame_sync) ++ { ++ context_x11->do_frame_sync = do_frame_sync; ++ ++ if (do_frame_sync) ++ eglSwapInterval (egl_display, 1); ++ else ++ eglSwapInterval (egl_display, 0); ++ } ++ } ++ ++ return TRUE; ++} ++ ++/** ++ * gdk_x11_display_get_glx_version: ++ * @display: a #GdkDisplay ++ * @major: (out): return location for the GLX major version ++ * @minor: (out): return location for the GLX minor version ++ * ++ * Retrieves the version of the GLX implementation. ++ * ++ * Returns: %TRUE if GLX is available ++ * ++ * Since: 3.16 ++ */ ++gboolean ++gdk_x11_display_get_glx_version (GdkDisplay *display, ++ gint *major, ++ gint *minor) ++{ ++ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); ++ ++ if (!GDK_IS_X11_DISPLAY (display)) ++ return FALSE; ++ ++ if (!gdk_x11_display_init_gl (display)) ++ return FALSE; ++ ++ if (major != NULL) ++ *major = GDK_X11_DISPLAY (display)->glx_version / 10; ++ if (minor != NULL) ++ *minor = GDK_X11_DISPLAY (display)->glx_version % 10; ++ ++ return TRUE; ++} +diff -Nuarp gtk+-3.22.20.old/gdk/x11/gdkglcontext-x11-eglx.c.orig gtk+-3.22.20.new/gdk/x11/gdkglcontext-x11-eglx.c.orig +--- gtk+-3.22.20.old/gdk/x11/gdkglcontext-x11-eglx.c.orig 1970-01-01 01:00:00.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/x11/gdkglcontext-x11-eglx.c.orig 2017-09-21 16:30:24.344036202 +0100 +@@ -0,0 +1,1012 @@ ++/* GDK - The GIMP Drawing Kit ++ * ++ * gdkglcontext-x11.c: X11 specific OpenGL wrappers ++ * ++ * Copyright © 2014 Emmanuele Bassi ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include "config.h" ++ ++#include "gdkglcontext-x11.h" ++#include "gdkdisplay-x11.h" ++#include "gdkscreen-x11.h" ++ ++#include "gdkx11display.h" ++#include "gdkx11glcontext.h" ++#include "gdkx11screen.h" ++#include "gdkx11window.h" ++#include "gdkx11visual.h" ++#include "gdkvisualprivate.h" ++#include "gdkx11property.h" ++#include <X11/Xatom.h> ++ ++#ifdef HAVE_XCOMPOSITE ++#include <X11/extensions/Xcomposite.h> ++#endif ++ ++#include "gdkinternals.h" ++ ++#include "gdkintl.h" ++ ++#include <cairo/cairo-xlib.h> ++ ++#include <epoxy/egl.h> ++ ++struct _GdkX11GLContext ++{ ++ GdkGLContext parent_instance; ++ ++ EGLDisplay egl_display; ++ EGLContext egl_context; ++ EGLConfig egl_config; ++ ++ guint is_attached : 1; ++ guint do_frame_sync : 1; ++}; ++ ++struct _GdkX11GLContextClass ++{ ++ GdkGLContextClass parent_class; ++}; ++ ++typedef struct { ++ EGLDisplay egl_display; ++ EGLConfig egl_config; ++ EGLSurface egl_surface; ++} DrawableInfo; ++ ++static gboolean gdk_x11_display_init_gl (GdkDisplay *display); ++ ++G_DEFINE_TYPE (GdkX11GLContext, gdk_x11_gl_context, GDK_TYPE_GL_CONTEXT) ++ ++static EGLDisplay ++gdk_x11_display_get_egl_display (GdkDisplay *display) ++{ ++ EGLDisplay dpy = NULL; ++ ++ dpy = g_object_get_data (G_OBJECT (display), "-gdk-x11-egl-display"); ++ if (dpy != NULL) ++ return dpy; ++ ++ if (epoxy_has_egl_extension (NULL, "EGL_KHR_platform_base")) ++ { ++ PFNEGLGETPLATFORMDISPLAYPROC getPlatformDisplay = ++ (void *) eglGetProcAddress ("eglGetPlatformDisplay"); ++ ++ if (getPlatformDisplay) ++ dpy = getPlatformDisplay (EGL_PLATFORM_X11_KHR, ++ gdk_x11_display_get_xdisplay (display), ++ NULL); ++ if (dpy != NULL) ++ goto out; ++ } ++ ++ if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base")) ++ { ++ PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = ++ (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT"); ++ ++ if (getPlatformDisplay) ++ dpy = getPlatformDisplay (EGL_PLATFORM_X11_EXT, ++ gdk_x11_display_get_xdisplay (display), ++ NULL); ++ if (dpy != NULL) ++ goto out; ++ } ++ ++ dpy = eglGetDisplay ((EGLNativeDisplayType) gdk_x11_display_get_xdisplay (display)); ++ ++out: ++ if (dpy != NULL) ++ g_object_set_data (G_OBJECT (display), "-gdk-x11-egl-display", dpy); ++ ++ return dpy; ++} ++ ++typedef struct { ++ EGLDisplay egl_display; ++ EGLConfig egl_config; ++ EGLSurface egl_surface; ++ ++ Display *xdisplay; ++ Window dummy_xwin; ++ XVisualInfo *xvisinfo; ++} DummyInfo; ++ ++static void ++dummy_info_free (gpointer data) ++{ ++ DummyInfo *info = data; ++ ++ if (data == NULL) ++ return; ++ ++ if (info->egl_surface != NULL) ++ { ++ eglDestroySurface (info->egl_display, info->egl_surface); ++ info->egl_surface = NULL; ++ } ++ ++ if (info->dummy_xwin != None) ++ { ++ XDestroyWindow (info->xdisplay, info->dummy_xwin); ++ info->dummy_xwin = None; ++ } ++ ++ if (info->xvisinfo != NULL) ++ { ++ XFree (info->xvisinfo); ++ info->xvisinfo = NULL; ++ } ++ ++ g_slice_free (DummyInfo, info); ++} ++ ++static XVisualInfo * ++get_visual_info_for_egl_config (GdkDisplay *display, ++ EGLConfig egl_config) ++{ ++ XVisualInfo visinfo_template; ++ int template_mask = 0; ++ XVisualInfo *visinfo = NULL; ++ int visinfos_count; ++ EGLint visualid, red_size, green_size, blue_size, alpha_size; ++ EGLDisplay egl_display = gdk_x11_display_get_egl_display (display); ++ ++ eglGetConfigAttrib (egl_display, egl_config, EGL_NATIVE_VISUAL_ID, &visualid); ++ ++ if (visualid != 0) ++ { ++ visinfo_template.visualid = visualid; ++ template_mask |= VisualIDMask; ++ } ++ else ++ { ++ /* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID ++ * attribute, so attempt to find the closest match. ++ */ ++ ++ eglGetConfigAttrib (egl_display, egl_config, EGL_RED_SIZE, &red_size); ++ eglGetConfigAttrib (egl_display, egl_config, EGL_GREEN_SIZE, &green_size); ++ eglGetConfigAttrib (egl_display, egl_config, EGL_BLUE_SIZE, &blue_size); ++ eglGetConfigAttrib (egl_display, egl_config, EGL_ALPHA_SIZE, &alpha_size); ++ ++ visinfo_template.depth = red_size + green_size + blue_size + alpha_size; ++ template_mask |= VisualDepthMask; ++ ++ visinfo_template.screen = DefaultScreen (gdk_x11_display_get_xdisplay (display)); ++ template_mask |= VisualScreenMask; ++ } ++ ++ visinfo = XGetVisualInfo (gdk_x11_display_get_xdisplay (display), ++ template_mask, ++ &visinfo_template, ++ &visinfos_count); ++ ++ if (visinfos_count < 1) ++ return NULL; ++ ++ return visinfo; ++} ++ ++static EGLSurface ++gdk_x11_display_get_egl_dummy_surface (GdkDisplay *display, ++ EGLConfig egl_config) ++{ ++ DummyInfo *info; ++ XVisualInfo *xvisinfo; ++ XSetWindowAttributes attrs; ++ ++ info = g_object_get_data (G_OBJECT (display), "-gdk-x11-egl-dummy-surface"); ++ if (info != NULL) ++ return info->egl_surface; ++ ++ xvisinfo = get_visual_info_for_egl_config (display, egl_config); ++ if (xvisinfo == NULL) ++ return NULL; ++ ++ info = g_slice_new (DummyInfo); ++ info->xdisplay = gdk_x11_display_get_xdisplay (display); ++ info->xvisinfo = xvisinfo; ++ info->egl_display = gdk_x11_display_get_egl_display (display); ++ info->egl_config = egl_config; ++ ++ attrs.override_redirect = True; ++ attrs.colormap = XCreateColormap (info->xdisplay, ++ DefaultRootWindow (info->xdisplay), ++ xvisinfo->visual, ++ AllocNone); ++ attrs.border_pixel = 0; ++ ++ info->dummy_xwin = ++ XCreateWindow (info->xdisplay, ++ DefaultRootWindow (info->xdisplay), ++ -100, -100, 1, 1, ++ 0, ++ xvisinfo->depth, ++ CopyFromParent, ++ xvisinfo->visual, ++ CWOverrideRedirect | CWColormap | CWBorderPixel, ++ &attrs); ++ ++ info->egl_surface = ++ eglCreateWindowSurface (info->egl_display, ++ info->egl_config, ++ (EGLNativeWindowType) info->dummy_xwin, ++ NULL); ++ ++ g_object_set_data_full (G_OBJECT (display), "-gdk-x11-egl-dummy-surface", ++ info, ++ dummy_info_free); ++ ++ return info->egl_surface; ++} ++ ++static void ++drawable_info_free (gpointer data) ++{ ++ DrawableInfo *info = data; ++ ++ if (data == NULL) ++ return; ++ ++ if (info->egl_surface != NULL) ++ { ++ eglDestroySurface (info->egl_display, info->egl_surface); ++ info->egl_surface = NULL; ++ } ++ ++ g_slice_free (DrawableInfo, data); ++} ++ ++static EGLSurface ++gdk_x11_window_get_egl_surface (GdkWindow *window, ++ EGLConfig config) ++{ ++ GdkDisplay *display = gdk_window_get_display (window); ++ EGLDisplay egl_display = gdk_x11_display_get_egl_display (display); ++ DrawableInfo *info; ++ ++ info = g_object_get_data (G_OBJECT (window), "-gdk-x11-egl-drawable"); ++ if (info != NULL) ++ return info->egl_surface; ++ ++ info = g_slice_new (DrawableInfo); ++ info->egl_display = egl_display; ++ info->egl_config = config; ++ info->egl_surface = ++ eglCreateWindowSurface (info->egl_display, config, ++ (EGLNativeWindowType) gdk_x11_window_get_xid (window), ++ NULL); ++ ++ g_object_set_data_full (G_OBJECT (window), "-gdk-x11-egl-drawable", ++ info, ++ drawable_info_free); ++ ++ return info->egl_surface; ++} ++ ++void ++gdk_x11_window_invalidate_for_new_frame (GdkWindow *window, ++ cairo_region_t *update_area) ++{ ++ cairo_rectangle_int_t window_rect; ++ GdkDisplay *display = gdk_window_get_display (window); ++ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); ++ GdkX11GLContext *context_x11; ++ EGLint buffer_age; ++ gboolean invalidate_all; ++ ++ /* Minimal update is ok if we're not drawing with gl */ ++ if (window->gl_paint_context == NULL) ++ return; ++ ++ context_x11 = GDK_X11_GL_CONTEXT (window->gl_paint_context); ++ ++ buffer_age = 0; ++ ++ if (display_x11->has_buffer_age) ++ { ++ gdk_gl_context_make_current (window->gl_paint_context); ++ ++ eglQuerySurface (gdk_x11_display_get_egl_display (display), ++ gdk_x11_window_get_egl_surface (window, context_x11->egl_config), ++ EGL_BUFFER_AGE_EXT, ++ &buffer_age); ++ } ++ ++ ++ invalidate_all = FALSE; ++ if (buffer_age == 0 || buffer_age >= 4) ++ { ++ invalidate_all = TRUE; ++ } ++ else ++ { ++ if (buffer_age >= 2) ++ { ++ if (window->old_updated_area[0]) ++ cairo_region_union (update_area, window->old_updated_area[0]); ++ else ++ invalidate_all = TRUE; ++ } ++ if (buffer_age >= 3) ++ { ++ if (window->old_updated_area[1]) ++ cairo_region_union (update_area, window->old_updated_area[1]); ++ else ++ invalidate_all = TRUE; ++ } ++ } ++ ++ if (invalidate_all) ++ { ++ window_rect.x = 0; ++ window_rect.y = 0; ++ window_rect.width = gdk_window_get_width (window); ++ window_rect.height = gdk_window_get_height (window); ++ ++ /* If nothing else is known, repaint everything so that the back ++ buffer is fully up-to-date for the swapbuffer */ ++ cairo_region_union_rectangle (update_area, &window_rect); ++ } ++} ++ ++static void ++gdk_x11_gl_context_end_frame (GdkGLContext *context, ++ cairo_region_t *painted, ++ cairo_region_t *damage) ++{ ++ GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context); ++ GdkWindow *window = gdk_gl_context_get_window (context); ++ GdkDisplay *display = gdk_window_get_display (window); ++ EGLDisplay edpy = gdk_x11_display_get_egl_display (display); ++ EGLSurface esurface; ++ ++ gdk_gl_context_make_current (context); ++ ++ esurface = gdk_x11_window_get_egl_surface (window, context_x11->egl_config); ++ ++ if (GDK_X11_DISPLAY (display)->has_swap_buffers_with_damage) ++ { ++ int i, j, n_rects = cairo_region_num_rectangles (damage); ++ int window_height = gdk_window_get_height (window); ++ gboolean free_rects = FALSE; ++ cairo_rectangle_int_t rect; ++ EGLint *rects; ++ ++ if (n_rects < 16) ++ rects = g_newa (EGLint, n_rects * 4); ++ else ++ { ++ rects = g_new (EGLint, n_rects * 4); ++ free_rects = TRUE; ++ } ++ ++ for (i = 0, j = 0; i < n_rects; i++) ++ { ++ cairo_region_get_rectangle (damage, i, &rect); ++ rects[j++] = rect.x; ++ rects[j++] = window_height - rect.height - rect.y; ++ rects[j++] = rect.width; ++ rects[j++] = rect.height; ++ } ++ ++ eglSwapBuffersWithDamageEXT (edpy, esurface, rects, n_rects); ++ ++ if (free_rects) ++ g_free (rects); ++ } ++ else ++ eglSwapBuffers (edpy, esurface); ++} ++ ++static gboolean ++gdk_x11_gl_context_texture_from_surface (GdkGLContext *context, ++ cairo_surface_t *surface, ++ cairo_region_t *region) ++{ ++ GdkWindow *window = gdk_gl_context_get_window (context); ++ GdkDisplay *display = gdk_window_get_display (window); ++ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); ++ EGLDisplay edpy = gdk_x11_display_get_egl_display (display); ++ EGLImageKHR img = EGL_NO_IMAGE_KHR; ++ const EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; ++ double device_x_offset, device_y_offset; ++ cairo_rectangle_int_t rect; ++ int n_rects, i; ++ int unscaled_window_height; ++ int window_scale; ++ unsigned int texture_id; ++ double sx, sy; ++ float uscale, vscale; ++ GdkTexturedQuad *quads; ++ ++ if (!display_x11->has_image_pixmap || ++ cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB) ++ return FALSE; ++ ++ img = eglCreateImageKHR (edpy, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, ++ (EGLClientBuffer)cairo_xlib_surface_get_drawable (surface), ++ attribs); ++ ++ if (img == EGL_NO_IMAGE_KHR) ++ return FALSE; ++ ++ GDK_NOTE (OPENGL, g_message ("Using eglCreateImageKHR() to draw surface")); ++ ++ window_scale = gdk_window_get_scale_factor (window); ++ gdk_window_get_unscaled_size (window, NULL, &unscaled_window_height); ++ ++ sx = sy = 1; ++ cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy); ++ cairo_surface_get_device_offset (surface, &device_x_offset, &device_y_offset); ++ ++ glGenTextures (1, &texture_id); ++ glBindTexture (GL_TEXTURE_2D, texture_id); ++ ++ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); ++ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ++ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ++ ++ glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, img); ++ ++ glEnable (GL_SCISSOR_TEST); ++ ++ n_rects = cairo_region_num_rectangles (region); ++ quads = g_new (GdkTexturedQuad, n_rects); ++ ++#define FLIP_Y(_y) (unscaled_window_height - (_y)) ++ ++ cairo_region_get_extents (region, &rect); ++ glScissor (rect.x * window_scale, FLIP_Y((rect.y + rect.height) * window_scale), ++ rect.width * window_scale, rect.height * window_scale); ++ ++ for (i = 0; i < n_rects; i++) ++ { ++ int src_x, src_y, src_height, src_width; ++ ++ cairo_region_get_rectangle (region, i, &rect); ++ ++ src_x = rect.x * sx + device_x_offset; ++ src_y = rect.y * sy + device_y_offset; ++ src_width = rect.width * sx; ++ src_height = rect.height * sy; ++ ++ uscale = 1.0 / cairo_xlib_surface_get_width (surface); ++ vscale = 1.0 / cairo_xlib_surface_get_height (surface); ++ ++ { ++ GdkTexturedQuad quad = { ++ rect.x * window_scale, FLIP_Y(rect.y * window_scale), ++ (rect.x + rect.width) * window_scale, FLIP_Y((rect.y + rect.height) * window_scale), ++ uscale * src_x, vscale * src_y, ++ uscale * (src_x + src_width), vscale * (src_y + src_height), ++ }; ++ ++ quads[i] = quad; ++ } ++ } ++ ++#undef FLIP_Y ++ ++ gdk_gl_texture_quads (context, GL_TEXTURE_2D, n_rects, quads, FALSE); ++ g_free (quads); ++ ++ glDisable (GL_SCISSOR_TEST); ++ ++ eglDestroyImageKHR (edpy, img); ++ ++ glDeleteTextures (1, &texture_id); ++ ++ return TRUE; ++} ++ ++#define N_EGL_ATTRS 16 ++ ++static gboolean ++gdk_x11_gl_context_realize (GdkGLContext *context, ++ GError **error) ++{ ++ GdkX11Display *display_x11; ++ GdkDisplay *display; ++ GdkX11GLContext *context_x11; ++ GdkGLContext *share; ++ GdkWindow *window; ++ gboolean debug_bit, compat_bit, legacy_bit, es_bit; ++ int major, minor; ++ EGLint context_attrs[N_EGL_ATTRS]; ++ ++ window = gdk_gl_context_get_window (context); ++ display = gdk_window_get_display (window); ++ ++ if (!gdk_x11_display_init_gl (display)) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, ++ _("No GL implementation available")); ++ return FALSE; ++ } ++ ++ context_x11 = GDK_X11_GL_CONTEXT (context); ++ display_x11 = GDK_X11_DISPLAY (display); ++ share = gdk_gl_context_get_shared_context (context); ++ ++ gdk_gl_context_get_required_version (context, &major, &minor); ++ debug_bit = gdk_gl_context_get_debug_enabled (context); ++ compat_bit = gdk_gl_context_get_forward_compatible (context); ++ ++ legacy_bit = !display_x11->has_create_context || ++ (_gdk_gl_flags & GDK_GL_LEGACY) != 0; ++ ++ /* XXX: Force GLES */ ++ es_bit = TRUE; ++ ++ if (es_bit) ++ { ++ /* XXX: Force GLES 2.0 */ ++ context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION; ++ context_attrs[1] = 2; ++ context_attrs[2] = EGL_NONE; ++ ++ eglBindAPI (EGL_OPENGL_ES_API); ++ } ++ else ++ { ++ int flags = 0; ++ ++ if (!display_x11->has_create_context) ++ { ++ context_attrs[0] = EGL_NONE; ++ } ++ else ++ { ++ if (debug_bit) ++ flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; ++ if (compat_bit) ++ flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; ++ ++ context_attrs[0] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; ++ context_attrs[1] = legacy_bit ++ ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR ++ : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; ++ context_attrs[2] = EGL_CONTEXT_MAJOR_VERSION_KHR; ++ context_attrs[3] = legacy_bit ? 3 : major; ++ context_attrs[4] = EGL_CONTEXT_MINOR_VERSION_KHR; ++ context_attrs[5] = legacy_bit ? 0 : minor; ++ context_attrs[6] = EGL_CONTEXT_FLAGS_KHR; ++ context_attrs[7] = flags; ++ context_attrs[8] = EGL_NONE; ++ } ++ ++ eglBindAPI (EGL_OPENGL_API); ++ } ++ ++ GDK_NOTE (OPENGL, ++ g_message ("Creating EGL context (version:%d.%d, debug:%s, forward:%s, legacy:%s, es:%s)", ++ 2, 0, ++ debug_bit ? "yes" : "no", ++ compat_bit ? "yes" : "no", ++ legacy_bit ? "yes" : "no", ++ es_bit ? "yes" : "no")); ++ ++ context_x11->egl_context = ++ eglCreateContext (gdk_x11_display_get_egl_display (display), ++ context_x11->egl_config, ++ share != NULL ? GDK_X11_GL_CONTEXT (share)->egl_context ++ : EGL_NO_CONTEXT, ++ context_attrs); ++ ++ /* If we're not asking for a GLES context, and we don't have the legacy bit set ++ * already, try again with a legacy context ++ */ ++ if (context_x11->egl_context == NULL && !es_bit && !legacy_bit) ++ { ++ context_attrs[1] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; ++ context_attrs[3] = 3; ++ context_attrs[5] = 0; ++ ++ legacy_bit = TRUE; ++ es_bit = FALSE; ++ ++ GDK_NOTE (OPENGL, ++ g_message ("Context creation failed; trying legacy EGL context")); ++ ++ context_x11->egl_context = ++ eglCreateContext (gdk_x11_display_get_egl_display (display), ++ context_x11->egl_config, ++ share != NULL ? GDK_X11_GL_CONTEXT (share)->egl_context ++ : EGL_NO_CONTEXT, ++ context_attrs); ++ } ++ ++ if (context_x11->egl_context == NULL) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, ++ _("Unable to create a GL context")); ++ return FALSE; ++ } ++ ++ gdk_gl_context_set_is_legacy (context, legacy_bit); ++ gdk_gl_context_set_use_es (context, es_bit); ++ ++ GDK_NOTE (OPENGL, ++ g_message ("Realized EGL context[%p]", ++ context_x11->egl_context)); ++ ++ return TRUE; ++} ++ ++static void ++gdk_x11_gl_context_dispose (GObject *gobject) ++{ ++ GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (gobject); ++ ++ if (context_x11->egl_context != NULL) ++ { ++ GdkGLContext *context = GDK_GL_CONTEXT (gobject); ++ GdkDisplay *display = gdk_gl_context_get_display (context); ++ ++ if (eglGetCurrentContext () != context_x11->egl_context) ++ eglMakeCurrent (gdk_x11_display_get_egl_display (display), ++ EGL_NO_SURFACE, ++ EGL_NO_SURFACE, ++ EGL_NO_CONTEXT); ++ ++ GDK_NOTE (OPENGL, g_message ("Destroying EGL context")); ++ eglDestroyContext (gdk_x11_display_get_egl_display (display), ++ context_x11->egl_context); ++ context_x11->egl_context = NULL; ++ } ++ ++ G_OBJECT_CLASS (gdk_x11_gl_context_parent_class)->dispose (gobject); ++} ++ ++static void ++gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass) ++{ ++ GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass); ++ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ++ ++ context_class->realize = gdk_x11_gl_context_realize; ++ context_class->end_frame = gdk_x11_gl_context_end_frame; ++ context_class->texture_from_surface = gdk_x11_gl_context_texture_from_surface; ++ ++ gobject_class->dispose = gdk_x11_gl_context_dispose; ++} ++ ++static void ++gdk_x11_gl_context_init (GdkX11GLContext *self) ++{ ++ self->do_frame_sync = TRUE; ++} ++ ++static gboolean ++gdk_x11_display_init_gl (GdkDisplay *display) ++{ ++ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); ++ EGLDisplay edpy; ++ int major, minor; ++ ++ if (display_x11->supports_gl) ++ return TRUE; ++ ++ if (_gdk_gl_flags & GDK_GL_DISABLE) ++ return FALSE; ++ ++ edpy = gdk_x11_display_get_egl_display (display); ++ if (edpy == NULL) ++ return FALSE; ++ ++ if (!eglInitialize (edpy, &major, &minor)) ++ return FALSE; ++ ++ if (!eglBindAPI (EGL_OPENGL_ES_API)) ++ return FALSE; ++ ++ display_x11->supports_gl = TRUE; ++ ++ display_x11->glx_version = major * 10 + minor; ++ display_x11->glx_error_base = 0; ++ display_x11->glx_event_base = 0; ++ ++ display_x11->has_create_context = ++ epoxy_has_egl_extension (edpy, "EGL_KHR_create_context"); ++ display_x11->has_create_es2_context = FALSE; ++ display_x11->has_swap_interval = TRUE; ++ display_x11->has_texture_from_pixmap = FALSE; ++ display_x11->has_image_pixmap = ++ epoxy_has_egl_extension (edpy, "EGL_KHR_image_pixmap"); ++ display_x11->has_video_sync = FALSE; ++ display_x11->has_buffer_age = ++ epoxy_has_egl_extension (edpy, "EGL_EXT_buffer_age"); ++ display_x11->has_sync_control = FALSE; ++ display_x11->has_multisample = FALSE; ++ display_x11->has_visual_rating = FALSE; ++ display_x11->has_swap_buffers_with_damage = ++ epoxy_has_egl_extension (edpy, "EGL_EXT_swap_buffers_with_damage"); ++ ++ GDK_NOTE (OPENGL, ++ g_message ("EGL X11 found\n" ++ " - Vendor: %s\n" ++ " - Version: %s\n" ++ " - Client APIs: %s\n" ++ " - Checked extensions:\n" ++ "\t* EGL_KHR_create_context: %s\n" ++ "\t* EGL_EXT_buffer_age: %s\n" ++ "\t* EGL_EXT_swap_buffers_with_damage: %s\n" ++ "\t* EGL_KHR_image_pixmap: %s", ++ eglQueryString (edpy, EGL_VENDOR), ++ eglQueryString (edpy, EGL_VERSION), ++ eglQueryString (edpy, EGL_CLIENT_APIS), ++ display_x11->has_create_context ? "yes" : "no", ++ display_x11->has_buffer_age ? "yes" : "no", ++ display_x11->has_swap_buffers_with_damage ? "yes" : "no", ++ display_x11->has_image_pixmap ? "yes" : "no")); ++ ++ return TRUE; ++} ++ ++void ++_gdk_x11_screen_update_visuals_for_gl (GdkScreen *screen) ++{ ++ /* No-op; there's just no way to do the same trick we use ++ * with GLX to select an appropriate visual and cache it. ++ * For EGL-X11 we always pick the first visual and stick ++ * with it. ++ */ ++} ++ ++#define MAX_EGL_ATTRS 30 ++ ++static gboolean ++find_egl_config_for_window (GdkWindow *window, ++ EGLConfig *config_out, ++ GError **error) ++{ ++ GdkDisplay *display = gdk_window_get_display (window); ++ GdkVisual *visual = gdk_window_get_visual (window); ++ EGLint attrs[MAX_EGL_ATTRS]; ++ EGLint count; ++ EGLDisplay egl_display; ++ EGLConfig *configs; ++ gboolean use_rgba; ++ int i = 0; ++ ++ attrs[i++] = EGL_SURFACE_TYPE; ++ attrs[i++] = EGL_WINDOW_BIT; ++ ++ attrs[i++] = EGL_COLOR_BUFFER_TYPE; ++ attrs[i++] = EGL_RGB_BUFFER; ++ ++ attrs[i++] = EGL_RED_SIZE; ++ attrs[i++] = 1; ++ attrs[i++] = EGL_GREEN_SIZE; ++ attrs[i++] = 1; ++ attrs[i++] = EGL_BLUE_SIZE; ++ attrs[i++] = 1; ++ ++ use_rgba = (visual == gdk_screen_get_rgba_visual (gdk_window_get_screen (window))); ++ ++ if (use_rgba) ++ { ++ attrs[i++] = EGL_ALPHA_SIZE; ++ attrs[i++] = 1; ++ } ++ else ++ { ++ attrs[i++] = EGL_ALPHA_SIZE; ++ attrs[i++] = EGL_DONT_CARE; ++ } ++ ++ attrs[i++] = EGL_NONE; ++ g_assert (i < MAX_EGL_ATTRS); ++ ++ egl_display = gdk_x11_display_get_egl_display (display); ++ if (!eglChooseConfig (egl_display, attrs, NULL, 0, &count) || count < 1) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, ++ GDK_GL_ERROR_UNSUPPORTED_FORMAT, ++ _("No available configurations for the given pixel format")); ++ return FALSE; ++ } ++ ++ configs = g_new (EGLConfig, count); ++ if (!eglChooseConfig (egl_display, attrs, configs, count, &count) || count < 1) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, ++ GDK_GL_ERROR_UNSUPPORTED_FORMAT, ++ _("No available configurations for the given pixel format")); ++ g_free (configs); ++ return FALSE; ++ } ++ ++ if (config_out != NULL) ++ *config_out = configs[0]; ++ ++ g_free (configs); ++ ++ return TRUE; ++} ++ ++GdkGLContext * ++gdk_x11_window_create_gl_context (GdkWindow *window, ++ gboolean attached, ++ GdkGLContext *share, ++ GError **error) ++{ ++ GdkDisplay *display; ++ GdkX11GLContext *context; ++ EGLConfig config; ++ ++ display = gdk_window_get_display (window); ++ ++ if (!gdk_x11_display_init_gl (display)) ++ { ++ g_set_error_literal (error, GDK_GL_ERROR, ++ GDK_GL_ERROR_NOT_AVAILABLE, ++ _("No GL implementation is available")); ++ return NULL; ++ } ++ ++ if (!find_egl_config_for_window (window, &config, error)) ++ return NULL; ++ ++ context = g_object_new (GDK_TYPE_X11_GL_CONTEXT, ++ "display", display, ++ "window", window, ++ "shared-context", share, ++ NULL); ++ ++ context->egl_config = config; ++ context->is_attached = attached; ++ ++ return GDK_GL_CONTEXT (context); ++} ++ ++#ifdef HAVE_XCOMPOSITE ++static gboolean ++window_is_composited (GdkDisplay *display, ++ GdkWindow *window) ++{ ++ Display *dpy = GDK_DISPLAY_XDISPLAY (display); ++ Pixmap pixmap; ++ ++ gdk_x11_display_error_trap_push (display); ++ ++ /* This is kind of an expensive check, because there's no XComposite ++ * API to check if a Window has been unredirected. We check if there's ++ * a named Pixmap for it, and if we fail it means that the screen is ++ * not composited or the window is unredirected or not visible ++ */ ++ pixmap = XCompositeNameWindowPixmap (dpy, GDK_WINDOW_XID (window)); ++ ++ XSync (GDK_DISPLAY_XDISPLAY (display), False); ++ ++ if (gdk_x11_display_error_trap_pop (display)) ++ return FALSE; ++ ++ XFreePixmap (GDK_DISPLAY_XDISPLAY (display), pixmap); ++ ++ return TRUE; ++} ++#endif /* HAVE_XCOMPOSITE */ ++ ++gboolean ++gdk_x11_display_make_gl_context_current (GdkDisplay *display, ++ GdkGLContext *context) ++{ ++ GdkX11GLContext *context_x11; ++ GdkWindow *window; ++ gboolean do_frame_sync = FALSE; ++ EGLSurface surface; ++ EGLDisplay egl_display; ++ ++ egl_display = gdk_x11_display_get_egl_display (display); ++ ++ if (context == NULL) ++ { ++ eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); ++ return TRUE; ++ } ++ ++ window = gdk_gl_context_get_window (context); ++ context_x11 = GDK_X11_GL_CONTEXT (context); ++ if (context_x11->egl_context == NULL) ++ { ++ g_critical ("No EGL context associated to the GdkGLContext; you must " ++ "call gdk_gl_context_realize() first."); ++ return FALSE; ++ } ++ ++ GDK_NOTE (OPENGL, ++ g_message ("Making EGL context current")); ++ ++ if (context_x11->is_attached) ++ surface = gdk_x11_window_get_egl_surface (window, context_x11->egl_config); ++ else ++ surface = gdk_x11_display_get_egl_dummy_surface (display, context_x11->egl_config); ++ ++ if (!eglMakeCurrent (egl_display, surface, surface, context_x11->egl_context)) ++ { ++ GDK_NOTE (OPENGL, ++ g_message ("Making EGL context current failed")); ++ return FALSE; ++ } ++ ++ if (context_x11->is_attached) ++ { ++ GdkScreen *screen = gdk_window_get_screen (window); ++ gboolean is_composited = gdk_screen_is_composited (screen); ++ ++#ifdef HAVE_XCOMPOSITE ++ /* If the WM is compositing and the window is redirected there is no ++ * particular need to delay the swap when drawing on the offscreen, ++ * rendering to the screen happens later anyway, and its up to the ++ * compositor to sync that to the vblank. ++ */ ++ if (is_composited) ++ is_composited = window_is_composited (display, window->impl_window); ++#endif /* HAVE_XCOMPOSITE */ ++ ++ do_frame_sync = !is_composited; ++ ++ if (do_frame_sync != context_x11->do_frame_sync) ++ { ++ context_x11->do_frame_sync = do_frame_sync; ++ ++ if (do_frame_sync) ++ eglSwapInterval (egl_display, 1); ++ else ++ eglSwapInterval (egl_display, 0); ++ } ++ } ++ ++ return TRUE; ++} ++ ++/** ++ * gdk_x11_display_get_glx_version: ++ * @display: a #GdkDisplay ++ * @major: (out): return location for the GLX major version ++ * @minor: (out): return location for the GLX minor version ++ * ++ * Retrieves the version of the GLX implementation. ++ * ++ * Returns: %TRUE if GLX is available ++ * ++ * Since: 3.16 ++ */ ++gboolean ++gdk_x11_display_get_glx_version (GdkDisplay *display, ++ gint *major, ++ gint *minor) ++{ ++ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); ++ ++ if (!GDK_IS_X11_DISPLAY (display)) ++ return FALSE; ++ ++ if (!gdk_x11_display_init_gl (display)) ++ return FALSE; ++ ++ if (major != NULL) ++ *major = GDK_X11_DISPLAY (display)->glx_version / 10; ++ if (minor != NULL) ++ *minor = GDK_X11_DISPLAY (display)->glx_version % 10; ++ ++ return TRUE; ++} +diff -Nuarp gtk+-3.22.20.old/gdk/x11/gdkglcontext-x11.h gtk+-3.22.20.new/gdk/x11/gdkglcontext-x11.h +--- gtk+-3.22.20.old/gdk/x11/gdkglcontext-x11.h 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/x11/gdkglcontext-x11.h 2017-09-21 16:26:15.910417616 +0100 +@@ -24,9 +24,6 @@ + #include <X11/X.h> + #include <X11/Xlib.h> + +-#include <epoxy/gl.h> +-#include <epoxy/glx.h> +- + #include "gdkglcontextprivate.h" + #include "gdkdisplayprivate.h" + #include "gdkvisual.h" +@@ -36,27 +33,6 @@ + + G_BEGIN_DECLS + +-struct _GdkX11GLContext +-{ +- GdkGLContext parent_instance; +- +- GLXContext glx_context; +- GLXFBConfig glx_config; +- GLXDrawable drawable; +- +- guint is_attached : 1; +- guint is_direct : 1; +- guint do_frame_sync : 1; +- +- guint do_blit_swap : 1; +-}; +- +-struct _GdkX11GLContextClass +-{ +- GdkGLContextClass parent_class; +-}; +- +-gboolean gdk_x11_screen_init_gl (GdkScreen *screen); + GdkGLContext * gdk_x11_window_create_gl_context (GdkWindow *window, + gboolean attached, + GdkGLContext *share, +diff -Nuarp gtk+-3.22.20.old/gdk/x11/gdkwindow-x11.h gtk+-3.22.20.new/gdk/x11/gdkwindow-x11.h +--- gtk+-3.22.20.old/gdk/x11/gdkwindow-x11.h 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/x11/gdkwindow-x11.h 2017-09-21 16:30:39.668074358 +0100 +@@ -147,6 +147,7 @@ struct _GdkToplevelX11 + * to the extended update counter */ + guint pending_counter_value_is_extended : 1; + guint configure_counter_value_is_extended : 1; ++ guint unredirected : 1; /* _GTK_WINDOW_UNREDIRECTED */ + + gulong map_serial; /* Serial of last transition from unmapped */ + +diff -Nuarp gtk+-3.22.20.old/gdk/x11/Makefile.am gtk+-3.22.20.new/gdk/x11/Makefile.am +--- gtk+-3.22.20.old/gdk/x11/Makefile.am 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gdk/x11/Makefile.am 2017-09-21 16:26:15.906417606 +0100 +@@ -40,7 +40,6 @@ libgdk_x11_la_SOURCES = \ + gdkeventtranslator.c \ + gdkeventtranslator.h \ + gdkgeometry-x11.c \ +- gdkglcontext-x11.c \ + gdkglcontext-x11.h \ + gdkkeys-x11.c \ + gdkmain-x11.c \ +@@ -61,6 +60,12 @@ libgdk_x11_la_SOURCES = \ + xsettings-client.h \ + xsettings-client.c + ++if USE_EGL_X11 ++libgdk_x11_la_SOURCES += gdkglcontext-x11-eglx.c ++else ++libgdk_x11_la_SOURCES += gdkglcontext-x11.c ++endif ++ + libgdkinclude_HEADERS = \ + gdkx.h + +diff -Nuarp gtk+-3.22.20.old/gtk/gtkglarea.c gtk+-3.22.20.new/gtk/gtkglarea.c +--- gtk+-3.22.20.old/gtk/gtkglarea.c 2017-08-11 20:47:18.000000000 +0100 ++++ gtk+-3.22.20.new/gtk/gtkglarea.c 2017-09-21 16:29:43.002933265 +0100 +@@ -390,7 +390,7 @@ gtk_gl_area_ensure_buffers (GtkGLArea *a + + priv->have_buffers = TRUE; + +- glGenFramebuffersEXT (1, &priv->frame_buffer); ++ glGenFramebuffers (1, &priv->frame_buffer); + + if (priv->has_alpha) + { +@@ -401,7 +401,7 @@ gtk_gl_area_ensure_buffers (GtkGLArea *a + /* Delete old render buffer if any */ + if (priv->render_buffer != 0) + { +- glDeleteRenderbuffersEXT(1, &priv->render_buffer); ++ glDeleteRenderbuffers(1, &priv->render_buffer); + priv->render_buffer = 0; + } + } +@@ -409,7 +409,7 @@ gtk_gl_area_ensure_buffers (GtkGLArea *a + { + /* For non-alpha we use render buffers so we can blit instead of texture the result */ + if (priv->render_buffer == 0) +- glGenRenderbuffersEXT (1, &priv->render_buffer); ++ glGenRenderbuffers (1, &priv->render_buffer); + + /* Delete old texture if any */ + if (priv->texture != 0) +@@ -422,12 +422,12 @@ gtk_gl_area_ensure_buffers (GtkGLArea *a + if ((priv->has_depth_buffer || priv->has_stencil_buffer)) + { + if (priv->depth_stencil_buffer == 0) +- glGenRenderbuffersEXT (1, &priv->depth_stencil_buffer); ++ glGenRenderbuffers (1, &priv->depth_stencil_buffer); + } + else if (priv->depth_stencil_buffer != 0) + { + /* Delete old depth/stencil buffer */ +- glDeleteRenderbuffersEXT (1, &priv->depth_stencil_buffer); ++ glDeleteRenderbuffers (1, &priv->depth_stencil_buffer); + priv->depth_stencil_buffer = 0; + } + +@@ -460,7 +460,7 @@ gtk_gl_area_allocate_buffers (GtkGLArea + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + if (gdk_gl_context_get_use_es (priv->context)) +- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); ++ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + else + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); + } +@@ -514,23 +514,23 @@ gtk_gl_area_attach_buffers (GtkGLArea *a + else if (priv->needs_resize) + gtk_gl_area_allocate_buffers (area); + +- glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, priv->frame_buffer); ++ glBindFramebuffer (GL_FRAMEBUFFER, priv->frame_buffer); + + if (priv->texture) +- glFramebufferTexture2D (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, ++ glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, priv->texture, 0); + else if (priv->render_buffer) +- glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, +- GL_RENDERBUFFER_EXT, priv->render_buffer); ++ glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ++ GL_RENDERBUFFER, priv->render_buffer); + + if (priv->depth_stencil_buffer) + { + if (priv->has_depth_buffer) +- glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, +- GL_RENDERBUFFER_EXT, priv->depth_stencil_buffer); ++ glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, ++ GL_RENDERBUFFER, priv->depth_stencil_buffer); + if (priv->has_stencil_buffer) +- glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, +- GL_RENDERBUFFER_EXT, priv->depth_stencil_buffer); ++ glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, ++ GL_RENDERBUFFER, priv->depth_stencil_buffer); + } + } + +@@ -546,7 +546,7 @@ gtk_gl_area_delete_buffers (GtkGLArea *a + + if (priv->render_buffer != 0) + { +- glDeleteRenderbuffersEXT (1, &priv->render_buffer); ++ glDeleteRenderbuffers (1, &priv->render_buffer); + priv->render_buffer = 0; + } + +@@ -558,14 +558,14 @@ gtk_gl_area_delete_buffers (GtkGLArea *a + + if (priv->depth_stencil_buffer != 0) + { +- glDeleteRenderbuffersEXT (1, &priv->depth_stencil_buffer); ++ glDeleteRenderbuffers (1, &priv->depth_stencil_buffer); + priv->depth_stencil_buffer = 0; + } + + if (priv->frame_buffer != 0) + { +- glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); +- glDeleteFramebuffersEXT (1, &priv->frame_buffer); ++ glBindFramebuffer (GL_FRAMEBUFFER, 0); ++ glDeleteFramebuffers (1, &priv->frame_buffer); + priv->frame_buffer = 0; + } + } +@@ -697,6 +697,21 @@ gtk_gl_area_draw (GtkWidget *widget, + + gtk_gl_area_attach_buffers (area); + ++ status = glCheckFramebufferStatus (GL_FRAMEBUFFER); ++ if (status != GL_FRAMEBUFFER_COMPLETE) ++ { ++ g_set_error_literal (&priv->error, ++ GDK_GL_ERROR, GDK_GL_ERROR_UNSUPPORTED_FORMAT, ++ "Unsupported framebuffer configuration"); ++ ++ gtk_gl_area_draw_error_screen (area, ++ cr, ++ gtk_widget_get_allocated_width (widget), ++ gtk_widget_get_allocated_height (widget)); ++ ++ return FALSE; ++ } ++ + if (priv->has_depth_buffer) + glEnable (GL_DEPTH_TEST); + else +@@ -706,34 +721,26 @@ gtk_gl_area_draw (GtkWidget *widget, + w = gtk_widget_get_allocated_width (widget) * scale; + h = gtk_widget_get_allocated_height (widget) * scale; + +- status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT); +- if (status == GL_FRAMEBUFFER_COMPLETE_EXT) ++ if (priv->needs_render || priv->auto_render) + { +- if (priv->needs_render || priv->auto_render) ++ if (priv->needs_resize) + { +- if (priv->needs_resize) +- { +- g_signal_emit (area, area_signals[RESIZE], 0, w, h, NULL); +- priv->needs_resize = FALSE; +- } +- +- g_signal_emit (area, area_signals[RENDER], 0, priv->context, &unused); ++ g_signal_emit (area, area_signals[RESIZE], 0, w, h, NULL); ++ priv->needs_resize = FALSE; + } + +- priv->needs_render = FALSE; +- +- gdk_cairo_draw_from_gl (cr, +- gtk_widget_get_window (widget), +- priv->texture ? priv->texture : priv->render_buffer, +- priv->texture ? GL_TEXTURE : GL_RENDERBUFFER, +- scale, 0, 0, w, h); +- gtk_gl_area_make_current (area); +- } +- else +- { +- g_warning ("fb setup not supported"); ++ g_signal_emit (area, area_signals[RENDER], 0, priv->context, &unused); + } + ++ priv->needs_render = FALSE; ++ ++ gdk_cairo_draw_from_gl (cr, ++ gtk_widget_get_window (widget), ++ priv->texture ? priv->texture : priv->render_buffer, ++ priv->texture ? GL_TEXTURE : GL_RENDERBUFFER, ++ scale, 0, 0, w, h); ++ gtk_gl_area_make_current (area); ++ + return TRUE; + } + diff --git a/gtk3-fix-atk-gjs-crash.patch b/gtk3-fix-atk-gjs-crash.patch new file mode 100644 index 0000000000000000000000000000000000000000..37d89abfc7806bcdae4f2a247a02f39d6cc3cf40 --- /dev/null +++ b/gtk3-fix-atk-gjs-crash.patch @@ -0,0 +1,75 @@ +From f5c24a2397f65e275db6ebb5c971191d8c6ebec6 Mon Sep 17 00:00:00 2001 +From: Juan Pablo Ugarte <ugarte@endlessm.com> +Date: Thu, 19 Oct 2017 15:16:43 -0300 +Subject: [PATCH] GtkScrolledWindowAccessible, GtkIconViewAccessible: fix bug + #789215 + +Use g_signal_connect_data() instead of g_signal_connect_object() +to make sure the callback gets disconected when the data object +is destroyed. +--- + gtk/a11y/gtkiconviewaccessible.c | 24 ++++++++++++------------ + gtk/a11y/gtkscrolledwindowaccessible.c | 12 ++++++------ + 2 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/gtk/a11y/gtkiconviewaccessible.c b/gtk/a11y/gtkiconviewaccessible.c +index eb85522d87..e8a3aa780f 100644 +--- a/gtk/a11y/gtkiconviewaccessible.c ++++ b/gtk/a11y/gtkiconviewaccessible.c +@@ -1226,18 +1226,18 @@ gtk_icon_view_accessible_connect_model_signals (GtkIconView *icon_view) + GObject *obj; + + obj = G_OBJECT (icon_view->priv->model); +- g_signal_connect_data (obj, "row-changed", +- (GCallback) gtk_icon_view_accessible_model_row_changed, +- icon_view, NULL, 0); +- g_signal_connect_data (obj, "row-inserted", +- (GCallback) gtk_icon_view_accessible_model_row_inserted, +- icon_view, NULL, G_CONNECT_AFTER); +- g_signal_connect_data (obj, "row-deleted", +- (GCallback) gtk_icon_view_accessible_model_row_deleted, +- icon_view, NULL, G_CONNECT_AFTER); +- g_signal_connect_data (obj, "rows-reordered", +- (GCallback) gtk_icon_view_accessible_model_rows_reordered, +- icon_view, NULL, G_CONNECT_AFTER); ++ g_signal_connect_object (obj, "row-changed", ++ G_CALLBACK (gtk_icon_view_accessible_model_row_changed), ++ icon_view, 0); ++ g_signal_connect_object (obj, "row-inserted", ++ G_CALLBACK (gtk_icon_view_accessible_model_row_inserted), ++ icon_view, G_CONNECT_AFTER); ++ g_signal_connect_object (obj, "row-deleted", ++ G_CALLBACK (gtk_icon_view_accessible_model_row_deleted), ++ icon_view, G_CONNECT_AFTER); ++ g_signal_connect_object (obj, "rows-reordered", ++ G_CALLBACK (gtk_icon_view_accessible_model_rows_reordered), ++ icon_view, G_CONNECT_AFTER); + } + + static void +diff --git a/gtk/a11y/gtkscrolledwindowaccessible.c b/gtk/a11y/gtkscrolledwindowaccessible.c +index 488cf7a9ea..80fb5b75b4 100644 +--- a/gtk/a11y/gtkscrolledwindowaccessible.c ++++ b/gtk/a11y/gtkscrolledwindowaccessible.c +@@ -92,12 +92,12 @@ gtk_scrolled_window_accessible_initialize (AtkObject *obj, + + window = GTK_SCROLLED_WINDOW (data); + +- g_signal_connect_data (gtk_scrolled_window_get_hscrollbar (window), "notify::visible", +- G_CALLBACK (visibility_changed), +- obj, NULL, FALSE); +- g_signal_connect_data (gtk_scrolled_window_get_vscrollbar (window), "notify::visible", +- G_CALLBACK (visibility_changed), +- obj, NULL, FALSE); ++ g_signal_connect_object (gtk_scrolled_window_get_hscrollbar (window), "notify::visible", ++ G_CALLBACK (visibility_changed), ++ obj, 0); ++ g_signal_connect_object (gtk_scrolled_window_get_vscrollbar (window), "notify::visible", ++ G_CALLBACK (visibility_changed), ++ obj, 0); + + obj->role = ATK_ROLE_SCROLL_PANE; + } +-- +2.15.0.rc1 + diff --git a/gtkgstwidget-add-ready-to-show-signal.patch b/gtkgstwidget-add-ready-to-show-signal.patch new file mode 100644 index 0000000000000000000000000000000000000000..2fd06fddce665b280213d958735239fdfcc8a328 --- /dev/null +++ b/gtkgstwidget-add-ready-to-show-signal.patch @@ -0,0 +1,54 @@ +From a76037f34e8acf8642b8a313152a0bdeeec5c335 Mon Sep 17 00:00:00 2001 +From: Juan Pablo Ugarte <ugarte@endlessm.com> +Date: Wed, 12 Dec 2018 14:11:28 -0800 +Subject: [PATCH] gtkgstwidget: add ready-to-show signal. + +Add a way to know when the widget is ready to show video content. + +Closes issue #528 +--- + ext/gtk/gtkgstbasewidget.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/ext/gtk/gtkgstbasewidget.c b/ext/gtk/gtkgstbasewidget.c +index 4858f2764..a3808c57f 100644 +--- a/ext/gtk/gtkgstbasewidget.c ++++ b/ext/gtk/gtkgstbasewidget.c +@@ -203,11 +203,15 @@ _queue_draw (GtkGstBaseWidget * widget) + widget->pending_resize = FALSE; + + widget->v_info = widget->pending_v_info; +- widget->negotiated = TRUE; + + _apply_par (widget); + + gtk_widget_queue_resize (GTK_WIDGET (widget)); ++ ++ if (!widget->negotiated && widget->pending_buffer) ++ g_signal_emit_by_name (widget, "ready-to-show"); ++ ++ widget->negotiated = TRUE; + } else { + gtk_widget_queue_draw (GTK_WIDGET (widget)); + } +@@ -395,6 +399,17 @@ gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass) + "When enabled, alpha will be ignored and converted to black", + DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + ++ /** ++ * GtkGstBaseWidget::ready-to-show: ++ * @self: the #GtkGstBaseWidgetClass which received the signal. ++ * ++ * This signal is emited in the main thread once when the widget is ready ++ * to display a video frame if shown on the screen. ++ */ ++ g_signal_new_class_handler ("ready-to-show", ++ G_TYPE_FROM_CLASS (gobject_klass), ++ G_SIGNAL_RUN_LAST, NULL, NULL, NULL, NULL, G_TYPE_NONE, 0); ++ + widget_klass->get_preferred_width = gtk_gst_base_widget_get_preferred_width; + widget_klass->get_preferred_height = gtk_gst_base_widget_get_preferred_height; + widget_klass->key_press_event = gtk_gst_base_widget_key_event; +-- +2.20.0 + diff --git a/issue b/issue new file mode 100644 index 0000000000000000000000000000000000000000..e587c8838a1b609a6fed822d892d8e22ce724e61 --- /dev/null +++ b/issue @@ -0,0 +1 @@ +Endless Applications Platform master \n \l diff --git a/issue.net b/issue.net new file mode 100644 index 0000000000000000000000000000000000000000..3607338295a18b403ab47004a4077b686f052d7b --- /dev/null +++ b/issue.net @@ -0,0 +1 @@ +Endless Applications Platform master %h diff --git a/lxml-Fix-getting-lib-version-when-using-pkg-config.patch b/lxml-Fix-getting-lib-version-when-using-pkg-config.patch new file mode 100644 index 0000000000000000000000000000000000000000..84fcbdd181e6482ce5f9ab2caab5dd65cc3e4d7f --- /dev/null +++ b/lxml-Fix-getting-lib-version-when-using-pkg-config.patch @@ -0,0 +1,27 @@ +From d10c98f4bb5e15d5c39bf71206065c3a25754900 Mon Sep 17 00:00:00 2001 +From: Patrick Griffis <tingping@tingping.se> +Date: Mon, 22 Aug 2016 17:37:35 -0400 +Subject: [PATCH] Fix getting lib version when using pkg-config + +--- + setupinfo.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/setupinfo.py b/setupinfo.py +index ecbf961..7cb0d7b 100644 +--- a/setupinfo.py ++++ b/setupinfo.py +@@ -360,8 +360,8 @@ def check_min_version(version, min_version, error_name): + + + def get_library_versions(): +- xml2_version = run_command(find_xml2_config(), "--version") +- xslt_version = run_command(find_xslt_config(), "--version") ++ xml2_version = run_command(find_xml2_config(), "--modversion") ++ xslt_version = run_command(find_xslt_config(), "--modversion") + return xml2_version, xslt_version + + +-- +2.9.3 + diff --git a/mathjax-makefile b/mathjax-makefile new file mode 100644 index 0000000000000000000000000000000000000000..2ce4790bd6071308cb8f92587f738e2fac80dbf5 --- /dev/null +++ b/mathjax-makefile @@ -0,0 +1,17 @@ +all: + @true + +install: + mkdir -p /usr/share/javascript/mathjax + mv MathJax.js /usr/share/javascript/mathjax + mv config /usr/share/javascript/mathjax + mv extensions /usr/share/javascript/mathjax + mv images /usr/share/javascript/mathjax + mv jax /usr/share/javascript/mathjax + mv localization /usr/share/javascript/mathjax + mv test /usr/share/javascript/mathjax + mv unpacked /usr/share/javascript/mathjax + mkdir -p /usr/share/javascript/mathjax/fonts/HTML-CSS/TeX + mv fonts/HTML-CSS/TeX/otf /usr/share/javascript/mathjax/fonts/HTML-CSS/TeX + mv fonts/HTML-CSS/TeX/svg /usr/share/javascript/mathjax/fonts/HTML-CSS/TeX + mv fonts/HTML-CSS/TeX/woff /usr/share/javascript/mathjax/fonts/HTML-CSS/TeX diff --git a/org.freedesktop.Platform.Icontheme.EndlessOS.appdata.xml b/org.freedesktop.Platform.Icontheme.EndlessOS.appdata.xml new file mode 100644 index 0000000000000000000000000000000000000000..b4296fd66bc891d348695f645d6eac3272702bf2 --- /dev/null +++ b/org.freedesktop.Platform.Icontheme.EndlessOS.appdata.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component type="runtime"> + <id>org.freedesktop.Platform.Icontheme.EndlessOS</id> + <metadata_license>CC0-1.0</metadata_license> + <project_license>LGPL-2.1+</project_license> + <name>EndlessOS icon theme</name> + <summary>EndlessOS icon theme</summary> + <description> + <p> + The default icon theme used in Endless OS. + https://endlessos.com + </p> + </description> + <url type="homepage">https://github.com/endlessm/eos-theme</url> +</component> diff --git a/org.freedesktop.Platform.Icontheme.EndlessOS.json b/org.freedesktop.Platform.Icontheme.EndlessOS.json new file mode 100644 index 0000000000000000000000000000000000000000..f54ac5c374ef0db0a63be4209fe24bce366b7cb3 --- /dev/null +++ b/org.freedesktop.Platform.Icontheme.EndlessOS.json @@ -0,0 +1,49 @@ +{ + "id": "org.freedesktop.Platform.Icontheme.EndlessOS", + "branch": "1.0", + "runtime": "org.freedesktop.Sdk", + "build-extension": true, + "sdk": "org.freedesktop.Sdk", + "runtime-version": "1.6", + "sdk-extensions": [], + "separate-locales": false, + "cleanup": [ "/share/info", "/share/man" ], + "appstream-compose": false, + "build-options" : { + "prefix": "/usr/share/runtime" + }, + "modules": [ + { + "name": "eos-theme", + "config-opts": [ + "--enable-app-icons", + "--disable-fonts", + "--disable-settings" + ], + "sources": [ + { + "type": "git", + "url": "https://github.com/endlessm/eos-theme.git" + } + ], + "ensure-writable": [ + "/share/runtime/share/dconf" + ] + }, + { + "name": "appdata", + "buildsystem": "simple", + "build-commands": [ + "mkdir -p ${FLATPAK_DEST}/share/appdata", + "cp org.freedesktop.Platform.Icontheme.EndlessOS.appdata.xml ${FLATPAK_DEST}/share/appdata", + "appstream-compose --basename=org.freedesktop.Platform.Icontheme.EndlessOS --prefix=${FLATPAK_DEST} --origin=flatpak org.freedesktop.Platform.Icontheme.EndlessOS" + ], + "sources": [ + { + "type": "file", + "path": "org.freedesktop.Platform.Icontheme.EndlessOS.appdata.xml" + } + ] + } + ] +} diff --git a/os-release b/os-release new file mode 100644 index 0000000000000000000000000000000000000000..68b7fef8d790464e62ee83b40413f98a299ca65b --- /dev/null +++ b/os-release @@ -0,0 +1,4 @@ +NAME=Endless +VERSION=master (Flatpak runtime) +VERSION_ID=master +ID=com.endlessm.apps.Platform diff --git a/os-release-configure b/os-release-configure new file mode 100755 index 0000000000000000000000000000000000000000..a9993355ef0b27381bec21d4e564fd0c3ee5d555 --- /dev/null +++ b/os-release-configure @@ -0,0 +1,17 @@ +#!/bin/sh + +cat <<EOF > Makefile +all: + +install: + mkdir -p ${DESTDIR}/usr/lib + install os-release ${DESTDIR}/usr/lib + mkdir -p ${DESTDIR}/usr/share/appdata + mkdir -p ${DESTDIR}/etc + install issue ${DESTDIR}/etc + install issue.net ${DESTDIR}/etc + install com.endlessm.apps.Platform.appdata.xml ${DESTDIR}/usr/share/appdata + install com.endlessm.apps.Sdk.appdata.xml ${DESTDIR}/usr/share/appdata + appstream-compose --basename=com.endlessm.apps.Platform --prefix=/usr --origin=flatpak com.endlessm.apps.Platform + appstream-compose --basename=com.endlessm.apps.Sdk --prefix=/usr --origin=flatpak com.endlessm.apps.Sdk +EOF diff --git a/polib-makefile b/polib-makefile new file mode 100644 index 0000000000000000000000000000000000000000..c7d42671e9530daa4427831e0bed16e284411198 --- /dev/null +++ b/polib-makefile @@ -0,0 +1,8 @@ +all: + @true + +install: + PYVER=`$$PYTHON -c 'import sys; print("python{0}.{1}".format(sys.version.split(".")[0], sys.version.split(".")[1]))'`; \ + mkdir -p /usr/lib/$$PYVER/site-packages && \ + cp polib.py /usr/lib/$$PYVER/site-packages/polib.py + diff --git a/setuptools-makefile b/setuptools-makefile new file mode 100644 index 0000000000000000000000000000000000000000..2967fdf1570a7278544faab36170259dadd6f57c --- /dev/null +++ b/setuptools-makefile @@ -0,0 +1,5 @@ +all: + python3 ./setup.py build + +install: + python3 ./setup.py install --prefix=/usr --skip-build --optimize=1 diff --git a/tcl-no-docs.patch b/tcl-no-docs.patch new file mode 100644 index 0000000000000000000000000000000000000000..d7ed325cca215f85a50a05dc26fdff48fd63b410 --- /dev/null +++ b/tcl-no-docs.patch @@ -0,0 +1,108 @@ +diff -Nuarp tcl8.6.6.old/pkgs/itcl4.0.5/Makefile.in tcl8.6.6.new/pkgs/itcl4.0.5/Makefile.in +--- tcl8.6.6.old/pkgs/itcl4.0.5/Makefile.in 2016-07-12 17:59:19.000000000 +0100 ++++ tcl8.6.6.new/pkgs/itcl4.0.5/Makefile.in 2017-09-04 16:49:53.976631679 +0100 +@@ -197,7 +197,7 @@ libraries: + + doc: + +-install: all install-binaries install-libraries install-doc ++install: all install-binaries install-libraries + + install-binaries: binaries install-lib-binaries install-bin-binaries + +diff -Nuarp tcl8.6.6.old/pkgs/sqlite3.13.0/Makefile.in tcl8.6.6.new/pkgs/sqlite3.13.0/Makefile.in +--- tcl8.6.6.old/pkgs/sqlite3.13.0/Makefile.in 2016-01-07 15:38:22.000000000 +0000 ++++ tcl8.6.6.new/pkgs/sqlite3.13.0/Makefile.in 2017-09-04 16:50:17.863699170 +0100 +@@ -206,7 +206,7 @@ doc: + @echo " xml2nroff sample.xml > sample.n" + @echo " xml2html sample.xml > sample.html" + +-install: all install-binaries install-libraries install-doc ++install: all install-binaries install-libraries + + install-binaries: binaries install-lib-binaries install-bin-binaries + +diff -Nuarp tcl8.6.6.old/pkgs/tdbc1.0.4/Makefile.in tcl8.6.6.new/pkgs/tdbc1.0.4/Makefile.in +--- tcl8.6.6.old/pkgs/tdbc1.0.4/Makefile.in 2015-10-19 15:52:13.000000000 +0100 ++++ tcl8.6.6.new/pkgs/tdbc1.0.4/Makefile.in 2017-09-04 16:51:54.612972531 +0100 +@@ -204,7 +204,7 @@ libraries: + + doc: + +-install: all install-binaries install-libraries install-doc ++install: all install-binaries install-libraries + + install-binaries: binaries install-lib-binaries install-bin-binaries + +diff -Nuarp tcl8.6.6.old/pkgs/tdbcmysql1.0.4/Makefile.in tcl8.6.6.new/pkgs/tdbcmysql1.0.4/Makefile.in +--- tcl8.6.6.old/pkgs/tdbcmysql1.0.4/Makefile.in 2015-10-13 12:57:32.000000000 +0100 ++++ tcl8.6.6.new/pkgs/tdbcmysql1.0.4/Makefile.in 2017-09-04 16:51:18.636870881 +0100 +@@ -197,7 +197,7 @@ libraries: + + doc: + +-install: all install-binaries install-libraries install-doc ++install: all install-binaries install-libraries + + install-binaries: binaries install-lib-binaries install-bin-binaries + +diff -Nuarp tcl8.6.6.old/pkgs/tdbcodbc1.0.4/Makefile.in tcl8.6.6.new/pkgs/tdbcodbc1.0.4/Makefile.in +--- tcl8.6.6.old/pkgs/tdbcodbc1.0.4/Makefile.in 2015-10-13 12:57:58.000000000 +0100 ++++ tcl8.6.6.new/pkgs/tdbcodbc1.0.4/Makefile.in 2017-09-04 16:51:41.762936222 +0100 +@@ -200,7 +200,7 @@ libraries: + + doc: + +-install: all install-binaries install-libraries install-doc ++install: all install-binaries install-libraries + + install-binaries: binaries install-lib-binaries install-bin-binaries + +diff -Nuarp tcl8.6.6.old/pkgs/tdbcpostgres1.0.4/Makefile.in tcl8.6.6.new/pkgs/tdbcpostgres1.0.4/Makefile.in +--- tcl8.6.6.old/pkgs/tdbcpostgres1.0.4/Makefile.in 2015-10-13 12:58:11.000000000 +0100 ++++ tcl8.6.6.new/pkgs/tdbcpostgres1.0.4/Makefile.in 2017-09-04 16:52:09.363014204 +0100 +@@ -200,7 +200,7 @@ libraries: + + doc: + +-install: all install-binaries install-libraries install-doc ++install: all install-binaries install-libraries + + install-binaries: binaries install-lib-binaries install-bin-binaries + +diff -Nuarp tcl8.6.6.old/pkgs/tdbcsqlite3-1.0.4/Makefile.in tcl8.6.6.new/pkgs/tdbcsqlite3-1.0.4/Makefile.in +--- tcl8.6.6.old/pkgs/tdbcsqlite3-1.0.4/Makefile.in 2015-10-19 16:03:19.000000000 +0100 ++++ tcl8.6.6.new/pkgs/tdbcsqlite3-1.0.4/Makefile.in 2017-09-04 16:53:57.464319638 +0100 +@@ -155,7 +155,7 @@ doc: + @echo " xml2nroff sample.xml > sample.n" + @echo " xml2html sample.xml > sample.html" + +-install: all install-binaries install-libraries install-doc ++install: all install-binaries install-libraries + + install-binaries: install-lib-binaries + +diff -Nuarp tcl8.6.6.old/pkgs/thread2.8.0/Makefile.in tcl8.6.6.new/pkgs/thread2.8.0/Makefile.in +--- tcl8.6.6.old/pkgs/thread2.8.0/Makefile.in 2015-10-13 12:58:40.000000000 +0100 ++++ tcl8.6.6.new/pkgs/thread2.8.0/Makefile.in 2017-09-04 16:51:29.561901748 +0100 +@@ -203,7 +203,7 @@ libraries: + + doc: + +-install: all install-binaries install-libraries install-doc ++install: all install-binaries install-libraries + + install-binaries: binaries install-lib-binaries install-bin-binaries + +diff -Nuarp tcl8.6.6.old/unix/Makefile.in tcl8.6.6.new/unix/Makefile.in +--- tcl8.6.6.old/unix/Makefile.in 2016-07-26 15:07:18.000000000 +0100 ++++ tcl8.6.6.new/unix/Makefile.in 2017-09-04 16:18:19.460369839 +0100 +@@ -769,7 +769,7 @@ trace-test: ${TCLTEST_EXE} + #-------------------------------------------------------------------------- + + INSTALL_BASE_TARGETS = install-binaries install-libraries install-msgs $(INSTALL_TZDATA) +-INSTALL_DOC_TARGETS = install-doc ++INSTALL_DOC_TARGETS = + INSTALL_PACKAGE_TARGETS = install-packages + INSTALL_DEV_TARGETS = install-headers + INSTALL_EXTRA_TARGETS = @EXTRA_INSTALL@