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[] = {
++  { &GTK_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_FAST, "-eos-fast" },
++  { &GTK_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_GOOD, "-eos-good" },
++  { &GTK_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_BEST, "-eos-best" },
++  { &GTK_CSS_VALUE_EOS_CAIRO_FILTER, 1, CAIRO_FILTER_NEAREST, "-eos-nearest" },
++  { &GTK_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 == &GTK_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@