From 7b666d29c84d5cad788815a1c9133a5c38c5f410 Mon Sep 17 00:00:00 2001
From: Leo <thinkabit.ukim@gmail.com>
Date: Wed, 29 Jan 2020 00:19:19 +0100
Subject: [PATCH] Remove stale patches in community/

---
 community/beanstalkd/alpine.patch             |   12 -
 community/evince/CVE-2019-11459.patch         |   72 -
 community/fmt/FMT_API.patch                   |   13 -
 community/ftgl/ftgl-2.1.3-rc5-ldflags.patch   |  118 -
 community/ftgl/ftgl-2.1.3-rc5-ttf_font.patch  |   12 -
 community/gnome-keyring/fix-includes.patch    |   10 -
 .../lshw/basename-limits-long-bits.patch      |   40 -
 community/mate-calc/install-sh.patch          |   10 -
 .../mate-indicator-applet/install-sh.patch    |   10 -
 .../mate-settings-daemon/install-sh.patch     |   10 -
 community/miniupnpd/musl.patch                |   11 -
 community/opensc/fix-overlapping-memcpy.patch |   12 -
 .../opensc-fix-format-overflow-werror.patch   |   10 -
 ...-set-default-url-to-alpine-patchwork.patch |   25 -
 .../perl-log-log4perl/026FileApp.t.patch      |   13 -
 ...-1.19-Fixes-for-removal-dot-from-INC.patch |   24 -
 ...-1.25-Fixes-for-removal-dot-from-INC.patch |   12 -
 .../plymouth/plymouth-add-sysmacros.patch     |   10 -
 .../plymouth-git-master-20170123.patch        | 5399 -----------------
 community/prosody/luasec-0.6-fix.patch        |   14 -
 community/prosody/mallinfo.patch              |   13 -
 community/prosody/prosodyctl.patch            |   11 -
 community/py3-itypes/disable-flake8.patch     |   30 -
 community/raptor2/raptor-curl.patch           |   12 -
 community/rethinkdb/musl-fixes-all.patch      |   95 -
 .../sleuthkit/20_fix_spelling_errors.patch    |   34 -
 community/thttpd/discreet.patch               |   34 -
 community/thttpd/getline.patch                |   21 -
 community/tint2/musl-fixes.patch              |   16 -
 community/unarj/format.patch                  |   66 -
 community/v4l-utils/fix-compliance.patch      |   77 -
 community/v4l-utils/fix-libdvbv5.patch        |   19 -
 .../xfce4-battery-plugin/fix-includes.patch   |   19 -
 33 files changed, 6284 deletions(-)
 delete mode 100644 community/beanstalkd/alpine.patch
 delete mode 100644 community/evince/CVE-2019-11459.patch
 delete mode 100644 community/fmt/FMT_API.patch
 delete mode 100644 community/ftgl/ftgl-2.1.3-rc5-ldflags.patch
 delete mode 100644 community/ftgl/ftgl-2.1.3-rc5-ttf_font.patch
 delete mode 100644 community/gnome-keyring/fix-includes.patch
 delete mode 100644 community/lshw/basename-limits-long-bits.patch
 delete mode 100644 community/mate-calc/install-sh.patch
 delete mode 100644 community/mate-indicator-applet/install-sh.patch
 delete mode 100644 community/mate-settings-daemon/install-sh.patch
 delete mode 100644 community/miniupnpd/musl.patch
 delete mode 100644 community/opensc/fix-overlapping-memcpy.patch
 delete mode 100644 community/opensc/opensc-fix-format-overflow-werror.patch
 delete mode 100644 community/patchwork/0001-pwclient-set-default-url-to-alpine-patchwork.patch
 delete mode 100644 community/perl-log-log4perl/026FileApp.t.patch
 delete mode 100644 community/perl-unicode-collate/Unicode-Collate-1.19-Fixes-for-removal-dot-from-INC.patch
 delete mode 100644 community/perl-unicode-normalize/Unicode-Normalize-1.25-Fixes-for-removal-dot-from-INC.patch
 delete mode 100644 community/plymouth/plymouth-add-sysmacros.patch
 delete mode 100644 community/plymouth/plymouth-git-master-20170123.patch
 delete mode 100644 community/prosody/luasec-0.6-fix.patch
 delete mode 100644 community/prosody/mallinfo.patch
 delete mode 100644 community/prosody/prosodyctl.patch
 delete mode 100644 community/py3-itypes/disable-flake8.patch
 delete mode 100644 community/raptor2/raptor-curl.patch
 delete mode 100644 community/rethinkdb/musl-fixes-all.patch
 delete mode 100644 community/sleuthkit/20_fix_spelling_errors.patch
 delete mode 100644 community/thttpd/discreet.patch
 delete mode 100644 community/thttpd/getline.patch
 delete mode 100644 community/tint2/musl-fixes.patch
 delete mode 100644 community/unarj/format.patch
 delete mode 100644 community/v4l-utils/fix-compliance.patch
 delete mode 100644 community/v4l-utils/fix-libdvbv5.patch
 delete mode 100644 community/xfce4-battery-plugin/fix-includes.patch

diff --git a/community/beanstalkd/alpine.patch b/community/beanstalkd/alpine.patch
deleted file mode 100644
index 598319261670..000000000000
--- a/community/beanstalkd/alpine.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- ./sd-daemon.c
-+++ ./sd-daemon.c
-@@ -32,7 +32,7 @@
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <sys/un.h>
--#include <sys/fcntl.h>
-+#include <fcntl.h>
- #include <netinet/in.h>
- #include <stdlib.h>
- #include <errno.h>
-
diff --git a/community/evince/CVE-2019-11459.patch b/community/evince/CVE-2019-11459.patch
deleted file mode 100644
index b331a0c30ad0..000000000000
--- a/community/evince/CVE-2019-11459.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From 234f034a4d15cd46dd556f4945f99fbd57ef5f15 Mon Sep 17 00:00:00 2001
-From: Jason Crain <jcrain@src.gnome.org>
-Date: Mon, 15 Apr 2019 23:06:36 -0600
-Subject: [PATCH] tiff: Handle failure from TIFFReadRGBAImageOriented
-
-The TIFFReadRGBAImageOriented function returns zero if it was unable to
-read the image. Return NULL in this case instead of displaying
-uninitialized memory.
-
-Fixes #1129
----
- backend/tiff/tiff-document.c | 28 ++++++++++++++++++----------
- 1 file changed, 18 insertions(+), 10 deletions(-)
-
-diff --git a/backend/tiff/tiff-document.c b/backend/tiff/tiff-document.c
-index 7715031b..38bb3bd8 100644
---- a/backend/tiff/tiff-document.c
-+++ b/backend/tiff/tiff-document.c
-@@ -292,18 +292,22 @@ tiff_document_render (EvDocument      *document,
- 		g_warning("Failed to allocate memory for rendering.");
- 		return NULL;
- 	}
--	
-+
-+	if (!TIFFReadRGBAImageOriented (tiff_document->tiff,
-+					width, height,
-+					(uint32 *)pixels,
-+					orientation, 0)) {
-+		g_warning ("Failed to read TIFF image.");
-+		g_free (pixels);
-+		return NULL;
-+	}
-+
- 	surface = cairo_image_surface_create_for_data (pixels,
- 						       CAIRO_FORMAT_RGB24,
- 						       width, height,
- 						       rowstride);
- 	cairo_surface_set_user_data (surface, &key,
- 				     pixels, (cairo_destroy_func_t)g_free);
--
--	TIFFReadRGBAImageOriented (tiff_document->tiff,
--				   width, height,
--				   (uint32 *)pixels,
--				   orientation, 0);
- 	pop_handlers ();
- 
- 	/* Convert the format returned by libtiff to
-@@ -384,13 +388,17 @@ tiff_document_get_thumbnail (EvDocument      *document,
- 	if (!pixels)
- 		return NULL;
- 	
-+	if (!TIFFReadRGBAImageOriented (tiff_document->tiff,
-+					width, height,
-+					(uint32 *)pixels,
-+					ORIENTATION_TOPLEFT, 0)) {
-+		g_free (pixels);
-+		return NULL;
-+	}
-+
- 	pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, 
- 					   width, height, rowstride,
- 					   (GdkPixbufDestroyNotify) g_free, NULL);
--	TIFFReadRGBAImageOriented (tiff_document->tiff,
--				   width, height,
--				   (uint32 *)pixels,
--				   ORIENTATION_TOPLEFT, 0);
- 	pop_handlers ();
- 
- 	ev_render_context_compute_scaled_size (rc, width, height * (x_res / y_res),
--- 
-2.21.0
-
diff --git a/community/fmt/FMT_API.patch b/community/fmt/FMT_API.patch
deleted file mode 100644
index 20e2533de545..000000000000
--- a/community/fmt/FMT_API.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/include/fmt/core.h b/include/fmt/core.h
-index 6a0846f..39d3e0e 100644
---- a/include/fmt/core.h
-+++ b/include/fmt/core.h
-@@ -224,7 +224,7 @@ namespace internal {
- // A workaround for gcc 4.8 to make void_t work in a SFINAE context.
- template <typename... Ts> struct void_t_impl { using type = void; };
- 
--void assert_fail(const char* file, int line, const char* message);
-+FMT_API void assert_fail(const char* file, int line, const char* message);
- 
- #ifndef FMT_ASSERT
- #  ifdef NDEBUG
diff --git a/community/ftgl/ftgl-2.1.3-rc5-ldflags.patch b/community/ftgl/ftgl-2.1.3-rc5-ldflags.patch
deleted file mode 100644
index be9331d6f5a1..000000000000
--- a/community/ftgl/ftgl-2.1.3-rc5-ldflags.patch
+++ /dev/null
@@ -1,118 +0,0 @@
-diff -up ftgl-2.1.3~rc5/demo/Makefile.am.ldflags ftgl-2.1.3~rc5/demo/Makefile.am
---- ftgl-2.1.3~rc5/demo/Makefile.am.ldflags	2008-06-02 03:10:10.000000000 +0200
-+++ ftgl-2.1.3~rc5/demo/Makefile.am	2010-02-14 15:02:19.670081290 +0100
-@@ -9,14 +9,14 @@ simple_SOURCES = \
-     simple.cpp \
-     $(NULL)
- simple_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--simple_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+simple_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS)
- simple_LDADD = ../src/libftgl.la
- 
- c_demo_SOURCES = \
-     c-demo.c \
-     $(NULL)
- c_demo_CFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--c_demo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+c_demo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GLUT_LIBS) -lm
- c_demo_LDADD = ../src/libftgl.la
- 
- FTGLDemo_SOURCES = \
-@@ -27,7 +27,7 @@ FTGLDemo_SOURCES = \
- 	trackball.h \
- 	$(NULL)
- FTGLDemo_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--FTGLDemo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+FTGLDemo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS)
- FTGLDemo_LDADD = ../src/libftgl.la
- 
- FTGLMFontDemo_SOURCES = \
-@@ -38,7 +38,7 @@ FTGLMFontDemo_SOURCES = \
- 	trackball.h \
- 	$(NULL)
- FTGLMFontDemo_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--FTGLMFontDemo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+FTGLMFontDemo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS)
- FTGLMFontDemo_LDADD = ../src/libftgl.la
- 
- NULL =
-diff -up ftgl-2.1.3~rc5/demo/Makefile.in.ldflags ftgl-2.1.3~rc5/demo/Makefile.in
---- ftgl-2.1.3~rc5/demo/Makefile.in.ldflags	2008-06-12 16:33:01.000000000 +0200
-+++ ftgl-2.1.3~rc5/demo/Makefile.in	2010-02-14 15:02:01.866831398 +0100
-@@ -242,14 +242,14 @@ simple_SOURCES = \
-     $(NULL)
- 
- simple_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--simple_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+simple_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS)
- simple_LDADD = ../src/libftgl.la
- c_demo_SOURCES = \
-     c-demo.c \
-     $(NULL)
- 
- c_demo_CFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--c_demo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+c_demo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS) -lm
- c_demo_LDADD = ../src/libftgl.la
- FTGLDemo_SOURCES = \
- 	FTGLDemo.cpp \
-@@ -260,7 +260,7 @@ FTGLDemo_SOURCES = \
- 	$(NULL)
- 
- FTGLDemo_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--FTGLDemo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+FTGLDemo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS)
- FTGLDemo_LDADD = ../src/libftgl.la
- FTGLMFontDemo_SOURCES = \
- 	FTGLMFontDemo.cpp \
-@@ -271,7 +271,7 @@ FTGLMFontDemo_SOURCES = \
- 	$(NULL)
- 
- FTGLMFontDemo_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--FTGLMFontDemo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+FTGLMFontDemo_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS)
- FTGLMFontDemo_LDADD = ../src/libftgl.la
- NULL = 
- all: all-am
-diff -up ftgl-2.1.3~rc5/test/Makefile.am.ldflags ftgl-2.1.3~rc5/test/Makefile.am
---- ftgl-2.1.3~rc5/test/Makefile.am.ldflags	2010-02-14 14:43:14.819077822 +0100
-+++ ftgl-2.1.3~rc5/test/Makefile.am	2010-02-14 14:43:49.227081230 +0100
-@@ -51,7 +51,7 @@ AM_CPPFLAGS = \
-     $(NULL)
- 
- CXXTest_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--CXXTest_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) -lcppunit
-+CXXTest_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS) -lcppunit
- CXXTest_LDADD = ../src/libftgl.la
- 
- CTest_SOURCES = \
-@@ -64,7 +64,7 @@ CTest_CPPFLAGS = \
-     -I$(top_srcdir)/src/FTFont \
-     -I$(top_srcdir)/src/FTLayout
- CTest_CFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--CTest_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+CTest_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS)
- CTest_LDADD = ../src/libftgl.la
- 
- NULL =
-diff -up ftgl-2.1.3~rc5/test/Makefile.in.ldflags ftgl-2.1.3~rc5/test/Makefile.in
---- ftgl-2.1.3~rc5/test/Makefile.in.ldflags	2010-02-14 14:43:20.365077958 +0100
-+++ ftgl-2.1.3~rc5/test/Makefile.in	2010-02-14 14:44:13.653078013 +0100
-@@ -294,7 +294,7 @@ AM_CPPFLAGS = \
-     $(NULL)
- 
- CXXTest_CXXFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--CXXTest_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) -lcppunit
-+CXXTest_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS) -lcppunit
- CXXTest_LDADD = ../src/libftgl.la
- CTest_SOURCES = \
-     CTest.c \
-@@ -308,7 +308,7 @@ CTest_CPPFLAGS = \
-     -I$(top_srcdir)/src/FTLayout
- 
- CTest_CFLAGS = $(FT2_CFLAGS) $(GL_CFLAGS)
--CTest_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS)
-+CTest_LDFLAGS = $(FT2_LIBS) $(GLUT_LIBS) $(GL_LIBS)
- CTest_LDADD = ../src/libftgl.la
- NULL = 
- all: all-am
diff --git a/community/ftgl/ftgl-2.1.3-rc5-ttf_font.patch b/community/ftgl/ftgl-2.1.3-rc5-ttf_font.patch
deleted file mode 100644
index 81ae273b3064..000000000000
--- a/community/ftgl/ftgl-2.1.3-rc5-ttf_font.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -up ftgl-2.1.3~rc5/demo/FTGLDemo.cpp.ttf_font ftgl-2.1.3~rc5/demo/FTGLDemo.cpp
---- ftgl-2.1.3~rc5/demo/FTGLDemo.cpp.ttf_font	2008-06-08 17:49:10.000000000 +0200
-+++ ftgl-2.1.3~rc5/demo/FTGLDemo.cpp	2009-05-21 02:18:42.000000000 +0200
-@@ -48,7 +48,7 @@
- #       define FONT_FILE "C:\\WINNT\\Fonts\\arial.ttf"
- #   else
-         // Put your font file here if configure did not find it.
--#       define FONT_FILE 0
-+#       define FONT_FILE "/usr/share/fonts/dejavu/DejaVuSans.ttf"
- #   endif
- #endif
- 
diff --git a/community/gnome-keyring/fix-includes.patch b/community/gnome-keyring/fix-includes.patch
deleted file mode 100644
index e8e3e20f522c..000000000000
--- a/community/gnome-keyring/fix-includes.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- gnome-keyring-2.32.1.orig/pkcs11/rpc-layer/gkm-rpc-daemon-standalone.c
-+++ gnome-keyring-2.32.1/pkcs11/rpc-layer/gkm-rpc-daemon-standalone.c
-@@ -32,6 +32,7 @@
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
-+#include <sys/select.h>
- 
- #include <dlfcn.h>
- #include <pthread.h>
diff --git a/community/lshw/basename-limits-long-bits.patch b/community/lshw/basename-limits-long-bits.patch
deleted file mode 100644
index cd5db0c7b1f9..000000000000
--- a/community/lshw/basename-limits-long-bits.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-commit 9389deed8b49a4845c51d5e7177d143cbb96718a
-Author: Isaac Dunham <ibid.ag@gmail.com>
-Date:   Fri Sep 12 21:45:32 2014 -0700
-
-    Numerous less obvious fixes
-
-    -POSIX basename() requires a char *, not const char*
-
-diff --git a/src/core/pci.cc b/src/core/pci.cc
-index aaa257c..b8a7917 100644
---- a/src/core/pci.cc
-+++ b/src/core/pci.cc
-@@ -13,6 +13,7 @@
- #include <string.h>
- #include <stdlib.h>
- #include <dirent.h>
-+#include <limits.h>
-
- __ID("@(#) $Id$");
-
-@@ -1127,10 +1129,16 @@ bool scan_pci(hwNode & n)
-         {
-           string drivername = readlink(string(devices[i]->d_name)+"/driver");
-           string modulename = readlink(string(devices[i]->d_name)+"/driver/module");
--
--          device->setConfig("driver", basename(const_cast<char *>(drivername.c_str())));
-+          char driver_c[PATH_MAX];
-+          char module_c[PATH_MAX];
-+          bzero(driver_c,PATH_MAX);
-+          bzero(module_c,PATH_MAX);
-+          strncpy(driver_c, drivername.c_str(),PATH_MAX);
-+          strncpy(module_c, modulename.c_str(),PATH_MAX);
-+
-+          device->setConfig("driver", basename(driver_c));
-           if(exists(modulename))
--            device->setConfig("module", basename(const_cast<char *>(modulename.c_str())));
-+            device->setConfig("module", basename(module_c));
-
-           if(exists(string(devices[i]->d_name)+"/rom"))
-           {
diff --git a/community/mate-calc/install-sh.patch b/community/mate-calc/install-sh.patch
deleted file mode 100644
index d32f681c0e43..000000000000
--- a/community/mate-calc/install-sh.patch
+++ /dev/null
@@ -1,10 +0,0 @@
-diff --git a/install-sh b/install-sh
-index defb86a..8175c64 100755
---- a/install-sh
-+++ b/install-sh
-@@ -1,4 +1,4 @@
--#!/usr/bin/sh
-+#!/bin/sh
- # install - install a program, script, or datafile
- 
- scriptversion=2018-03-11.20; # UTC
diff --git a/community/mate-indicator-applet/install-sh.patch b/community/mate-indicator-applet/install-sh.patch
deleted file mode 100644
index d32f681c0e43..000000000000
--- a/community/mate-indicator-applet/install-sh.patch
+++ /dev/null
@@ -1,10 +0,0 @@
-diff --git a/install-sh b/install-sh
-index defb86a..8175c64 100755
---- a/install-sh
-+++ b/install-sh
-@@ -1,4 +1,4 @@
--#!/usr/bin/sh
-+#!/bin/sh
- # install - install a program, script, or datafile
- 
- scriptversion=2018-03-11.20; # UTC
diff --git a/community/mate-settings-daemon/install-sh.patch b/community/mate-settings-daemon/install-sh.patch
deleted file mode 100644
index d32f681c0e43..000000000000
--- a/community/mate-settings-daemon/install-sh.patch
+++ /dev/null
@@ -1,10 +0,0 @@
-diff --git a/install-sh b/install-sh
-index defb86a..8175c64 100755
---- a/install-sh
-+++ b/install-sh
-@@ -1,4 +1,4 @@
--#!/usr/bin/sh
-+#!/bin/sh
- # install - install a program, script, or datafile
- 
- scriptversion=2018-03-11.20; # UTC
diff --git a/community/miniupnpd/musl.patch b/community/miniupnpd/musl.patch
deleted file mode 100644
index 7c2e2dc0f7ee..000000000000
--- a/community/miniupnpd/musl.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- ./miniupnpd.c.orig
-+++ ./miniupnpd.c
-@@ -39,7 +39,7 @@
- #include <sys/param.h>
- #if defined(sun)
- #include <kstat.h>
--#else
-+#elif defined(__BSD__)
- /* for BSD's sysctl */
- #include <sys/sysctl.h>
- #endif
diff --git a/community/opensc/fix-overlapping-memcpy.patch b/community/opensc/fix-overlapping-memcpy.patch
deleted file mode 100644
index f6bb934d1f89..000000000000
--- a/community/opensc/fix-overlapping-memcpy.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/src/libopensc/card-gids.c b/src/libopensc/card-gids.c
-index 2471c55a..27576f99 100644
---- a/src/libopensc/card-gids.c
-+++ b/src/libopensc/card-gids.c
-@@ -1915,7 +1915,6 @@ static int gids_authenticate_admin(sc_card_t *card, u8* key) {
- 	LOG_TEST_RET(card->ctx, r, "unable to set computer random");
- 
- 	// send it to the card
--	memcpy(apduSetRandom+4, randomR1, 16);
- 	sc_format_apdu(card, &apdu, SC_APDU_CASE_4, INS_GENERAL_AUTHENTICATE, 0x00, 0x00);
- 	apdu.lc = sizeof(apduSetRandom);
- 	apdu.data = apduSetRandom;
diff --git a/community/opensc/opensc-fix-format-overflow-werror.patch b/community/opensc/opensc-fix-format-overflow-werror.patch
deleted file mode 100644
index fb2031df9219..000000000000
--- a/community/opensc/opensc-fix-format-overflow-werror.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/src/pkcs15init/pkcs15-oberthur.c
-+++ b/src/pkcs15init/pkcs15-oberthur.c
-@@ -70,7 +70,6 @@
- 	ctx = p15card->card->ctx;
- 
- 	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
--	sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "cosm_write_tokeninfo() label '%s'; flags 0x%X", label, flags);
- 	if (sc_profile_get_file(profile, COSM_TITLE"-token-info", &file)) {
- 		rv = SC_ERROR_INCONSISTENT_PROFILE;
- 		SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot find "COSM_TITLE"-token-info");
diff --git a/community/patchwork/0001-pwclient-set-default-url-to-alpine-patchwork.patch b/community/patchwork/0001-pwclient-set-default-url-to-alpine-patchwork.patch
deleted file mode 100644
index 511e9042f165..000000000000
--- a/community/patchwork/0001-pwclient-set-default-url-to-alpine-patchwork.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 304b9f210a6edccc33b5ead321b43f02884aca62 Mon Sep 17 00:00:00 2001
-From: Carlo Landmeter <clandmeter@gmail.com>
-Date: Thu, 23 Apr 2015 10:01:18 +0200
-Subject: [PATCH] pwclient set default url to alpine patchwork
-
----
- apps/patchwork/bin/pwclient | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/apps/patchwork/bin/pwclient b/apps/patchwork/bin/pwclient
-index 2a80981..b1adad3 100755
---- a/apps/patchwork/bin/pwclient
-+++ b/apps/patchwork/bin/pwclient
-@@ -35,7 +35,7 @@ import re
- # This script will check the PW_XMLRPC_URL environment variable
- # for the URL to access.  If that is unspecified, it will fallback to
- # the hardcoded default value specified here.
--DEFAULT_URL = "http://patchwork/xmlrpc/"
-+DEFAULT_URL = "http://patchwork.alpinelinux.org/xmlrpc/"
- CONFIG_FILE = os.path.expanduser('~/.pwclientrc')
- 
- class Filter:
--- 
-2.3.5
-
diff --git a/community/perl-log-log4perl/026FileApp.t.patch b/community/perl-log-log4perl/026FileApp.t.patch
deleted file mode 100644
index 07b51afc2380..000000000000
--- a/community/perl-log-log4perl/026FileApp.t.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/t/026FileApp.t b/t/026FileApp.t
-index b3ae4f4..6c3b345 100644
---- a/t/026FileApp.t
-+++ b/t/026FileApp.t
-@@ -484,7 +484,7 @@ EOT
-   
-   my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat("${testpath}_1");
-   
--  is($mode & 07777,0750); #Win32 777
-+  is($mode & 0777,0750); #Win32 777
-   
-    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($testmkpathfile);
-   
diff --git a/community/perl-unicode-collate/Unicode-Collate-1.19-Fixes-for-removal-dot-from-INC.patch b/community/perl-unicode-collate/Unicode-Collate-1.19-Fixes-for-removal-dot-from-INC.patch
deleted file mode 100644
index aae5e3bb6e4b..000000000000
--- a/community/perl-unicode-collate/Unicode-Collate-1.19-Fixes-for-removal-dot-from-INC.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff -up Unicode-Collate-1.19/mklocale.orig Unicode-Collate-1.19/mklocale
---- Unicode-Collate-1.19/mklocale.orig	2017-05-11 14:46:13.491501304 +0200
-+++ Unicode-Collate-1.19/mklocale	2017-05-11 14:48:21.829764058 +0200
-@@ -546,7 +546,7 @@ for my $txt (@txts) {
- 	    s/\s*\z/.pm/;
- 	    my $f = File::Spec->catfile($CUR_DIR, split /::/, $_);
- 	    $f = 'Korean.pm' if /::Korean\.pm/; # using the newer one
--	    require $f;
-+	    require "./$f";
- 	    next;
- 	}
- 	if (/^(alternate)\s+(\S+)/) {
-diff -up Unicode-Collate-1.19/Makefile.PL.orig Unicode-Collate-1.19/Makefile.PL
---- Unicode-Collate-1.19/Makefile.PL.orig	2017-05-11 14:57:57.113506081 +0200
-+++ Unicode-Collate-1.19/Makefile.PL	2017-05-11 14:57:25.895682439 +0200
-@@ -6,7 +6,7 @@ my $clean = {};
- if (-f "Collate.xs") {
-     print "Making header files for XS...\n";
- 
--    do 'mkheader' or die $@ || "mkheader: $!";
-+    do './mkheader' or die $@ || "mkheader: $!";
- 
-     $clean = { FILES => 'ucatbl.h' };
- }
diff --git a/community/perl-unicode-normalize/Unicode-Normalize-1.25-Fixes-for-removal-dot-from-INC.patch b/community/perl-unicode-normalize/Unicode-Normalize-1.25-Fixes-for-removal-dot-from-INC.patch
deleted file mode 100644
index e34e2b19d39e..000000000000
--- a/community/perl-unicode-normalize/Unicode-Normalize-1.25-Fixes-for-removal-dot-from-INC.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -up Unicode-Normalize-1.25/Makefile.PL.orig Unicode-Normalize-1.25/Makefile.PL
---- Unicode-Normalize-1.25/Makefile.PL.orig	2017-05-12 10:24:13.296305863 +0200
-+++ Unicode-Normalize-1.25/Makefile.PL	2017-05-12 10:25:28.275822594 +0200
-@@ -8,7 +8,7 @@ my $mm_ver = ExtUtils::MakeMaker->VERSIO
- if (-f "Normalize.xs") {
-     print STDERR "Making header files for XS...\n";
- 
--    do 'mkheader' or die $@ || "mkheader: $!";
-+    do './mkheader' or die $@ || "mkheader: $!";
- 
-     $clean = { FILES => 'unfcan.h unfcmb.h unfcmp.h unfcpt.h unfexc.h' };
- }
diff --git a/community/plymouth/plymouth-add-sysmacros.patch b/community/plymouth/plymouth-add-sysmacros.patch
deleted file mode 100644
index 90c011955f0c..000000000000
--- a/community/plymouth/plymouth-add-sysmacros.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/src/libply-splash-core/ply-terminal.c
-+++ b/src/libply-splash-core/ply-terminal.c
-@@ -32,6 +32,7 @@
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <sys/types.h>
-+#include <sys/sysmacros.h>
- #include <termios.h>
- #include <unistd.h>
- #include <wchar.h>
diff --git a/community/plymouth/plymouth-git-master-20170123.patch b/community/plymouth/plymouth-git-master-20170123.patch
deleted file mode 100644
index 6ab412fa5d10..000000000000
--- a/community/plymouth/plymouth-git-master-20170123.patch
+++ /dev/null
@@ -1,5399 +0,0 @@
-diff --git a/Makefile.am b/Makefile.am
-index 395c91b..cb6eedb 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -4,7 +4,7 @@ if BUILD_DOCUMENTATION
- SUBDIRS += docs
- endif
- 
--DISTCHECK_CONFIGURE_FLAGS = --disable-tests --without-system-root-install
-+DISTCHECK_CONFIGURE_FLAGS = --disable-tests --disable-systemd-integration
- 
- EXTRA_DIST = ChangeLog                                                         \
-              README
-diff --git a/configure.ac b/configure.ac
-index aad673e..d145c69 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -1,4 +1,4 @@
--AC_INIT([plymouth],[0.9.2],[https://bugs.freedesktop.org/enter_bug.cgi?product=plymouth])
-+AC_INIT([plymouth],[0.9.3],[https://bugs.freedesktop.org/enter_bug.cgi?product=plymouth])
- AC_CONFIG_SRCDIR(src/main.c)
- AC_CONFIG_HEADER(config.h)
- AC_CONFIG_AUX_DIR(build-tools)
-@@ -11,7 +11,7 @@ AM_PROG_CC_C_O
- AC_HEADER_STDC
- AC_C_CONST
- 
--AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip])
-+AM_INIT_AUTOMAKE([dist-xz no-dist-gzip])
- m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
- AM_MAINTAINER_MODE([enable])
- 
-@@ -38,9 +38,18 @@ PKG_CHECK_MODULES(IMAGE, [libpng >= 1.2.16 ])
- AC_SUBST(IMAGE_CFLAGS)
- AC_SUBST(IMAGE_LIBS)
- 
--PKG_CHECK_MODULES(UDEV, [libudev]);
--AC_SUBST(UDEV_CFLAGS)
--AC_SUBST(UDEV_LIBS)
-+AC_ARG_WITH(udev, AS_HELP_STRING([--with-udev], [Add udev support]),, with_udev=yes)
-+
-+if test "x$with_udev" != "xno" ; then
-+  PKG_CHECK_MODULES(UDEV, [libudev], have_udev=yes, have_udev=no)
-+  AC_SUBST(UDEV_CFLAGS)
-+  AC_SUBST(UDEV_LIBS)
-+  if test "x$have_udev" = "xyes"; then
-+    AC_DEFINE(HAVE_UDEV, 1, [Define if have udev support])
-+  else
-+    AC_MSG_ERROR([libudev is required unless --without-udev is passed])
-+  fi
-+fi
- 
- PLYMOUTH_CFLAGS=""
- PLYMOUTH_LIBS="-lm -lrt -ldl"
-@@ -117,16 +126,21 @@ if test x$enable_upstart_monitoring = xyes; then
- fi
- AM_CONDITIONAL(ENABLE_UPSTART_MONITORING, [test "$enable_upstart_monitoring" = yes])
- 
--AC_ARG_ENABLE(systemd-integration, AS_HELP_STRING([--enable-systemd-integration],[coordinate boot up with systemd]),enable_systemd_integration=$enableval,enable_systemd_integration=no)
-+AC_ARG_ENABLE(systemd-integration, AS_HELP_STRING([--enable-systemd-integration],[coordinate boot up with systemd]),enable_systemd_integration=$enableval,enable_systemd_integration=yes)
- AM_CONDITIONAL(ENABLE_SYSTEMD_INTEGRATION, [test "$enable_systemd_integration" = yes])
- 
- if test x$enable_systemd_integration = xyes; then
-   AC_DEFINE(PLY_ENABLE_SYSTEMD_INTEGRATION, 1, [Coordinate boot up with systemd])
--  SYSTEMD_UNIT_DIR=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
-+  AC_ARG_WITH([systemdunitdir], AC_HELP_STRING([--with-systemdunitdir=DIR],
-+    [path to systemd service directory]), [path_systemdunit=${withval}],
-+      [path_systemdunit="`$PKG_CONFIG --variable=systemdsystemunitdir systemd`"])
-+  if (test -n "${path_systemdunit}"); then
-+    SYSTEMD_UNIT_DIR="${path_systemdunit}"
-+  fi
-   AC_SUBST(SYSTEMD_UNIT_DIR)
- fi
- 
--AC_ARG_WITH(system-root-install, AS_HELP_STRING([--with-system-root-install],[Install client in /bin and daemon in /sbin]),with_system_root_install=${withval},with_system_root_install=yes)
-+AC_ARG_WITH(system-root-install, AS_HELP_STRING([--with-system-root-install],[Install client in /bin and daemon in /sbin]),with_system_root_install=${withval},with_system_root_install=no)
- AM_CONDITIONAL(WITH_SYSTEM_ROOT_INSTALL,  [test "$with_system_root_install" = yes])
- 
- if test x$with_system_root_install = xyes; then
-diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in
-index 43c7f22..e3326e9 100755
---- a/scripts/plymouth-populate-initrd.in
-+++ b/scripts/plymouth-populate-initrd.in
-@@ -392,6 +392,9 @@ fi
- if [ $THEME_OVERRIDE ]; then
-     conf=$INITRDDIR/${PLYMOUTH_CONFDIR}/plymouthd.conf
-     echo "modifying plymouthd.conf: Theme=$PLYMOUTH_THEME_NAME" > /dev/stderr
-+    # make sure the section and key exist so we can modify them
-+    grep -q "^ *\[Daemon\]" $conf || echo "[Daemon]" >> $conf
-+    grep -q "^ *Theme *=" $conf || echo "Theme=fade-in" >> $conf
-     sed -i "s/^ *Theme *=.*/# theme modified by plymouth-populate-initrd\nTheme=$PLYMOUTH_THEME_NAME/" $conf
- fi
- 
-diff --git a/src/libply-splash-core/Makefile.am b/src/libply-splash-core/Makefile.am
-index d07d7f1..7036569 100644
---- a/src/libply-splash-core/Makefile.am
-+++ b/src/libply-splash-core/Makefile.am
-@@ -21,7 +21,6 @@ libply_splash_core_HEADERS = \
- 		    ply-pixel-display.h                                       \
- 		    ply-renderer.h                                            \
- 		    ply-renderer-plugin.h                                     \
--		    ply-seat.h                                                \
- 		    ply-terminal.h                                            \
- 		    ply-text-display.h                                        \
- 		    ply-text-progress-bar.h                                   \
-@@ -47,7 +46,6 @@ libply_splash_core_la_SOURCES = \
- 		    ply-terminal.c                                           \
- 		    ply-pixel-buffer.c                                       \
- 		    ply-renderer.c                                           \
--		    ply-seat.c                                               \
- 		    ply-boot-splash.c
- 
- MAINTAINERCLEANFILES = Makefile.in
-diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c
-index 310d4d5..87a7a0c 100644
---- a/src/libply-splash-core/ply-boot-splash.c
-+++ b/src/libply-splash-core/ply-boot-splash.c
-@@ -57,7 +57,10 @@ struct _ply_boot_splash
-         ply_boot_splash_mode_t                    mode;
-         ply_buffer_t                             *boot_buffer;
-         ply_trigger_t                            *idle_trigger;
--        ply_list_t                               *seats;
-+
-+        ply_keyboard_t                           *keyboard;
-+        ply_list_t                               *pixel_displays;
-+        ply_list_t                               *text_displays;
- 
-         char                                     *theme_path;
-         char                                     *plugin_dir;
-@@ -94,160 +97,102 @@ ply_boot_splash_new (const char   *theme_path,
-         splash->mode = PLY_BOOT_SPLASH_MODE_INVALID;
- 
-         splash->boot_buffer = boot_buffer;
--        splash->seats = ply_list_new ();
-+        splash->pixel_displays = ply_list_new ();
-+        splash->text_displays = ply_list_new ();
- 
-         return splash;
- }
- 
--static void
--detach_from_seat (ply_boot_splash_t *splash,
--                  ply_seat_t        *seat)
-+void
-+ply_boot_splash_set_keyboard (ply_boot_splash_t *splash,
-+                              ply_keyboard_t    *keyboard)
- {
--        ply_keyboard_t *keyboard;
--        ply_list_t *displays;
--        ply_list_node_t *node, *next_node;
--
--        ply_trace ("removing keyboard");
--        if (splash->plugin_interface->unset_keyboard != NULL) {
--                keyboard = ply_seat_get_keyboard (seat);
--                splash->plugin_interface->unset_keyboard (splash->plugin, keyboard);
--        }
--
--        ply_trace ("removing pixel displays");
--        displays = ply_seat_get_pixel_displays (seat);
--
--        node = ply_list_get_first_node (displays);
--        while (node != NULL) {
--                ply_pixel_display_t *display;
--                ply_list_node_t *next_node;
--                unsigned long width, height;
--
--                display = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (displays, node);
--
--                width = ply_pixel_display_get_width (display);
--                height = ply_pixel_display_get_height (display);
--
--                ply_trace ("Removing %lux%lu pixel display", width, height);
--
--                if (splash->plugin_interface->remove_pixel_display != NULL)
--                        splash->plugin_interface->remove_pixel_display (splash->plugin, display);
--
--                node = next_node;
--        }
--
--        ply_trace ("removing text displays");
--        displays = ply_seat_get_text_displays (seat);
--
--        node = ply_list_get_first_node (displays);
--        while (node != NULL) {
--                ply_text_display_t *display;
--                int number_of_columns, number_of_rows;
--
--                display = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (displays, node);
--
--                number_of_columns = ply_text_display_get_number_of_columns (display);
--                number_of_rows = ply_text_display_get_number_of_rows (display);
--
--                ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows);
--
--                if (splash->plugin_interface->remove_text_display != NULL)
--                        splash->plugin_interface->remove_text_display (splash->plugin, display);
-+        if (splash->plugin_interface->set_keyboard == NULL)
-+                return;
- 
--                node = next_node;
--        }
-+        splash->plugin_interface->set_keyboard (splash->plugin, keyboard);
-+        splash->keyboard = keyboard;
- }
- 
--static void
--attach_to_seat (ply_boot_splash_t *splash,
--                ply_seat_t        *seat)
-+void
-+ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash)
- {
--        ply_keyboard_t *keyboard;
--        ply_list_t *displays;
--        ply_list_node_t *node, *next_node;
--
--        if (splash->plugin_interface->set_keyboard != NULL) {
--                keyboard = ply_seat_get_keyboard (seat);
--                splash->plugin_interface->set_keyboard (splash->plugin, keyboard);
--        }
--
--        if (splash->plugin_interface->add_pixel_display != NULL) {
--                displays = ply_seat_get_pixel_displays (seat);
--
--                ply_trace ("adding pixel displays");
--                node = ply_list_get_first_node (displays);
--                while (node != NULL) {
--                        ply_pixel_display_t *display;
--                        ply_list_node_t *next_node;
--                        unsigned long width, height;
--
--                        display = ply_list_node_get_data (node);
--                        next_node = ply_list_get_next_node (displays, node);
-+        if (splash->plugin_interface->unset_keyboard == NULL)
-+                return;
- 
--                        width = ply_pixel_display_get_width (display);
--                        height = ply_pixel_display_get_height (display);
-+        splash->plugin_interface->unset_keyboard (splash->plugin, splash->keyboard);
-+}
- 
--                        ply_trace ("Adding %lux%lu pixel display", width, height);
-+void
-+ply_boot_splash_add_pixel_display (ply_boot_splash_t   *splash,
-+                                   ply_pixel_display_t *display)
-+{
-+        unsigned long width, height;
- 
--                        splash->plugin_interface->add_pixel_display (splash->plugin, display);
-+        if (splash->plugin_interface->add_pixel_display == NULL)
-+                return;
- 
--                        node = next_node;
--                }
--        }
-+        width = ply_pixel_display_get_width (display);
-+        height = ply_pixel_display_get_height (display);
- 
--        if (splash->plugin_interface->add_text_display != NULL) {
--                displays = ply_seat_get_text_displays (seat);
-+        ply_trace ("adding %lux%lu pixel display", width, height);
- 
--                ply_trace ("adding text displays");
--                node = ply_list_get_first_node (displays);
--                while (node != NULL) {
--                        ply_text_display_t *display;
--                        int number_of_columns, number_of_rows;
-+        splash->plugin_interface->add_pixel_display (splash->plugin, display);
-+        ply_list_append_data (splash->pixel_displays, display);
-+}
- 
--                        display = ply_list_node_get_data (node);
--                        next_node = ply_list_get_next_node (displays, node);
-+void
-+ply_boot_splash_remove_pixel_display (ply_boot_splash_t   *splash,
-+                                      ply_pixel_display_t *display)
-+{
-+        unsigned long width, height;
- 
--                        number_of_columns = ply_text_display_get_number_of_columns (display);
--                        number_of_rows = ply_text_display_get_number_of_rows (display);
-+        if (splash->plugin_interface->remove_pixel_display == NULL)
-+                return;
- 
--                        ply_trace ("Adding %dx%d text display", number_of_columns, number_of_rows);
-+        width = ply_pixel_display_get_width (display);
-+        height = ply_pixel_display_get_height (display);
- 
--                        splash->plugin_interface->add_text_display (splash->plugin, display);
-+        ply_trace ("removing %lux%lu pixel display", width, height);
- 
--                        node = next_node;
--                }
--        }
-+        splash->plugin_interface->remove_pixel_display (splash->plugin, display);
-+        ply_list_remove_data (splash->pixel_displays, display);
- }
- 
- void
--ply_boot_splash_attach_to_seat (ply_boot_splash_t *splash,
--                                ply_seat_t        *seat)
-+ply_boot_splash_add_text_display (ply_boot_splash_t  *splash,
-+                                  ply_text_display_t *display)
- {
--        ply_list_node_t *node;
-+        int number_of_columns, number_of_rows;
- 
--        node = ply_list_find_node (splash->seats, seat);
--
--        if (node != NULL)
-+        if (splash->plugin_interface->add_text_display == NULL)
-                 return;
- 
--        ply_list_append_data (splash->seats, seat);
--        attach_to_seat (splash, seat);
-+        number_of_columns = ply_text_display_get_number_of_columns (display);
-+        number_of_rows = ply_text_display_get_number_of_rows (display);
-+
-+        ply_trace ("adding %dx%d text display", number_of_columns, number_of_rows);
-+
-+        splash->plugin_interface->add_text_display (splash->plugin, display);
-+        ply_list_append_data (splash->text_displays, display);
- }
- 
- void
--ply_boot_splash_detach_from_seat (ply_boot_splash_t *splash,
--                                  ply_seat_t        *seat)
-+ply_boot_splash_remove_text_display (ply_boot_splash_t  *splash,
-+                                     ply_text_display_t *display)
- {
--        ply_list_node_t *node;
--
--        node = ply_list_find_node (splash->seats, seat);
-+        int number_of_columns, number_of_rows;
- 
--        if (node == NULL)
-+        if (splash->plugin_interface->remove_text_display == NULL)
-                 return;
- 
--        ply_list_remove_data (splash->seats, seat);
--        detach_from_seat (splash, seat);
-+        number_of_columns = ply_text_display_get_number_of_columns (display);
-+        number_of_rows = ply_text_display_get_number_of_rows (display);
-+
-+        ply_trace ("removing %dx%d text display", number_of_columns, number_of_rows);
-+
-+        splash->plugin_interface->remove_text_display (splash->plugin, display);
-+        ply_list_remove_data (splash->text_displays, display);
- }
- 
- bool
-@@ -378,23 +323,60 @@ ply_boot_splash_unload (ply_boot_splash_t *splash)
- }
- 
- static void
--detach_from_seats (ply_boot_splash_t *splash)
-+remove_pixel_displays (ply_boot_splash_t *splash)
-+{
-+        ply_list_node_t *node;
-+
-+        if (splash->plugin_interface->remove_pixel_display == NULL)
-+                return;
-+
-+        ply_trace ("removing pixel displays");
-+
-+        node = ply_list_get_first_node (splash->pixel_displays);
-+        while (node != NULL) {
-+                ply_pixel_display_t *display;
-+                ply_list_node_t *next_node;
-+                unsigned long width, height;
-+
-+                display = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (splash->pixel_displays, node);
-+
-+                width = ply_pixel_display_get_width (display);
-+                height = ply_pixel_display_get_height (display);
-+
-+                ply_trace ("Removing %lux%lu pixel display", width, height);
-+
-+                splash->plugin_interface->remove_pixel_display (splash->plugin, display);
-+
-+                node = next_node;
-+        }
-+}
-+
-+static void
-+remove_text_displays (ply_boot_splash_t *splash)
- {
-         ply_list_node_t *node;
- 
--        ply_trace ("detaching from seats");
-+        if (splash->plugin_interface->remove_text_display == NULL)
-+                return;
-+
-+        ply_trace ("removing text displays");
- 
--        node = ply_list_get_first_node (splash->seats);
-+        node = ply_list_get_first_node (splash->text_displays);
-         while (node != NULL) {
--                ply_seat_t *seat;
-+                ply_text_display_t *display;
-                 ply_list_node_t *next_node;
-+                int number_of_columns, number_of_rows;
- 
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (splash->seats, node);
-+                display = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (splash->text_displays, node);
- 
--                detach_from_seat (splash, seat);
-+                number_of_columns = ply_text_display_get_number_of_columns (display);
-+                number_of_rows = ply_text_display_get_number_of_rows (display);
-+
-+                ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows);
- 
--                ply_list_remove_node (splash->seats, node);
-+                splash->plugin_interface->remove_text_display (splash->plugin, display);
- 
-                 node = next_node;
-         }
-@@ -419,11 +401,17 @@ ply_boot_splash_free (ply_boot_splash_t *splash)
-                                                        splash);
-         }
- 
--        detach_from_seats (splash);
--        ply_list_free (splash->seats);
-+        if (splash->module_handle != NULL) {
-+                ply_boot_splash_unset_keyboard (splash);
-+
-+                remove_pixel_displays (splash);
-+                ply_list_free (splash->pixel_displays);
-+
-+                remove_text_displays (splash);
-+                ply_list_free (splash->text_displays);
- 
--        if (splash->module_handle != NULL)
-                 ply_boot_splash_unload (splash);
-+        }
- 
-         if (splash->idle_trigger != NULL)
-                 ply_trigger_free (splash->idle_trigger);
-diff --git a/src/libply-splash-core/ply-boot-splash.h b/src/libply-splash-core/ply-boot-splash.h
-index 0ad6f22..b66ca47 100644
---- a/src/libply-splash-core/ply-boot-splash.h
-+++ b/src/libply-splash-core/ply-boot-splash.h
-@@ -33,12 +33,10 @@
- #include "ply-pixel-display.h"
- #include "ply-text-display.h"
- #include "ply-progress.h"
--#include "ply-seat.h"
- 
- #include "ply-boot-splash-plugin.h"
- 
- typedef struct _ply_boot_splash ply_boot_splash_t;
--typedef struct _ply_seat ply_seat_t;
- 
- typedef void (*ply_boot_splash_on_idle_handler_t) (void *user_data);
- 
-@@ -50,10 +48,17 @@ ply_boot_splash_t *ply_boot_splash_new (const char   *theme_path,
- bool ply_boot_splash_load (ply_boot_splash_t *splash);
- bool ply_boot_splash_load_built_in (ply_boot_splash_t *splash);
- void ply_boot_splash_unload (ply_boot_splash_t *splash);
--void ply_boot_splash_attach_to_seat (ply_boot_splash_t *splash,
--                                     ply_seat_t        *seat);
--void ply_boot_splash_detach_from_seat (ply_boot_splash_t *splash,
--                                       ply_seat_t        *seat);
-+void ply_boot_splash_set_keyboard (ply_boot_splash_t *splash,
-+                                   ply_keyboard_t    *keyboard);
-+void ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash);
-+void ply_boot_splash_add_pixel_display (ply_boot_splash_t   *splash,
-+                                        ply_pixel_display_t *pixel_display);
-+void ply_boot_splash_remove_pixel_display (ply_boot_splash_t  *splash,
-+                                          ply_pixel_display_t *pixel_display);
-+void ply_boot_splash_add_text_display (ply_boot_splash_t   *splash,
-+                                       ply_text_display_t  *text_display);
-+void ply_boot_splash_remove_text_display (ply_boot_splash_t  *splash,
-+                                          ply_text_display_t *text_display);
- void ply_boot_splash_free (ply_boot_splash_t *splash);
- bool ply_boot_splash_show (ply_boot_splash_t     *splash,
-                            ply_boot_splash_mode_t mode);
-diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
-index 67eba32..b4c33d4 100644
---- a/src/libply-splash-core/ply-device-manager.c
-+++ b/src/libply-splash-core/ply-device-manager.c
-@@ -30,7 +30,9 @@
- #include <sys/stat.h>
- #include <sys/types.h>
- 
-+#ifdef HAVE_UDEV
- #include <libudev.h>
-+#endif
- 
- #include "ply-logger.h"
- #include "ply-event-loop.h"
-@@ -41,27 +43,40 @@
- #define SUBSYSTEM_DRM "drm"
- #define SUBSYSTEM_FRAME_BUFFER "graphics"
- 
--static void create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager,
--                                                        const char           *device_path,
--                                                        ply_terminal_t       *terminal,
--                                                        ply_renderer_type_t   renderer_type);
-+#ifdef HAVE_UDEV
-+static void create_devices_from_udev (ply_device_manager_t *manager);
-+#endif
-+
-+static void create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager,
-+                                                           const char           *device_path,
-+                                                           ply_terminal_t       *terminal,
-+                                                           ply_renderer_type_t   renderer_type);
- struct _ply_device_manager
- {
-         ply_device_manager_flags_t flags;
-         ply_event_loop_t          *loop;
-         ply_hashtable_t           *terminals;
-+        ply_hashtable_t           *renderers;
-         ply_terminal_t            *local_console_terminal;
--        ply_seat_t                *local_console_seat;
--        ply_list_t                *seats;
-+        ply_list_t                *keyboards;
-+        ply_list_t                *text_displays;
-+        ply_list_t                *pixel_displays;
-         struct udev               *udev_context;
--        struct udev_queue         *udev_queue;
--        int                        udev_queue_fd;
--        ply_fd_watch_t            *udev_queue_fd_watch;
-         struct udev_monitor       *udev_monitor;
- 
--        ply_seat_added_handler_t   seat_added_handler;
--        ply_seat_removed_handler_t seat_removed_handler;
--        void                      *seat_event_handler_data;
-+        ply_keyboard_added_handler_t         keyboard_added_handler;
-+        ply_keyboard_removed_handler_t       keyboard_removed_handler;
-+        ply_pixel_display_added_handler_t    pixel_display_added_handler;
-+        ply_pixel_display_removed_handler_t  pixel_display_removed_handler;
-+        ply_text_display_added_handler_t     text_display_added_handler;
-+        ply_text_display_removed_handler_t   text_display_removed_handler;
-+        void                                *event_handler_data;
-+
-+        uint32_t                    local_console_managed : 1;
-+        uint32_t                    local_console_is_text : 1;
-+        uint32_t                    serial_consoles_detected : 1;
-+        uint32_t                    renderers_activated : 1;
-+        uint32_t                    keyboards_activated : 1;
- };
- 
- static void
-@@ -87,64 +102,66 @@ attach_to_event_loop (ply_device_manager_t *manager,
-                                        manager);
- }
- 
--static bool
--device_is_for_local_console (ply_device_manager_t *manager,
--                             struct udev_device   *device)
--{
--        const char *device_path;
--        struct udev_device *bus_device;
--        char *bus_device_path;
--        const char *boot_vga;
--        bool for_local_console;
--
--        /* Look at the associated bus device to see if this card is the
--         * card the kernel is using for its console. */
--        device_path = udev_device_get_syspath (device);
--        asprintf (&bus_device_path, "%s/device", device_path);
--        bus_device = udev_device_new_from_syspath (manager->udev_context, bus_device_path);
--
--        boot_vga = udev_device_get_sysattr_value (bus_device, "boot_vga");
--        free (bus_device_path);
--
--        if (boot_vga != NULL && strcmp (boot_vga, "1") == 0)
--                for_local_console = true;
--        else
--                for_local_console = false;
--
--        return for_local_console;
--}
--
--static bool
--drm_device_in_use (ply_device_manager_t *manager,
--                   const char           *device_path)
-+static void
-+free_displays_for_renderer (ply_device_manager_t *manager,
-+                            ply_renderer_t       *renderer)
- {
-         ply_list_node_t *node;
- 
--        node = ply_list_get_first_node (manager->seats);
-+        node = ply_list_get_first_node (manager->pixel_displays);
-         while (node != NULL) {
--                ply_seat_t *seat;
--                ply_renderer_t *renderer;
-                 ply_list_node_t *next_node;
--                const char *renderer_device_path;
-+                ply_pixel_display_t *display;
-+                ply_renderer_t *display_renderer;
- 
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (manager->seats, node);
--                renderer = ply_seat_get_renderer (seat);
-+                display = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (manager->pixel_displays, node);
-+                display_renderer = ply_pixel_display_get_renderer (display);
- 
--                if (renderer != NULL) {
--                        renderer_device_path = ply_renderer_get_device_name (renderer);
-+                if (display_renderer == renderer) {
-+                        if (manager->pixel_display_removed_handler != NULL)
-+                                manager->pixel_display_removed_handler (manager->event_handler_data, display);
-+                        ply_pixel_display_free (display);
-+                        ply_list_remove_node (manager->pixel_displays, node);
- 
--                        if (renderer_device_path != NULL) {
--                                if (strcmp (device_path, renderer_device_path) == 0) {
--                                        return true;
--                                }
--                        }
-                 }
- 
-                 node = next_node;
-         }
-+}
- 
--        return false;
-+static void
-+free_devices_from_device_path (ply_device_manager_t *manager,
-+                               const char           *device_path)
-+{
-+        char *key = NULL;
-+        ply_renderer_t *renderer = NULL;
-+
-+        ply_hashtable_lookup_full (manager->renderers,
-+                                   (void *) device_path,
-+                                   (void **) &key,
-+                                   (void **) &renderer);
-+
-+        if (renderer == NULL)
-+                return;
-+
-+        free_displays_for_renderer (manager, renderer);
-+
-+        ply_hashtable_remove (manager->renderers, (void *) device_path);
-+        free (key);
-+        ply_renderer_free (renderer);
-+}
-+
-+#ifdef HAVE_UDEV
-+static bool
-+drm_device_in_use (ply_device_manager_t *manager,
-+                   const char           *device_path)
-+{
-+        ply_renderer_t *renderer;
-+
-+        renderer = ply_hashtable_lookup (manager->renderers, (void *) device_path);
-+
-+        return renderer != NULL;
- }
- 
- static bool
-@@ -196,19 +213,10 @@ fb_device_has_drm_device (ply_device_manager_t *manager,
- }
- 
- static void
--create_seat_for_udev_device (ply_device_manager_t *manager,
--                             struct udev_device   *device)
-+create_devices_for_udev_device (ply_device_manager_t *manager,
-+                                struct udev_device   *device)
- {
--        bool for_local_console;
-         const char *device_path;
--        ply_terminal_t *terminal = NULL;
--
--        for_local_console = device_is_for_local_console (manager, device);
--
--        ply_trace ("device is for local console: %s", for_local_console ? "yes" : "no");
--
--        if (for_local_console)
--                terminal = manager->local_console_terminal;
- 
-         device_path = udev_device_get_devnode (device);
- 
-@@ -231,7 +239,13 @@ create_seat_for_udev_device (ply_device_manager_t *manager,
-                 }
- 
-                 if (renderer_type != PLY_RENDERER_TYPE_NONE) {
--                        create_seat_for_terminal_and_renderer_type (manager,
-+                        ply_terminal_t *terminal = NULL;
-+
-+                        if (!manager->local_console_managed) {
-+                                terminal = manager->local_console_terminal;
-+                        }
-+
-+                        create_devices_for_terminal_and_renderer_type (manager,
-                                                                     device_path,
-                                                                     terminal,
-                                                                     renderer_type);
-@@ -240,64 +254,26 @@ create_seat_for_udev_device (ply_device_manager_t *manager,
- }
- 
- static void
--free_seat_from_device_path (ply_device_manager_t *manager,
--                            const char           *device_path)
--{
--        ply_list_node_t *node;
--
--        node = ply_list_get_first_node (manager->seats);
--        while (node != NULL) {
--                ply_seat_t *seat;
--                ply_renderer_t *renderer;
--                ply_list_node_t *next_node;
--                const char *renderer_device_path;
--
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (manager->seats, node);
--                renderer = ply_seat_get_renderer (seat);
--
--                if (renderer != NULL) {
--                        renderer_device_path = ply_renderer_get_device_name (renderer);
--
--                        if (renderer_device_path != NULL) {
--                                if (strcmp (device_path, renderer_device_path) == 0) {
--                                        ply_trace ("removing seat associated with %s", device_path);
--
--                                        if (manager->seat_removed_handler != NULL)
--                                                manager->seat_removed_handler (manager->seat_event_handler_data, seat);
--
--                                        ply_seat_free (seat);
--                                        ply_list_remove_node (manager->seats, node);
--                                        break;
--                                }
--                        }
--                }
--
--                node = next_node;
--        }
--}
--
--static void
--free_seat_for_udev_device (ply_device_manager_t *manager,
--                           struct udev_device   *device)
-+free_devices_for_udev_device (ply_device_manager_t *manager,
-+                              struct udev_device   *device)
- {
-         const char *device_path;
- 
-         device_path = udev_device_get_devnode (device);
- 
-         if (device_path != NULL)
--                free_seat_from_device_path (manager, device_path);
-+                free_devices_from_device_path (manager, device_path);
- }
- 
- static bool
--create_seats_for_subsystem (ply_device_manager_t *manager,
--                            const char           *subsystem)
-+create_devices_for_subsystem (ply_device_manager_t *manager,
-+                              const char           *subsystem)
- {
-         struct udev_enumerate *matches;
-         struct udev_list_entry *entry;
-         bool found_device = false;
- 
--        ply_trace ("creating seats for %s devices",
-+        ply_trace ("creating objects for %s devices",
-                    strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0 ?
-                    "frame buffer" :
-                    subsystem);
-@@ -326,7 +302,7 @@ create_seats_for_subsystem (ply_device_manager_t *manager,
-                 if (udev_device_get_is_initialized (device)) {
-                         ply_trace ("device is initialized");
- 
--                        /* We only care about devices assigned to a (any) seat. Floating
-+                        /* We only care about devices assigned to a (any) devices. Floating
-                          * devices should be ignored.
-                          */
-                         if (udev_device_has_tag (device, "seat")) {
-@@ -335,10 +311,10 @@ create_seats_for_subsystem (ply_device_manager_t *manager,
-                                 if (node != NULL) {
-                                         ply_trace ("found node %s", node);
-                                         found_device = true;
--                                        create_seat_for_udev_device (manager, device);
-+                                        create_devices_for_udev_device (manager, device);
-                                 }
-                         } else {
--                                ply_trace ("device doesn't have a seat tag");
-+                                ply_trace ("device doesn't have a devices tag");
-                         }
-                 } else {
-                         ply_trace ("it's not initialized");
-@@ -371,17 +347,19 @@ on_udev_event (ply_device_manager_t *manager)
- 
-         if (strcmp (action, "add") == 0) {
-                 const char *subsystem;
--                bool coldplug_complete = manager->udev_queue_fd_watch == NULL;
- 
-                 subsystem = udev_device_get_subsystem (device);
- 
--                if (strcmp (subsystem, SUBSYSTEM_DRM) == 0 ||
--                    coldplug_complete)
--                        create_seat_for_udev_device (manager, device);
--                else
--                        ply_trace ("ignoring since we only handle subsystem %s devices after coldplug completes", subsystem);
-+                if (strcmp (subsystem, SUBSYSTEM_DRM) == 0) {
-+                        if (manager->local_console_managed && manager->local_console_is_text)
-+                                ply_trace ("ignoring since we're already using text splash for local console");
-+                        else
-+                                create_devices_for_udev_device (manager, device);
-+                } else {
-+                        ply_trace ("ignoring since we only handle subsystem %s devices after timeout", subsystem);
-+                }
-         } else if (strcmp (action, "remove") == 0) {
--                free_seat_for_udev_device (manager, device);
-+                free_devices_for_udev_device (manager, device);
-         }
- 
-         udev_device_unref (device);
-@@ -413,30 +391,7 @@ watch_for_udev_events (ply_device_manager_t *manager)
-                                  NULL,
-                                  manager);
- }
--
--static void
--free_seats (ply_device_manager_t *manager)
--{
--        ply_list_node_t *node;
--
--        ply_trace ("removing seats");
--        node = ply_list_get_first_node (manager->seats);
--        while (node != NULL) {
--                ply_seat_t *seat;
--                ply_list_node_t *next_node;
--
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (manager->seats, node);
--
--                if (manager->seat_removed_handler != NULL)
--                        manager->seat_removed_handler (manager->seat_event_handler_data, seat);
--
--                ply_seat_free (seat);
--                ply_list_remove_node (manager->seats, node);
--
--                node = next_node;
--        }
--}
-+#endif
- 
- static void
- free_terminal (char                 *device,
-@@ -473,6 +428,10 @@ get_terminal (ply_device_manager_t *manager,
-             strcmp (full_name, "/dev/tty") == 0 ||
-             strcmp (full_name, ply_terminal_get_name (manager->local_console_terminal)) == 0) {
-                 terminal = manager->local_console_terminal;
-+
-+                ply_hashtable_insert (manager->terminals,
-+                                      (void *) ply_terminal_get_name (terminal),
-+                                      terminal);
-                 goto done;
-         }
- 
-@@ -491,6 +450,23 @@ done:
-         return terminal;
- }
- 
-+static void
-+free_renderer (char                 *device_path,
-+               ply_renderer_t       *renderer,
-+               ply_device_manager_t *manager)
-+{
-+        free_devices_from_device_path (manager, device_path);
-+}
-+
-+static void
-+free_renderers (ply_device_manager_t *manager)
-+{
-+        ply_hashtable_foreach (manager->renderers,
-+                               (ply_hashtable_foreach_func_t *)
-+                               free_renderer,
-+                               manager);
-+}
-+
- ply_device_manager_t *
- ply_device_manager_new (const char                *default_tty,
-                         ply_device_manager_flags_t flags)
-@@ -500,15 +476,19 @@ ply_device_manager_new (const char                *default_tty,
-         manager = calloc (1, sizeof(ply_device_manager_t));
-         manager->loop = NULL;
-         manager->terminals = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare);
-+        manager->renderers = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare);
-         manager->local_console_terminal = ply_terminal_new (default_tty);
--        ply_hashtable_insert (manager->terminals,
--                              (void *) ply_terminal_get_name (manager->local_console_terminal),
--                              manager->local_console_terminal);
--        manager->seats = ply_list_new ();
-+        manager->keyboards = ply_list_new ();
-+        manager->text_displays = ply_list_new ();
-+        manager->pixel_displays = ply_list_new ();
-         manager->flags = flags;
- 
-+#ifdef HAVE_UDEV
-         if (!(flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV))
-                 manager->udev_context = udev_new ();
-+#else
-+        manager->flags |= PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV;
-+#endif
- 
-         attach_to_event_loop (manager, ply_event_loop_get_default ());
- 
-@@ -527,17 +507,24 @@ ply_device_manager_free (ply_device_manager_t *manager)
-                                                (ply_event_loop_exit_handler_t)
-                                                detach_from_event_loop,
-                                                manager);
--        free_seats (manager);
--        ply_list_free (manager->seats);
- 
-         free_terminals (manager);
-         ply_hashtable_free (manager->terminals);
- 
-+        free_renderers (manager);
-+        ply_hashtable_free (manager->renderers);
-+
-+#ifdef HAVE_UDEV
-+        ply_event_loop_stop_watching_for_timeout (manager->loop,
-+                                         (ply_event_loop_timeout_handler_t)
-+                                         create_devices_from_udev, manager);
-+
-         if (manager->udev_monitor != NULL)
-                 udev_monitor_unref (manager->udev_monitor);
- 
-         if (manager->udev_context != NULL)
-                 udev_unref (manager->udev_context);
-+#endif
- 
-         free (manager);
- }
-@@ -615,53 +602,161 @@ add_consoles_from_file (ply_device_manager_t *manager,
- }
- 
- static void
--create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager,
--                                            const char           *device_path,
--                                            ply_terminal_t       *terminal,
--                                            ply_renderer_type_t   renderer_type)
-+create_pixel_displays_for_renderer (ply_device_manager_t *manager,
-+                                    ply_renderer_t       *renderer)
- {
--        ply_seat_t *seat;
--        bool is_local_terminal = false;
-+        ply_list_t *heads;
-+        ply_list_node_t *node;
-+
-+        heads = ply_renderer_get_heads (renderer);
- 
--        if (terminal != NULL && manager->local_console_terminal == terminal)
--                is_local_terminal = true;
-+        ply_trace ("Adding displays for %d heads",
-+                   ply_list_get_length (heads));
-+
-+        node = ply_list_get_first_node (heads);
-+        while (node != NULL) {
-+                ply_list_node_t *next_node;
-+                ply_renderer_head_t *head;
-+                ply_pixel_display_t *display;
-+
-+                head = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (heads, node);
-+
-+                display = ply_pixel_display_new (renderer, head);
-+
-+                ply_list_append_data (manager->pixel_displays, display);
-+
-+                if (manager->pixel_display_added_handler != NULL)
-+                        manager->pixel_display_added_handler (manager->event_handler_data, display);
-+                node = next_node;
-+        }
-+}
-+
-+static void
-+create_text_displays_for_terminal (ply_device_manager_t *manager,
-+                                   ply_terminal_t       *terminal)
-+{
-+  ply_text_display_t *display;
- 
--        if (is_local_terminal && manager->local_console_seat != NULL) {
--                ply_trace ("trying to create seat for local console when one already exists");
-+  if (!ply_terminal_is_open (terminal)) {
-+          if (!ply_terminal_open (terminal)) {
-+                  ply_trace ("could not add terminal %s: %m",
-+                             ply_terminal_get_name (terminal));
-+                  return;
-+          }
-+  }
-+
-+  ply_trace ("adding text display for terminal %s",
-+             ply_terminal_get_name (terminal));
-+
-+  display = ply_text_display_new (terminal);
-+  ply_list_append_data (manager->text_displays, display);
-+
-+  if (manager->text_display_added_handler != NULL)
-+          manager->text_display_added_handler (manager->event_handler_data, display);
-+}
-+
-+static void
-+create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager,
-+                                               const char           *device_path,
-+                                               ply_terminal_t       *terminal,
-+                                               ply_renderer_type_t   renderer_type)
-+{
-+        ply_renderer_t *renderer = NULL;
-+        ply_keyboard_t *keyboard = NULL;
-+
-+        if (device_path != NULL)
-+                renderer = ply_hashtable_lookup (manager->renderers, (void *) device_path);
-+
-+        if (renderer != NULL) {
-+                ply_trace ("ignoring device %s since it's already managed", device_path);
-                 return;
-         }
- 
--        ply_trace ("creating seat for %s (renderer type: %u) (terminal: %s)",
-+        ply_trace ("creating devices for %s (renderer type: %u) (terminal: %s)",
-                    device_path ? : "", renderer_type, terminal ? ply_terminal_get_name (terminal) : "none");
--        seat = ply_seat_new (terminal);
- 
--        if (!ply_seat_open (seat, renderer_type, device_path)) {
--                ply_trace ("could not create seat");
--                ply_seat_free (seat);
--                return;
-+        if (renderer_type != PLY_RENDERER_TYPE_NONE) {
-+                ply_renderer_t *old_renderer = NULL;
-+                renderer = ply_renderer_new (renderer_type, device_path, terminal);
-+
-+                if (renderer != NULL && !ply_renderer_open (renderer)) {
-+                        ply_trace ("could not open renderer for %s", device_path);
-+                        ply_renderer_free (renderer);
-+                        renderer = NULL;
-+
-+                        if (renderer_type != PLY_RENDERER_TYPE_AUTO)
-+                                return;
-+                }
-+
-+                if (renderer != NULL) {
-+                        old_renderer = ply_hashtable_lookup (manager->renderers,
-+                                                             (void *) ply_renderer_get_device_name (renderer));
-+
-+                        if (old_renderer != NULL) {
-+                                ply_trace ("ignoring device %s since it's alerady managed",
-+                                           ply_renderer_get_device_name (renderer));
-+                                ply_renderer_free (renderer);
-+
-+                                renderer = NULL;
-+                                return;
-+                        }
-+                }
-+        }
-+
-+        if (renderer != NULL) {
-+                keyboard = ply_keyboard_new_for_renderer (renderer);
-+                ply_list_append_data (manager->keyboards, keyboard);
-+
-+                if (manager->keyboard_added_handler != NULL)
-+                        manager->keyboard_added_handler (manager->event_handler_data, keyboard);
-+
-+                create_pixel_displays_for_renderer (manager, renderer);
-+                ply_hashtable_insert (manager->renderers, strdup (ply_renderer_get_device_name (renderer)), renderer);
-+                create_pixel_displays_for_renderer (manager, renderer);
-+
-+                if (manager->renderers_activated) {
-+                        ply_trace ("activating renderer");
-+                        ply_renderer_activate (renderer);
-+                }
-+
-+                if (terminal != NULL)
-+                        ply_terminal_refresh_geometry (terminal);
-+        } else if (terminal != NULL) {
-+                keyboard = ply_keyboard_new_for_terminal (terminal);
-+                ply_list_append_data (manager->keyboards, keyboard);
-+
-+                if (manager->keyboard_added_handler != NULL)
-+                        manager->keyboard_added_handler (manager->event_handler_data, keyboard);
-         }
- 
--        ply_list_append_data (manager->seats, seat);
-+        if (terminal != NULL) {
-+                create_text_displays_for_terminal (manager, terminal);
- 
--        if (is_local_terminal)
--                manager->local_console_seat = seat;
-+                if (terminal == manager->local_console_terminal) {
-+                        manager->local_console_is_text = renderer == NULL;
-+                        manager->local_console_managed = true;
-+                }
-+        }
- 
--        if (manager->seat_added_handler != NULL)
--                manager->seat_added_handler (manager->seat_event_handler_data, seat);
-+        if (keyboard != NULL && manager->keyboards_activated) {
-+                ply_trace ("activating keyboards");
-+                ply_keyboard_watch_for_input (keyboard);
-+        }
- }
- 
- static void
--create_seat_for_terminal (const char           *device_path,
--                          ply_terminal_t       *terminal,
--                          ply_device_manager_t *manager)
-+create_devices_for_terminal (const char           *device_path,
-+                             ply_terminal_t       *terminal,
-+                             ply_device_manager_t *manager)
- {
--        create_seat_for_terminal_and_renderer_type (manager,
--                                                    device_path,
--                                                    terminal,
--                                                    PLY_RENDERER_TYPE_NONE);
-+        create_devices_for_terminal_and_renderer_type (manager,
-+                                                       NULL,
-+                                                       terminal,
-+                                                       PLY_RENDERER_TYPE_NONE);
- }
- static bool
--create_seats_from_terminals (ply_device_manager_t *manager)
-+create_devices_from_terminals (ply_device_manager_t *manager)
- {
-         bool has_serial_consoles;
- 
-@@ -676,9 +771,11 @@ create_seats_from_terminals (ply_device_manager_t *manager)
- 
-         if (has_serial_consoles) {
-                 ply_trace ("serial consoles detected, managing them with details forced");
-+                manager->serial_consoles_detected = true;
-+
-                 ply_hashtable_foreach (manager->terminals,
-                                        (ply_hashtable_foreach_func_t *)
--                                       create_seat_for_terminal,
-+                                       create_devices_for_terminal,
-                                        manager);
-                 return true;
-         }
-@@ -686,145 +783,104 @@ create_seats_from_terminals (ply_device_manager_t *manager)
-         return false;
- }
- 
-+#ifdef HAVE_UDEV
- static void
--create_seats_from_udev (ply_device_manager_t *manager)
-+create_devices_from_udev (ply_device_manager_t *manager)
- {
-         bool found_drm_device, found_fb_device;
- 
--        ply_trace ("Looking for devices from udev");
-+        ply_trace ("Timeout elapsed, looking for devices from udev");
- 
--        found_drm_device = create_seats_for_subsystem (manager, SUBSYSTEM_DRM);
--        found_fb_device = create_seats_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
-+        found_drm_device = create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
-+        found_fb_device = create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
- 
-         if (found_drm_device || found_fb_device)
-                 return;
- 
--        ply_trace ("Creating non-graphical seat, since there's no suitable graphics hardware");
--        create_seat_for_terminal_and_renderer_type (manager,
--                                                    ply_terminal_get_name (manager->local_console_terminal),
--                                                    manager->local_console_terminal,
--                                                    PLY_RENDERER_TYPE_NONE);
--}
--
--static void
--create_fallback_seat (ply_device_manager_t *manager)
--{
--        create_seat_for_terminal_and_renderer_type (manager,
--                                                    ply_terminal_get_name (manager->local_console_terminal),
--                                                    manager->local_console_terminal,
--                                                    PLY_RENDERER_TYPE_AUTO);
-+        ply_trace ("Creating non-graphical devices, since there's no suitable graphics hardware");
-+        create_devices_for_terminal_and_renderer_type (manager,
-+                                                       NULL,
-+                                                       manager->local_console_terminal,
-+                                                       PLY_RENDERER_TYPE_NONE);
- }
-+#endif
- 
- static void
--on_udev_queue_changed (ply_device_manager_t *manager)
-+create_fallback_devices (ply_device_manager_t *manager)
- {
--        if (!udev_queue_get_queue_is_empty (manager->udev_queue))
--                return;
--
--        ply_trace ("udev coldplug complete");
--        ply_event_loop_stop_watching_fd (manager->loop, manager->udev_queue_fd_watch);
--        manager->udev_queue_fd_watch = NULL;
--        udev_queue_unref (manager->udev_queue);
--
--        close (manager->udev_queue_fd);
--        manager->udev_queue_fd = -1;
--
--        manager->udev_queue = NULL;
--
--        create_seats_from_udev (manager);
--}
--
--static void
--watch_for_coldplug_completion (ply_device_manager_t *manager)
--{
--        int fd;
--        int result;
--
--        manager->udev_queue = udev_queue_new (manager->udev_context);
--
--        if (udev_queue_get_queue_is_empty (manager->udev_queue)) {
--                ply_trace ("udev coldplug completed already ");
--                create_seats_from_udev (manager);
--                return;
--        }
--
--        fd = inotify_init1 (IN_CLOEXEC);
--        result = inotify_add_watch (fd, "/run/udev", IN_MOVED_TO| IN_DELETE);
--
--        if (result < 0) {
--                ply_trace ("could not watch for udev to show up: %m");
--                close (fd);
--
--                create_fallback_seat (manager);
--                return;
--        }
--
--        manager->udev_queue_fd = fd;
--
--        manager->udev_queue_fd_watch = ply_event_loop_watch_fd (manager->loop,
--                                                                fd,
--                                                                PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
--                                                                (ply_event_handler_t)
--                                                                on_udev_queue_changed,
--                                                                NULL,
--                                                                manager);
-+        create_devices_for_terminal_and_renderer_type (manager,
-+                                                       NULL,
-+                                                       manager->local_console_terminal,
-+                                                       PLY_RENDERER_TYPE_AUTO);
- }
- 
- void
--ply_device_manager_watch_seats (ply_device_manager_t      *manager,
--                                ply_seat_added_handler_t   seat_added_handler,
--                                ply_seat_removed_handler_t seat_removed_handler,
--                                void                      *data)
--{
--        bool done_with_initial_seat_setup;
--
--        manager->seat_added_handler = seat_added_handler;
--        manager->seat_removed_handler = seat_removed_handler;
--        manager->seat_event_handler_data = data;
--
--        /* Try to create seats for each serial device right away, if possible
-+ply_device_manager_watch_devices (ply_device_manager_t                *manager,
-+                                  double                               device_timeout,
-+                                  ply_keyboard_added_handler_t         keyboard_added_handler,
-+                                  ply_keyboard_removed_handler_t       keyboard_removed_handler,
-+                                  ply_pixel_display_added_handler_t    pixel_display_added_handler,
-+                                  ply_pixel_display_removed_handler_t  pixel_display_removed_handler,
-+                                  ply_text_display_added_handler_t     text_display_added_handler,
-+                                  ply_text_display_removed_handler_t   text_display_removed_handler,
-+                                  void                                *data)
-+{
-+        bool done_with_initial_devices_setup;
-+
-+        manager->keyboard_added_handler = keyboard_added_handler;
-+        manager->keyboard_removed_handler = keyboard_removed_handler;
-+        manager->pixel_display_added_handler = pixel_display_added_handler;
-+        manager->pixel_display_removed_handler = pixel_display_removed_handler;
-+        manager->text_display_added_handler = text_display_added_handler;
-+        manager->text_display_removed_handler = text_display_removed_handler;
-+        manager->event_handler_data = data;
-+
-+        /* Try to create devices for each serial device right away, if possible
-          */
--        done_with_initial_seat_setup = create_seats_from_terminals (manager);
-+        done_with_initial_devices_setup = create_devices_from_terminals (manager);
- 
--        if (done_with_initial_seat_setup)
-+        if (done_with_initial_devices_setup)
-                 return;
- 
-         if ((manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV)) {
--                ply_trace ("udev support disabled, creating fallback seat");
--                create_fallback_seat (manager);
-+                ply_trace ("udev support disabled, creating fallback devices");
-+                create_fallback_devices (manager);
-                 return;
-         }
- 
-+#ifdef HAVE_UDEV
-         watch_for_udev_events (manager);
--        watch_for_coldplug_completion (manager);
-+        create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
-+        ply_event_loop_watch_for_timeout (manager->loop,
-+                                         device_timeout,
-+                                         (ply_event_loop_timeout_handler_t)
-+                                         create_devices_from_udev, manager);
-+#endif
- }
- 
- bool
--ply_device_manager_has_open_seats (ply_device_manager_t *manager)
-+ply_device_manager_has_displays (ply_device_manager_t *manager)
- {
--        ply_list_node_t *node;
--
--        node = ply_list_get_first_node (manager->seats);
--        while (node != NULL) {
--                ply_seat_t *seat;
--                ply_list_node_t *next_node;
--
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (manager->seats, node);
--
--                if (ply_seat_is_open (seat))
--                        return true;
-+        return ply_list_get_length (manager->pixel_displays) > 0 ||
-+                ply_list_get_length (manager->text_displays) > 0;
-+}
- 
--                node = next_node;
--        }
-+ply_list_t *
-+ply_device_manager_get_keyboards (ply_device_manager_t *manager)
-+{
-+        return manager->keyboards;
-+}
- 
--        return false;
-+ply_list_t *
-+ply_device_manager_get_pixel_displays (ply_device_manager_t *manager)
-+{
-+        return manager->pixel_displays;
- }
- 
- ply_list_t *
--ply_device_manager_get_seats (ply_device_manager_t *manager)
-+ply_device_manager_get_text_displays (ply_device_manager_t *manager)
- {
--        return manager->seats;
-+        return manager->text_displays;
- }
- 
- ply_terminal_t *
-@@ -833,44 +889,49 @@ ply_device_manager_get_default_terminal (ply_device_manager_t *manager)
-         return manager->local_console_terminal;
- }
- 
-+bool
-+ply_device_manager_has_serial_consoles (ply_device_manager_t *manager)
-+{
-+        return manager->serial_consoles_detected;
-+}
-+
-+static void
-+activate_renderer (char                 *device_path,
-+                   ply_renderer_t       *renderer,
-+                   ply_device_manager_t *manager)
-+{
-+        ply_renderer_activate (renderer);
-+}
-+
- void
- ply_device_manager_activate_renderers (ply_device_manager_t *manager)
- {
--        ply_list_node_t *node;
--
-         ply_trace ("activating renderers");
--        node = ply_list_get_first_node (manager->seats);
--        while (node != NULL) {
--                ply_seat_t *seat;
--                ply_list_node_t *next_node;
--
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (manager->seats, node);
-+        ply_hashtable_foreach (manager->renderers,
-+                               (ply_hashtable_foreach_func_t *)
-+                               activate_renderer,
-+                               manager);
- 
--                ply_seat_activate_renderer (seat);
-+        manager->renderers_activated = true;
-+}
- 
--                node = next_node;
--        }
-+static void
-+deactivate_renderer (char                 *device_path,
-+                     ply_renderer_t       *renderer,
-+                     ply_device_manager_t *manager)
-+{
-+        ply_renderer_deactivate (renderer);
- }
- 
- void
- ply_device_manager_deactivate_renderers (ply_device_manager_t *manager)
- {
--        ply_list_node_t *node;
--
--        ply_trace ("deactivating renderers");
--        node = ply_list_get_first_node (manager->seats);
--        while (node != NULL) {
--                ply_seat_t *seat;
--                ply_list_node_t *next_node;
--
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (manager->seats, node);
--
--                ply_seat_deactivate_renderer (seat);
-+        ply_hashtable_foreach (manager->renderers,
-+                               (ply_hashtable_foreach_func_t *)
-+                               deactivate_renderer,
-+                               manager);
- 
--                node = next_node;
--        }
-+        manager->renderers_activated = false;
- }
- 
- void
-@@ -879,18 +940,20 @@ ply_device_manager_activate_keyboards (ply_device_manager_t *manager)
-         ply_list_node_t *node;
- 
-         ply_trace ("activating keyboards");
--        node = ply_list_get_first_node (manager->seats);
-+        node = ply_list_get_first_node (manager->keyboards);
-         while (node != NULL) {
--                ply_seat_t *seat;
-+                ply_keyboard_t *keyboard;
-                 ply_list_node_t *next_node;
- 
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (manager->seats, node);
-+                keyboard = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (manager->keyboards, node);
- 
--                ply_seat_activate_keyboard (seat);
-+                ply_keyboard_watch_for_input (keyboard);
- 
-                 node = next_node;
-         }
-+
-+        manager->keyboards_activated = true;
- }
- 
- void
-@@ -899,16 +962,18 @@ ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager)
-         ply_list_node_t *node;
- 
-         ply_trace ("deactivating keyboards");
--        node = ply_list_get_first_node (manager->seats);
-+        node = ply_list_get_first_node (manager->keyboards);
-         while (node != NULL) {
--                ply_seat_t *seat;
-+                ply_keyboard_t *keyboard;
-                 ply_list_node_t *next_node;
- 
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (manager->seats, node);
-+                keyboard = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (manager->keyboards, node);
- 
--                ply_seat_deactivate_keyboard (seat);
-+                ply_keyboard_stop_watching_for_input (keyboard);
- 
-                 node = next_node;
-         }
-+
-+        manager->keyboards_activated = false;
- }
-diff --git a/src/libply-splash-core/ply-device-manager.h b/src/libply-splash-core/ply-device-manager.h
-index c3e6487..058f6e8 100644
---- a/src/libply-splash-core/ply-device-manager.h
-+++ b/src/libply-splash-core/ply-device-manager.h
-@@ -21,7 +21,11 @@
- #define PLY_DEVICE_MANAGER_H
- 
- #include <stdbool.h>
--#include "ply-seat.h"
-+
-+#include "ply-keyboard.h"
-+#include "ply-pixel-display.h"
-+#include "ply-renderer.h"
-+#include "ply-text-display.h"
- 
- typedef enum
- {
-@@ -31,20 +35,30 @@ typedef enum
- } ply_device_manager_flags_t;
- 
- typedef struct _ply_device_manager ply_device_manager_t;
--typedef void (*ply_seat_added_handler_t) (void       *,
--                                          ply_seat_t *);
--typedef void (*ply_seat_removed_handler_t) (void       *,
--                                            ply_seat_t *);
-+typedef void (* ply_keyboard_added_handler_t) (void *, ply_keyboard_t *);
-+typedef void (* ply_keyboard_removed_handler_t) (void *, ply_keyboard_t *);
-+typedef void (* ply_pixel_display_added_handler_t) (void *, ply_pixel_display_t *);
-+typedef void (* ply_pixel_display_removed_handler_t) (void *, ply_pixel_display_t *);
-+typedef void (* ply_text_display_added_handler_t) (void *, ply_text_display_t *);
-+typedef void (* ply_text_display_removed_handler_t) (void *, ply_text_display_t *);
- 
- #ifndef PLY_HIDE_FUNCTION_DECLARATIONS
- ply_device_manager_t *ply_device_manager_new (const char                *default_tty,
-                                               ply_device_manager_flags_t flags);
--void ply_device_manager_watch_seats (ply_device_manager_t      *manager,
--                                     ply_seat_added_handler_t   seat_added_handler,
--                                     ply_seat_removed_handler_t seat_removed_handler,
--                                     void                      *data);
--bool ply_device_manager_has_open_seats (ply_device_manager_t *manager);
--ply_list_t *ply_device_manager_get_seats (ply_device_manager_t *manager);
-+void ply_device_manager_watch_devices (ply_device_manager_t                *manager,
-+                                       double                               device_timeout,
-+                                       ply_keyboard_added_handler_t         keyboard_added_handler,
-+                                       ply_keyboard_removed_handler_t       keyboard_removed_handler,
-+                                       ply_pixel_display_added_handler_t    pixel_display_added_handler,
-+                                       ply_pixel_display_removed_handler_t  pixel_display_removed_handler,
-+                                       ply_text_display_added_handler_t     text_display_added_handler,
-+                                       ply_text_display_removed_handler_t   text_display_removed_handler,
-+                                       void                                *data);
-+bool ply_device_manager_has_serial_consoles (ply_device_manager_t *manager);
-+bool ply_device_manager_has_displays (ply_device_manager_t *manager);
-+ply_list_t *ply_device_manager_get_keyboards (ply_device_manager_t *manager);
-+ply_list_t *ply_device_manager_get_pixel_displays (ply_device_manager_t *manager);
-+ply_list_t *ply_device_manager_get_text_displays (ply_device_manager_t *manager);
- void ply_device_manager_free (ply_device_manager_t *manager);
- void ply_device_manager_activate_keyboards (ply_device_manager_t *manager);
- void ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager);
-diff --git a/src/libply-splash-core/ply-keyboard.c b/src/libply-splash-core/ply-keyboard.c
-index ccf08e8..80f7694 100644
---- a/src/libply-splash-core/ply-keyboard.c
-+++ b/src/libply-splash-core/ply-keyboard.c
-@@ -93,6 +93,8 @@ struct _ply_keyboard
-         ply_list_t                  *backspace_handler_list;
-         ply_list_t                  *escape_handler_list;
-         ply_list_t                  *enter_handler_list;
-+
-+        uint32_t is_active : 1;
- };
- 
- static bool ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard);
-@@ -323,6 +325,12 @@ ply_keyboard_stop_watching_for_renderer_input (ply_keyboard_t *keyboard)
-                                          keyboard->provider.if_renderer->input_source);
- }
- 
-+bool
-+ply_keyboard_is_active (ply_keyboard_t *keyboard)
-+{
-+        return keyboard->is_active;
-+}
-+
- static void
- on_terminal_data (ply_keyboard_t *keyboard)
- {
-@@ -369,15 +377,20 @@ ply_keyboard_watch_for_input (ply_keyboard_t *keyboard)
- {
-         assert (keyboard != NULL);
- 
-+        if (keyboard->is_active)
-+                return true;
-+
-         switch (keyboard->provider_type) {
-         case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER:
--                return ply_keyboard_watch_for_renderer_input (keyboard);
-+                keyboard->is_active = ply_keyboard_watch_for_renderer_input (keyboard);
-+                break;
- 
-         case PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL:
--                return ply_keyboard_watch_for_terminal_input (keyboard);
-+                keyboard->is_active = ply_keyboard_watch_for_terminal_input (keyboard);
-+                break;
-         }
- 
--        return false;
-+        return keyboard->is_active;
- }
- 
- void
-@@ -385,6 +398,9 @@ ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard)
- {
-         assert (keyboard != NULL);
- 
-+        if (!keyboard->is_active)
-+                return;
-+
-         switch (keyboard->provider_type) {
-         case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER:
-                 ply_keyboard_stop_watching_for_renderer_input (keyboard);
-@@ -394,6 +410,8 @@ ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard)
-                 ply_keyboard_stop_watching_for_terminal_input (keyboard);
-                 break;
-         }
-+
-+        keyboard->is_active = false;
- }
- 
- void
-diff --git a/src/libply-splash-core/ply-keyboard.h b/src/libply-splash-core/ply-keyboard.h
-index 23497d9..6147cc7 100644
---- a/src/libply-splash-core/ply-keyboard.h
-+++ b/src/libply-splash-core/ply-keyboard.h
-@@ -71,6 +71,7 @@ void ply_keyboard_remove_enter_handler (ply_keyboard_t              *keyboard,
- 
- bool ply_keyboard_watch_for_input (ply_keyboard_t *keyboard);
- void ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard);
-+bool ply_keyboard_is_active (ply_keyboard_t *keyboard);
- 
- #endif
- 
-diff --git a/src/libply-splash-core/ply-pixel-buffer.c b/src/libply-splash-core/ply-pixel-buffer.c
-index c1825cc..52a3f86 100644
---- a/src/libply-splash-core/ply-pixel-buffer.c
-+++ b/src/libply-splash-core/ply-pixel-buffer.c
-@@ -37,14 +37,19 @@
- #include <stdlib.h>
- #include <unistd.h>
- 
-+#define ALPHA_MASK 0xff000000
-+
- struct _ply_pixel_buffer
- {
-         uint32_t       *bytes;
- 
--        ply_rectangle_t area;
--        ply_list_t     *clip_areas;
-+        ply_rectangle_t area; /* in device pixels */
-+        ply_rectangle_t logical_area; /* in logical pixels */
-+        ply_list_t     *clip_areas; /* in device pixels */
- 
--        ply_region_t   *updated_areas;
-+        ply_region_t   *updated_areas; /* in device pixels */
-+        uint32_t        is_opaque : 1;
-+        int             device_scale;
- };
- 
- static inline void ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
-@@ -166,6 +171,34 @@ ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
- }
- 
- static void
-+ply_rectangle_upscale (ply_rectangle_t *area,
-+                       int              scale)
-+{
-+        area->x *= scale;
-+        area->y *= scale;
-+        area->width *= scale;
-+        area->height *= scale;
-+}
-+
-+static void
-+ply_rectangle_downscale (ply_rectangle_t *area,
-+                         int              scale)
-+{
-+        area->x /= scale;
-+        area->y /= scale;
-+        area->width /= scale;
-+        area->height /= scale;
-+}
-+
-+static void
-+ply_pixel_buffer_adjust_area_for_device_scale (ply_pixel_buffer_t *buffer,
-+                                               ply_rectangle_t    *area)
-+{
-+        ply_rectangle_upscale (area, buffer->device_scale);
-+}
-+
-+/* this function will also convert logical pixels to device pixels */
-+static void
- ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer,
-                                          ply_rectangle_t    *area,
-                                          ply_rectangle_t    *cropped_area)
-@@ -173,6 +206,7 @@ ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer,
-         ply_list_node_t *node;
- 
-         *cropped_area = *area;
-+        ply_pixel_buffer_adjust_area_for_device_scale (buffer, cropped_area);
- 
-         node = ply_list_get_first_node (buffer->clip_areas);
-         while (node != NULL) {
-@@ -196,8 +230,19 @@ ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
-         unsigned long row, column;
-         ply_rectangle_t cropped_area;
- 
-+        if (fill_area == NULL)
-+                fill_area = &buffer->logical_area;
-+
-         ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
- 
-+        /* If we're filling the entire buffer with a fully opaque color,
-+         * then make note of it
-+         */
-+        if (fill_area == &buffer->area &&
-+            (pixel_value >> 24) == 0xff) {
-+                buffer->is_opaque = true;
-+        }
-+
-         for (row = cropped_area.y; row < cropped_area.y + cropped_area.height; row++) {
-                 for (column = cropped_area.x; column < cropped_area.x + cropped_area.width; column++) {
-                         ply_pixel_buffer_blend_value_at_pixel (buffer,
-@@ -205,6 +250,8 @@ ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
-                                                                pixel_value);
-                 }
-         }
-+
-+        ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
- }
- 
- void
-@@ -216,6 +263,8 @@ ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer,
-         new_clip_area = malloc (sizeof(*new_clip_area));
- 
-         *new_clip_area = *clip_area;
-+        ply_pixel_buffer_adjust_area_for_device_scale (buffer, new_clip_area);
-+
-         ply_list_append_data (buffer->clip_areas, new_clip_area);
- }
- 
-@@ -241,9 +290,12 @@ ply_pixel_buffer_new (unsigned long width,
-         buffer->bytes = (uint32_t *) calloc (height, width * sizeof(uint32_t));
-         buffer->area.width = width;
-         buffer->area.height = height;
-+        buffer->logical_area = buffer->area;
-+        buffer->device_scale = 1;
- 
-         buffer->clip_areas = ply_list_new ();
-         ply_pixel_buffer_push_clip_area (buffer, &buffer->area);
-+        buffer->is_opaque = false;
- 
-         return buffer;
- }
-@@ -278,21 +330,36 @@ ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer,
-         assert (buffer != NULL);
-         assert (size != NULL);
- 
--        *size = buffer->area;
-+        *size = buffer->logical_area;
- }
- 
- unsigned long
- ply_pixel_buffer_get_width (ply_pixel_buffer_t *buffer)
- {
-         assert (buffer != NULL);
--        return buffer->area.width;
-+        return buffer->logical_area.width;
- }
- 
- unsigned long
- ply_pixel_buffer_get_height (ply_pixel_buffer_t *buffer)
- {
-         assert (buffer != NULL);
--        return buffer->area.height;
-+        return buffer->logical_area.height;
-+}
-+
-+bool
-+ply_pixel_buffer_is_opaque (ply_pixel_buffer_t *buffer)
-+{
-+        assert (buffer != NULL);
-+        return buffer->is_opaque;
-+}
-+
-+void
-+ply_pixel_buffer_set_opaque (ply_pixel_buffer_t *buffer,
-+                             bool                is_opaque)
-+{
-+        assert (buffer != NULL);
-+        buffer->is_opaque = is_opaque;
- }
- 
- ply_region_t *
-@@ -359,7 +426,7 @@ ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
-         ply_rectangle_t cropped_area;
- 
-         if (fill_area == NULL)
--                fill_area = &buffer->area;
-+                fill_area = &buffer->logical_area;
- 
-         ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
- 
-@@ -430,24 +497,16 @@ ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer,
-                                   double              alpha)
- {
-         uint32_t pixel_value;
--        ply_rectangle_t cropped_area;
- 
-         assert (buffer != NULL);
- 
--        if (fill_area == NULL)
--                fill_area = &buffer->area;
--
--        ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
--
-         red *= alpha;
-         green *= alpha;
-         blue *= alpha;
- 
-         pixel_value = PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha);
- 
--        ply_pixel_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value);
--
--        ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
-+        ply_pixel_buffer_fill_area_with_pixel_value (buffer, fill_area, pixel_value);
- }
- 
- void
-@@ -456,7 +515,6 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
-                                                  uint32_t            hex_color,
-                                                  double              opacity)
- {
--        ply_rectangle_t cropped_area;
-         uint32_t pixel_value;
-         double red;
-         double green;
-@@ -465,11 +523,6 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
- 
-         assert (buffer != NULL);
- 
--        if (fill_area == NULL)
--                fill_area = &buffer->area;
--
--        ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
--
-         /* if they only gave an rgb hex number, assume an alpha of 0xff
-          */
-         if ((hex_color & 0xff000000) == 0)
-@@ -488,9 +541,7 @@ ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
- 
-         pixel_value = PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha);
- 
--        ply_pixel_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value);
--
--        ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
-+        ply_pixel_buffer_fill_area_with_pixel_value (buffer, fill_area, pixel_value);
- }
- 
- void
-@@ -502,48 +553,120 @@ ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer,
-                                                                 hex_color, 1.0);
- }
- 
-+static inline uint32_t
-+ply_pixels_interpolate (uint32_t *bytes,
-+                        int       width,
-+                        int       height,
-+                        double    x,
-+                        double    y)
-+{
-+        int ix;
-+        int iy;
-+        int i;
-+        int offset_x;
-+        int offset_y;
-+        uint32_t pixels[2][2];
-+        uint32_t reply = 0;
-+
-+        for (offset_y = 0; offset_y < 2; offset_y++) {
-+                for (offset_x = 0; offset_x < 2; offset_x++) {
-+                        ix = x + offset_x;
-+                        iy = y + offset_y;
-+
-+                        if (ix < 0 || ix >= width || iy < 0 || iy >= height)
-+                                pixels[offset_y][offset_x] = 0x00000000;
-+                        else
-+                                pixels[offset_y][offset_x] = bytes[ix + iy * width];
-+                }
-+        }
-+        if (!pixels[0][0] && !pixels[0][1] && !pixels[1][0] && !pixels[1][1]) return 0;
-+
-+        ix = x;
-+        iy = y;
-+        x -= ix;
-+        y -= iy;
-+        for (i = 0; i < 4; i++) {
-+                uint32_t value = 0;
-+                uint32_t mask = 0xFF << (i * 8);
-+                value += ((pixels[0][0]) & mask) * (1 - x) * (1 - y);
-+                value += ((pixels[0][1]) & mask) * x * (1 - y);
-+                value += ((pixels[1][0]) & mask) * (1 - x) * y;
-+                value += ((pixels[1][1]) & mask) * x * y;
-+                reply |= value & mask;
-+        }
-+        return reply;
-+}
-+
- void
--ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t *buffer,
--                                                             ply_rectangle_t    *fill_area,
--                                                             ply_rectangle_t    *clip_area,
--                                                             uint32_t           *data,
--                                                             double              opacity)
-+ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (ply_pixel_buffer_t *buffer,
-+                                                                       ply_rectangle_t    *fill_area,
-+                                                                       ply_rectangle_t    *clip_area,
-+                                                                       uint32_t           *data,
-+                                                                       double              opacity,
-+                                                                       int                 scale)
- {
-         unsigned long row, column;
-         uint8_t opacity_as_byte;
-+        ply_rectangle_t logical_fill_area;
-         ply_rectangle_t cropped_area;
-         unsigned long x;
-         unsigned long y;
-+        double scale_factor;
- 
-         assert (buffer != NULL);
- 
--        if (fill_area == NULL)
--                fill_area = &buffer->area;
-+        if (fill_area == NULL) {
-+                fill_area = &buffer->logical_area;
-+                logical_fill_area = buffer->logical_area;
-+        } else {
-+                logical_fill_area = *fill_area;
-+                ply_rectangle_downscale (&logical_fill_area, scale);
-+        }
- 
--        ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
-+        ply_pixel_buffer_crop_area_to_clip_area (buffer, &logical_fill_area, &cropped_area);
-+
-+        if (clip_area) {
-+                ply_rectangle_t device_clip_area;
- 
--        if (clip_area)
--                ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area);
-+                device_clip_area = *clip_area;
-+                ply_rectangle_downscale (&device_clip_area, scale);
-+                ply_pixel_buffer_adjust_area_for_device_scale (buffer, &device_clip_area);
-+                ply_rectangle_intersect (&cropped_area, &device_clip_area, &cropped_area);
-+        }
- 
-         if (cropped_area.width == 0 || cropped_area.height == 0)
-                 return;
- 
--        x = cropped_area.x - fill_area->x;
--        y = cropped_area.y - fill_area->y;
-         opacity_as_byte = (uint8_t) (opacity * 255.0);
-+        scale_factor = (double)scale / buffer->device_scale;
-+        x = cropped_area.x;
-+        y = cropped_area.y;
- 
-+        /* column, row are the point we want to write into, in
-+           pixel_buffer coordinate space (device pixels)
-+
-+           scale_factor * (column - fill_area->x), scale_factor * (row - fill_area->y)
-+           is the point we want to source from, in the data coordinate
-+           space */
-         for (row = y; row < y + cropped_area.height; row++) {
-                 for (column = x; column < x + cropped_area.width; column++) {
-                         uint32_t pixel_value;
- 
--                        pixel_value = data[fill_area->width * row + column];
-+                        if (buffer->device_scale == scale)
-+                                pixel_value = data[fill_area->width * (row - fill_area->y) +
-+                                                   column - fill_area->x];
-+                        else
-+                                pixel_value = ply_pixels_interpolate (data,
-+                                                                      fill_area->width,
-+                                                                      fill_area->height,
-+                                                                      scale_factor * column - fill_area->x,
-+                                                                      scale_factor * row - fill_area->y);
-                         if ((pixel_value >> 24) == 0x00)
-                                 continue;
- 
-                         pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte);
-                         ply_pixel_buffer_blend_value_at_pixel (buffer,
--                                                               cropped_area.x + (column - x),
--                                                               cropped_area.y + (row - y),
-+                                                               column, row,
-                                                                pixel_value);
-                 }
-         }
-@@ -552,15 +675,30 @@ ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t
- }
- 
- void
-+ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t *buffer,
-+                                                             ply_rectangle_t    *fill_area,
-+                                                             ply_rectangle_t    *clip_area,
-+                                                             uint32_t           *data,
-+                                                             double              opacity)
-+{
-+        ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer,
-+                                                                               fill_area,
-+                                                                               clip_area,
-+                                                                               data,
-+                                                                               opacity,
-+                                                                               1);
-+}
-+
-+void
- ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer,
-                                                    ply_rectangle_t    *fill_area,
-                                                    uint32_t           *data,
-                                                    double              opacity)
- {
--        ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
--                                                                     fill_area,
--                                                                     NULL,
--                                                                     data, opacity);
-+        ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer,
-+                                                                               fill_area,
-+                                                                               NULL,
-+                                                                               data, opacity, 1);
- }
- 
- void
-@@ -568,10 +706,10 @@ ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer,
-                                         ply_rectangle_t    *fill_area,
-                                         uint32_t           *data)
- {
--        ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
--                                                                     fill_area,
--                                                                     NULL,
--                                                                     data, 1.0);
-+        ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer,
-+                                                                               fill_area,
-+                                                                               NULL,
-+                                                                               data, 1.0, 1);
- }
- 
- void
-@@ -580,10 +718,25 @@ ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer,
-                                                   ply_rectangle_t    *clip_area,
-                                                   uint32_t           *data)
- {
--        ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
--                                                                     fill_area,
--                                                                     clip_area,
--                                                                     data, 1.0);
-+        ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (buffer,
-+                                                                               fill_area,
-+                                                                               clip_area,
-+                                                                               data, 1.0, 1);
-+}
-+
-+static void
-+ply_pixel_buffer_copy_area (ply_pixel_buffer_t *canvas,
-+                            ply_pixel_buffer_t *source,
-+                            int x, int y,
-+                            ply_rectangle_t *cropped_area)
-+{
-+        unsigned long row;
-+
-+        for (row = y; row < y + cropped_area->height; row++) {
-+                memcpy (canvas->bytes + (cropped_area->y + row - y) * canvas->area.width + cropped_area->x,
-+                        source->bytes + (row * source->area.width) + x,
-+                        cropped_area->width * 4);
-+        }
- }
- 
- void
-@@ -594,51 +747,51 @@ ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canv
-                                                         ply_rectangle_t    *clip_area,
-                                                         float               opacity)
- {
--        unsigned long row, column;
--        uint8_t opacity_as_byte;
--        ply_rectangle_t cropped_area;
-+        ply_rectangle_t fill_area;
-         unsigned long x;
-         unsigned long y;
- 
-         assert (canvas != NULL);
-         assert (source != NULL);
- 
--        cropped_area.x = x_offset;
--        cropped_area.y = y_offset;
--        cropped_area.width = source->area.width;
--        cropped_area.height = source->area.height;
-+        /* Fast path to memcpy if we need no blending or scaling */
-+        if (opacity == 1.0 && ply_pixel_buffer_is_opaque (source) &&
-+            canvas->device_scale == source->device_scale) {
-+                ply_rectangle_t cropped_area;
- 
--        ply_pixel_buffer_crop_area_to_clip_area (canvas, &cropped_area, &cropped_area);
-+                cropped_area.x = x_offset;
-+                cropped_area.y = y_offset;
-+                cropped_area.width = source->logical_area.width;
-+                cropped_area.height = source->logical_area.height;
- 
--        if (clip_area)
--                ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area);
-+                ply_pixel_buffer_crop_area_to_clip_area (canvas, &cropped_area, &cropped_area);
- 
--        if (cropped_area.width == 0 || cropped_area.height == 0)
--                return;
--
--        x = cropped_area.x - x_offset;
--        y = cropped_area.y - y_offset;
--        opacity_as_byte = (uint8_t) (opacity * 255.0);
--
--        for (row = y; row < y + cropped_area.height; row++) {
--                for (column = x; column < x + cropped_area.width; column++) {
--                        uint32_t pixel_value;
-+                /* clip_area is in source device pixels, which are also canvas device pixels */
-+                if (clip_area)
-+                        ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area);
- 
--                        pixel_value = source->bytes[row * source->area.width + column];
-+                if (cropped_area.width == 0 || cropped_area.height == 0)
-+                        return;
- 
--                        pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte);
-+                x = cropped_area.x - x_offset;
-+                y = cropped_area.y - y_offset;
- 
--                        if ((pixel_value >> 24) == 0x00)
--                                continue;
-+                ply_pixel_buffer_copy_area (canvas, source, x, y, &cropped_area);
- 
--                        ply_pixel_buffer_blend_value_at_pixel (canvas,
--                                                               cropped_area.x + (column - x),
--                                                               cropped_area.y + (row - y),
--                                                               pixel_value);
--                }
-+                ply_region_add_rectangle (canvas->updated_areas, &cropped_area);
-+        } else {
-+                fill_area.x = x_offset * source->device_scale;
-+                fill_area.y = y_offset * source->device_scale;
-+                fill_area.width = source->area.width;
-+                fill_area.height = source->area.height;
-+
-+                ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (canvas,
-+                                                                                       &fill_area,
-+                                                                                       clip_area,
-+                                                                                       source->bytes,
-+                                                                                       opacity,
-+                                                                                       source->device_scale);
-         }
--
--        ply_region_add_rectangle (canvas->updated_areas, &cropped_area);
- }
- 
- void
-@@ -696,52 +849,15 @@ ply_pixel_buffer_interpolate (ply_pixel_buffer_t *buffer,
-                               double              x,
-                               double              y)
- {
--        int ix;
--        int iy;
-         int width;
-         int height;
--
--        int i;
--
--        int offset_x;
--        int offset_y;
--        uint32_t pixels[2][2];
--        uint32_t reply = 0;
-         uint32_t *bytes;
- 
-         width = buffer->area.width;
-         height = buffer->area.height;
--
--
-         bytes = ply_pixel_buffer_get_argb32_data (buffer);
- 
--        for (offset_y = 0; offset_y < 2; offset_y++) {
--                for (offset_x = 0; offset_x < 2; offset_x++) {
--                        ix = x + offset_x;
--                        iy = y + offset_y;
--
--                        if (ix < 0 || ix >= width || iy < 0 || iy >= height)
--                                pixels[offset_y][offset_x] = 0x00000000;
--                        else
--                                pixels[offset_y][offset_x] = bytes[ix + iy * width];
--                }
--        }
--        if (!pixels[0][0] && !pixels[0][1] && !pixels[1][0] && !pixels[1][1]) return 0;
--
--        ix = x;
--        iy = y;
--        x -= ix;
--        y -= iy;
--        for (i = 0; i < 4; i++) {
--                uint32_t value = 0;
--                uint32_t mask = 0xFF << (i * 8);
--                value += ((pixels[0][0]) & mask) * (1 - x) * (1 - y);
--                value += ((pixels[0][1]) & mask) * x * (1 - y);
--                value += ((pixels[1][0]) & mask) * (1 - x) * y;
--                value += ((pixels[1][1]) & mask) * x * y;
--                reply |= value & mask;
--        }
--        return reply;
-+        return ply_pixels_interpolate (bytes, width, height, x, y);
- }
- 
- ply_pixel_buffer_t *
-@@ -753,7 +869,7 @@ ply_pixel_buffer_resize (ply_pixel_buffer_t *old_buffer,
-         int x, y;
-         double old_x, old_y;
-         int old_width, old_height;
--        float scale_x, scale_y;
-+        double scale_x, scale_y;
-         uint32_t *bytes;
- 
-         buffer = ply_pixel_buffer_new (width, height);
-@@ -852,4 +968,20 @@ ply_pixel_buffer_tile (ply_pixel_buffer_t *old_buffer,
-         return buffer;
- }
- 
-+int
-+ply_pixel_buffer_get_device_scale (ply_pixel_buffer_t *buffer)
-+{
-+        return buffer->device_scale;
-+}
-+
-+void
-+ply_pixel_buffer_set_device_scale (ply_pixel_buffer_t *buffer,
-+                                   int                 scale)
-+{
-+        buffer->device_scale = scale;
-+
-+        buffer->logical_area.width = buffer->area.width / scale;
-+        buffer->logical_area.height = buffer->area.height / scale;
-+}
-+
- /* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
-diff --git a/src/libply-splash-core/ply-pixel-buffer.h b/src/libply-splash-core/ply-pixel-buffer.h
-index 7848a98..595e9bd 100644
---- a/src/libply-splash-core/ply-pixel-buffer.h
-+++ b/src/libply-splash-core/ply-pixel-buffer.h
-@@ -43,10 +43,17 @@ ply_pixel_buffer_t *ply_pixel_buffer_new (unsigned long width,
- void ply_pixel_buffer_free (ply_pixel_buffer_t *buffer);
- void ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer,
-                                 ply_rectangle_t    *size);
-+int  ply_pixel_buffer_get_device_scale (ply_pixel_buffer_t *buffer);
-+void ply_pixel_buffer_set_device_scale (ply_pixel_buffer_t *buffer,
-+                                        int                 scale);
- 
- unsigned long ply_pixel_buffer_get_width (ply_pixel_buffer_t *buffer);
- unsigned long ply_pixel_buffer_get_height (ply_pixel_buffer_t *buffer);
- 
-+bool ply_pixel_buffer_is_opaque (ply_pixel_buffer_t *buffer);
-+void ply_pixel_buffer_set_opaque (ply_pixel_buffer_t *buffer,
-+                                  bool                is_opaque);
-+
- ply_region_t *ply_pixel_buffer_get_updated_areas (ply_pixel_buffer_t *buffer);
- 
- void ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer,
-@@ -86,6 +93,12 @@ void ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buff
-                                                                   ply_rectangle_t    *clip_area,
-                                                                   uint32_t           *data,
-                                                                   double              opacity);
-+void ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (ply_pixel_buffer_t *buffer,
-+                                                                            ply_rectangle_t    *fill_area,
-+                                                                            ply_rectangle_t    *clip_area,
-+                                                                            uint32_t           *data,
-+                                                                            double              opacity,
-+                                                                            int                 scale);
- 
- void ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canvas,
-                                                              ply_pixel_buffer_t *source,
-diff --git a/src/libply-splash-core/ply-pixel-display.c b/src/libply-splash-core/ply-pixel-display.c
-index b061bfc..cb01a2c 100644
---- a/src/libply-splash-core/ply-pixel-display.c
-+++ b/src/libply-splash-core/ply-pixel-display.c
-@@ -81,6 +81,18 @@ ply_pixel_display_new (ply_renderer_t      *renderer,
-         return display;
- }
- 
-+ply_renderer_t *
-+ply_pixel_display_get_renderer (ply_pixel_display_t *display)
-+{
-+        return display->renderer;
-+}
-+
-+ply_renderer_head_t *
-+ply_pixel_display_get_renderer_head (ply_pixel_display_t *display)
-+{
-+        return display->head;
-+}
-+
- unsigned long
- ply_pixel_display_get_width (ply_pixel_display_t *display)
- {
-diff --git a/src/libply-splash-core/ply-pixel-display.h b/src/libply-splash-core/ply-pixel-display.h
-index 62a36da..675c181 100644
---- a/src/libply-splash-core/ply-pixel-display.h
-+++ b/src/libply-splash-core/ply-pixel-display.h
-@@ -46,6 +46,9 @@ ply_pixel_display_t *ply_pixel_display_new (ply_renderer_t      *renderer,
- 
- void ply_pixel_display_free (ply_pixel_display_t *display);
- 
-+ply_renderer_t      *ply_pixel_display_get_renderer (ply_pixel_display_t *display);
-+ply_renderer_head_t *ply_pixel_display_get_renderer_head (ply_pixel_display_t *display);
-+
- unsigned long ply_pixel_display_get_width (ply_pixel_display_t *display);
- unsigned long ply_pixel_display_get_height (ply_pixel_display_t *display);
- 
-diff --git a/src/libply-splash-core/ply-renderer-plugin.h b/src/libply-splash-core/ply-renderer-plugin.h
-index 82ef913..f1455d3 100644
---- a/src/libply-splash-core/ply-renderer-plugin.h
-+++ b/src/libply-splash-core/ply-renderer-plugin.h
-@@ -66,6 +66,8 @@ typedef struct
- 
-         void (*close_input_source)(ply_renderer_backend_t      *backend,
-                                    ply_renderer_input_source_t *input_source);
-+
-+        const char * (*get_device_name)(ply_renderer_backend_t *backend);
- } ply_renderer_plugin_interface_t;
- 
- #endif /* PLY_RENDERER_PLUGIN_H */
-diff --git a/src/libply-splash-core/ply-renderer.c b/src/libply-splash-core/ply-renderer.c
-index f64eac5..b9059ef 100644
---- a/src/libply-splash-core/ply-renderer.c
-+++ b/src/libply-splash-core/ply-renderer.c
-@@ -55,6 +55,7 @@ struct _ply_renderer
- 
-         uint32_t                               input_source_is_open : 1;
-         uint32_t                               is_mapped : 1;
-+        uint32_t                               is_active : 1;
- };
- 
- typedef const ply_renderer_plugin_interface_t *
-@@ -154,6 +155,11 @@ ply_renderer_load_plugin (ply_renderer_t *renderer,
-                 return false;
-         }
- 
-+        if (renderer->plugin_interface->get_device_name != NULL) {
-+                free (renderer->device_name);
-+                renderer->device_name = strdup (renderer->plugin_interface->get_device_name (renderer->backend));
-+        }
-+
-         return true;
- }
- 
-@@ -268,15 +274,19 @@ ply_renderer_open (ply_renderer_t *renderer)
-                 { PLY_RENDERER_TYPE_NONE,         NULL                                             }
-         };
- 
-+        renderer->is_active = false;
-         for (i = 0; known_plugins[i].type != PLY_RENDERER_TYPE_NONE; i++) {
-                 if (renderer->type == known_plugins[i].type ||
-                     renderer->type == PLY_RENDERER_TYPE_AUTO)
--                        if (ply_renderer_open_plugin (renderer, known_plugins[i].path))
--                                return true;
-+                        if (ply_renderer_open_plugin (renderer, known_plugins[i].path)) {
-+                                renderer->is_active = true;
-+                                goto out;
-+                        }
-         }
- 
-         ply_trace ("could not find suitable rendering plugin");
--        return false;
-+out:
-+        return renderer->is_active;
- }
- 
- void
-@@ -284,6 +294,7 @@ ply_renderer_close (ply_renderer_t *renderer)
- {
-         ply_renderer_unmap_from_device (renderer);
-         ply_renderer_close_device (renderer);
-+        renderer->is_active = false;
- }
- 
- void
-@@ -291,7 +302,11 @@ ply_renderer_activate (ply_renderer_t *renderer)
- {
-         assert (renderer->plugin_interface != NULL);
- 
--        return renderer->plugin_interface->activate (renderer->backend);
-+        if (renderer->is_active)
-+              return;
-+
-+        renderer->plugin_interface->activate (renderer->backend);
-+        renderer->is_active = true;
- }
- 
- void
-@@ -302,6 +317,12 @@ ply_renderer_deactivate (ply_renderer_t *renderer)
-         return renderer->plugin_interface->deactivate (renderer->backend);
- }
- 
-+bool
-+ply_renderer_is_active (ply_renderer_t *renderer)
-+{
-+        return renderer->is_active;
-+}
-+
- ply_list_t *
- ply_renderer_get_heads (ply_renderer_t *renderer)
- {
-diff --git a/src/libply-splash-core/ply-renderer.h b/src/libply-splash-core/ply-renderer.h
-index a019a4d..59391e1 100644
---- a/src/libply-splash-core/ply-renderer.h
-+++ b/src/libply-splash-core/ply-renderer.h
-@@ -57,6 +57,7 @@ bool ply_renderer_open (ply_renderer_t *renderer);
- void ply_renderer_close (ply_renderer_t *renderer);
- void ply_renderer_activate (ply_renderer_t *renderer);
- void ply_renderer_deactivate (ply_renderer_t *renderer);
-+bool ply_renderer_is_active (ply_renderer_t *renderer);
- const char *ply_renderer_get_device_name (ply_renderer_t *renderer);
- ply_list_t *ply_renderer_get_heads (ply_renderer_t *renderer);
- ply_pixel_buffer_t *ply_renderer_get_buffer_for_head (ply_renderer_t      *renderer,
-diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c
-deleted file mode 100644
-index 700332f..0000000
---- a/src/libply-splash-core/ply-seat.c
-+++ /dev/null
-@@ -1,381 +0,0 @@
--/* ply-seat.c - APIs for encapsulating a keyboard and one or more displays
-- *
-- * Copyright (C) 2013 Red Hat, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This program 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 General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-- * 02111-1307, USA.
-- *
-- * Written by: Ray Strode <rstrode@redhat.com>
-- */
--#include "config.h"
--#include "ply-seat.h"
--
--#include <assert.h>
--#include <errno.h>
--#include <stdint.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <unistd.h>
--
--#include "ply-boot-splash.h"
--#include "ply-event-loop.h"
--#include "ply-keyboard.h"
--#include "ply-pixel-display.h"
--#include "ply-text-display.h"
--#include "ply-list.h"
--#include "ply-logger.h"
--#include "ply-utils.h"
--
--struct _ply_seat
--{
--        ply_event_loop_t  *loop;
--
--        ply_boot_splash_t *splash;
--        ply_terminal_t    *terminal;
--        ply_renderer_t    *renderer;
--        ply_keyboard_t    *keyboard;
--        ply_list_t        *text_displays;
--        ply_list_t        *pixel_displays;
--
--        uint32_t           renderer_active : 1;
--        uint32_t           keyboard_active : 1;
--};
--
--ply_seat_t *
--ply_seat_new (ply_terminal_t *terminal)
--{
--        ply_seat_t *seat;
--
--        seat = calloc (1, sizeof(ply_seat_t));
--
--        seat->loop = ply_event_loop_get_default ();
--        seat->terminal = terminal;
--        seat->text_displays = ply_list_new ();
--        seat->pixel_displays = ply_list_new ();
--
--        return seat;
--}
--
--static void
--add_pixel_displays (ply_seat_t *seat)
--{
--        ply_list_t *heads;
--        ply_list_node_t *node;
--
--        heads = ply_renderer_get_heads (seat->renderer);
--
--        ply_trace ("Adding displays for %d heads",
--                   ply_list_get_length (heads));
--
--        node = ply_list_get_first_node (heads);
--        while (node != NULL) {
--                ply_list_node_t *next_node;
--                ply_renderer_head_t *head;
--                ply_pixel_display_t *display;
--
--                head = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (heads, node);
--
--                display = ply_pixel_display_new (seat->renderer, head);
--
--                ply_list_append_data (seat->pixel_displays, display);
--
--                node = next_node;
--        }
--}
--
--static void
--add_text_displays (ply_seat_t *seat)
--{
--        ply_text_display_t *display;
--
--        if (!ply_terminal_is_open (seat->terminal)) {
--                if (!ply_terminal_open (seat->terminal)) {
--                        ply_trace ("could not add terminal %s: %m",
--                                   ply_terminal_get_name (seat->terminal));
--                        return;
--                }
--        }
--
--        ply_trace ("adding text display for terminal %s",
--                   ply_terminal_get_name (seat->terminal));
--
--        display = ply_text_display_new (seat->terminal);
--        ply_list_append_data (seat->text_displays, display);
--}
--
--bool
--ply_seat_open (ply_seat_t         *seat,
--               ply_renderer_type_t renderer_type,
--               const char         *device)
--{
--        if (renderer_type != PLY_RENDERER_TYPE_NONE) {
--                ply_renderer_t *renderer;
--
--                renderer = ply_renderer_new (renderer_type, device, seat->terminal);
--
--                if (!ply_renderer_open (renderer)) {
--                        ply_trace ("could not open renderer for %s", device);
--                        ply_renderer_free (renderer);
--
--                        seat->renderer = NULL;
--                        seat->renderer_active = false;
--
--                        if (renderer_type != PLY_RENDERER_TYPE_AUTO)
--                                return false;
--                } else {
--                        seat->renderer = renderer;
--                        seat->renderer_active = true;
--                }
--        }
--
--        if (seat->renderer != NULL) {
--                seat->keyboard = ply_keyboard_new_for_renderer (seat->renderer);
--                add_pixel_displays (seat);
--        } else if (seat->terminal != NULL) {
--                seat->keyboard = ply_keyboard_new_for_terminal (seat->terminal);
--        }
--
--        if (seat->terminal != NULL) {
--                add_text_displays (seat);
--        } else {
--                ply_trace ("not adding text display for seat, since seat has no associated terminal");
--        }
--
--        if (seat->keyboard != NULL) {
--                ply_keyboard_watch_for_input (seat->keyboard);
--                seat->keyboard_active = true;
--        } else {
--                ply_trace ("not watching seat for input");
--        }
--
--        return true;
--}
--
--bool
--ply_seat_is_open (ply_seat_t *seat)
--{
--        return ply_list_get_length (seat->pixel_displays) > 0 ||
--               ply_list_get_length (seat->text_displays) > 0;
--}
--
--void
--ply_seat_deactivate_keyboard (ply_seat_t *seat)
--{
--        if (!seat->keyboard_active)
--                return;
--
--        seat->keyboard_active = false;
--
--        if (seat->keyboard == NULL)
--                return;
--
--        ply_trace ("deactivating keyboard");
--        ply_keyboard_stop_watching_for_input (seat->keyboard);
--}
--
--void
--ply_seat_deactivate_renderer (ply_seat_t *seat)
--{
--        if (!seat->renderer_active)
--                return;
--
--        seat->renderer_active = false;
--
--        if (seat->renderer == NULL)
--                return;
--
--        ply_trace ("deactivating renderer");
--        ply_renderer_deactivate (seat->renderer);
--}
--
--void
--ply_seat_activate_keyboard (ply_seat_t *seat)
--{
--        if (seat->keyboard_active)
--                return;
--
--        if (seat->keyboard == NULL)
--                return;
--
--        ply_trace ("activating keyboard");
--        ply_keyboard_watch_for_input (seat->keyboard);
--
--        seat->keyboard_active = true;
--}
--
--void
--ply_seat_activate_renderer (ply_seat_t *seat)
--{
--        if (seat->renderer_active)
--                return;
--
--        if (seat->renderer == NULL)
--                return;
--
--        ply_trace ("activating renderer");
--        ply_renderer_activate (seat->renderer);
--
--        seat->renderer_active = true;
--}
--
--void
--ply_seat_refresh_displays (ply_seat_t *seat)
--{
--        ply_list_node_t *node;
--
--        node = ply_list_get_first_node (seat->pixel_displays);
--        while (node != NULL) {
--                ply_pixel_display_t *display;
--                ply_list_node_t *next_node;
--                unsigned long width, height;
--
--                display = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (seat->pixel_displays, node);
--
--                width = ply_pixel_display_get_width (display);
--                height = ply_pixel_display_get_height (display);
--
--                ply_pixel_display_draw_area (display, 0, 0, width, height);
--                node = next_node;
--        }
--
--        node = ply_list_get_first_node (seat->text_displays);
--        while (node != NULL) {
--                ply_text_display_t *display;
--                ply_list_node_t *next_node;
--                int number_of_columns, number_of_rows;
--
--                display = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (seat->text_displays, node);
--
--                number_of_columns = ply_text_display_get_number_of_columns (display);
--                number_of_rows = ply_text_display_get_number_of_rows (display);
--
--                ply_text_display_draw_area (display, 0, 0,
--                                            number_of_columns,
--                                            number_of_rows);
--                node = next_node;
--        }
--}
--
--void
--ply_seat_close (ply_seat_t *seat)
--{
--        if (seat->renderer == NULL)
--                return;
--
--        ply_trace ("destroying renderer");
--        ply_renderer_close (seat->renderer);
--        ply_renderer_free (seat->renderer);
--        seat->renderer = NULL;
--}
--
--void
--ply_seat_set_splash (ply_seat_t        *seat,
--                     ply_boot_splash_t *splash)
--{
--        if (seat->splash == splash)
--                return;
--
--        if (seat->splash != NULL)
--                ply_boot_splash_detach_from_seat (splash, seat);
--
--        if (splash != NULL)
--                ply_boot_splash_attach_to_seat (splash, seat);
--
--        seat->splash = splash;
--}
--
--static void
--free_pixel_displays (ply_seat_t *seat)
--{
--        ply_list_node_t *node;
--
--        ply_trace ("freeing %d pixel displays", ply_list_get_length (seat->pixel_displays));
--        node = ply_list_get_first_node (seat->pixel_displays);
--        while (node != NULL) {
--                ply_list_node_t *next_node;
--                ply_pixel_display_t *display;
--
--                next_node = ply_list_get_next_node (seat->pixel_displays, node);
--                display = ply_list_node_get_data (node);
--                ply_pixel_display_free (display);
--
--                ply_list_remove_node (seat->pixel_displays, node);
--
--                node = next_node;
--        }
--}
--
--static void
--free_text_displays (ply_seat_t *seat)
--{
--        ply_list_node_t *node;
--
--        ply_trace ("freeing %d text displays", ply_list_get_length (seat->text_displays));
--        node = ply_list_get_first_node (seat->text_displays);
--        while (node != NULL) {
--                ply_list_node_t *next_node;
--                ply_text_display_t *display;
--
--                next_node = ply_list_get_next_node (seat->text_displays, node);
--                display = ply_list_node_get_data (node);
--                ply_text_display_free (display);
--
--                ply_list_remove_node (seat->text_displays, node);
--
--                node = next_node;
--        }
--}
--
--void
--ply_seat_free (ply_seat_t *seat)
--{
--        if (seat == NULL)
--                return;
--
--        free_pixel_displays (seat);
--        free_text_displays (seat);
--        ply_keyboard_free (seat->keyboard);
--
--        free (seat);
--}
--
--ply_list_t *
--ply_seat_get_pixel_displays (ply_seat_t *seat)
--{
--        return seat->pixel_displays;
--}
--
--ply_list_t *
--ply_seat_get_text_displays (ply_seat_t *seat)
--{
--        return seat->text_displays;
--}
--
--ply_keyboard_t *
--ply_seat_get_keyboard (ply_seat_t *seat)
--{
--        return seat->keyboard;
--}
--
--ply_renderer_t *
--ply_seat_get_renderer (ply_seat_t *seat)
--{
--        return seat->renderer;
--}
--
--/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
-diff --git a/src/libply-splash-core/ply-seat.h b/src/libply-splash-core/ply-seat.h
-deleted file mode 100644
-index f9ed15d..0000000
---- a/src/libply-splash-core/ply-seat.h
-+++ /dev/null
-@@ -1,66 +0,0 @@
--/* ply-seat.h - APIs for encapsulating a keyboard and one or more displays
-- *
-- * Copyright (C) 2013 Red Hat, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This program 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 General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-- * 02111-1307, USA.
-- *
-- * Written By: Ray Strode <rstrode@redhat.com>
-- */
--#ifndef PLY_SEAT_H
--#define PLY_SEAT_H
--
--#include <stdarg.h>
--#include <stdbool.h>
--#include <stdint.h>
--#include <unistd.h>
--
--#include "ply-boot-splash.h"
--#include "ply-buffer.h"
--#include "ply-event-loop.h"
--#include "ply-keyboard.h"
--#include "ply-list.h"
--#include "ply-pixel-display.h"
--#include "ply-terminal.h"
--#include "ply-text-display.h"
--
--typedef struct _ply_boot_splash ply_boot_splash_t;
--typedef struct _ply_seat ply_seat_t;
--
--#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
--ply_seat_t *ply_seat_new (ply_terminal_t *terminal);
--
--void ply_seat_free (ply_seat_t *seat);
--bool ply_seat_open (ply_seat_t         *seat,
--                    ply_renderer_type_t renderer_type,
--                    const char         *device);
--bool ply_seat_is_open (ply_seat_t *seat);
--void ply_seat_deactivate_keyboard (ply_seat_t *seat);
--void ply_seat_activate_keyboard (ply_seat_t *seat);
--void ply_seat_deactivate_renderer (ply_seat_t *seat);
--void ply_seat_activate_renderer (ply_seat_t *seat);
--void ply_seat_refresh_displays (ply_seat_t *seat);
--void ply_seat_close (ply_seat_t *seat);
--void ply_seat_set_splash (ply_seat_t        *seat,
--                          ply_boot_splash_t *splash);
--
--ply_list_t *ply_seat_get_pixel_displays (ply_seat_t *seat);
--ply_list_t *ply_seat_get_text_displays (ply_seat_t *seat);
--ply_keyboard_t *ply_seat_get_keyboard (ply_seat_t *seat);
--ply_renderer_t *ply_seat_get_renderer (ply_seat_t *seat);
--#endif
--
--#endif /* PLY_SEAT_H */
--/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
-diff --git a/src/libply-splash-core/ply-terminal.c b/src/libply-splash-core/ply-terminal.c
-index 1bbeb42..a0954f2 100644
---- a/src/libply-splash-core/ply-terminal.c
-+++ b/src/libply-splash-core/ply-terminal.c
-@@ -387,8 +387,8 @@ on_tty_disconnected (ply_terminal_t *terminal)
-         ply_terminal_reopen_device (terminal);
- }
- 
--static bool
--ply_terminal_look_up_geometry (ply_terminal_t *terminal)
-+bool
-+ply_terminal_refresh_geometry (ply_terminal_t *terminal)
- {
-         struct winsize terminal_size;
- 
-@@ -551,7 +551,7 @@ ply_terminal_open_device (ply_terminal_t *terminal)
-         assert (terminal->fd < 0);
-         assert (terminal->fd_watch == NULL);
- 
--        terminal->fd = open (terminal->name, O_RDWR | O_NOCTTY);
-+        terminal->fd = open (terminal->name, O_RDWR | O_NOCTTY | O_NONBLOCK);
- 
-         if (terminal->fd < 0) {
-                 ply_trace ("Unable to open terminal device '%s': %m", terminal->name);
-@@ -570,6 +570,8 @@ ply_terminal_open_device (ply_terminal_t *terminal)
-                 return PLY_TERMINAL_OPEN_RESULT_FAILURE;
-         }
- 
-+        ply_set_fd_as_blocking (terminal->fd);
-+
-         terminal->fd_watch = ply_event_loop_watch_fd (terminal->loop, terminal->fd,
-                                                       PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
-                                                       (ply_event_handler_t) on_tty_input,
-@@ -605,7 +607,7 @@ ply_terminal_open (ply_terminal_t *terminal)
-                 return false;
-         }
- 
--        ply_terminal_look_up_geometry (terminal);
-+        ply_terminal_refresh_geometry (terminal);
- 
-         ply_terminal_look_up_color_palette (terminal);
-         ply_terminal_save_color_palette (terminal);
-@@ -613,7 +615,7 @@ ply_terminal_open (ply_terminal_t *terminal)
-         ply_event_loop_watch_signal (terminal->loop,
-                                      SIGWINCH,
-                                      (ply_event_handler_t)
--                                     ply_terminal_look_up_geometry,
-+                                     ply_terminal_refresh_geometry,
-                                      terminal);
- 
-         if (ply_terminal_is_vt (terminal)) {
-diff --git a/src/libply-splash-core/ply-terminal.h b/src/libply-splash-core/ply-terminal.h
-index dc83ec3..7cfcc59 100644
---- a/src/libply-splash-core/ply-terminal.h
-+++ b/src/libply-splash-core/ply-terminal.h
-@@ -69,6 +69,7 @@ void ply_terminal_reset_colors (ply_terminal_t *terminal);
- 
- bool ply_terminal_set_unbuffered_input (ply_terminal_t *terminal);
- bool ply_terminal_set_buffered_input (ply_terminal_t *terminal);
-+bool ply_terminal_refresh_geometry (ply_terminal_t *terminal);
- 
- __attribute__((__format__ (__printf__, 2, 3)))
- void ply_terminal_write (ply_terminal_t *terminal,
-diff --git a/src/libply-splash-graphics/ply-animation.c b/src/libply-splash-graphics/ply-animation.c
-index 81348f9..323d9ed 100644
---- a/src/libply-splash-graphics/ply-animation.c
-+++ b/src/libply-splash-graphics/ply-animation.c
-@@ -353,6 +353,11 @@ ply_animation_stop_now (ply_animation_t *animation)
- void
- ply_animation_stop (ply_animation_t *animation)
- {
-+        if (animation->is_stopped) {
-+                ply_trace ("animation already stopped, ignoring stop request");
-+                return;
-+        }
-+
-         if (animation->stop_trigger == NULL) {
-                 ply_animation_stop_now (animation);
-                 return;
-diff --git a/src/libply-splash-graphics/ply-image.c b/src/libply-splash-graphics/ply-image.c
-index f838601..8b46978 100644
---- a/src/libply-splash-graphics/ply-image.c
-+++ b/src/libply-splash-graphics/ply-image.c
-@@ -99,10 +99,13 @@ transform_to_argb32 (png_struct   *png,
-                 blue = data[i + 2];
-                 alpha = data[i + 3];
- 
--                red = (uint8_t) CLAMP (((red / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0);
--                green = (uint8_t) CLAMP (((green / 255.0) * (alpha / 255.0)) * 255.0,
--                                         0, 255.0);
--                blue = (uint8_t) CLAMP (((blue / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0);
-+                /* pre-multiply the alpha if there's translucency */
-+                if (alpha != 0xff) {
-+                        red = (uint8_t) CLAMP (((red / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0);
-+                        green = (uint8_t) CLAMP (((green / 255.0) * (alpha / 255.0)) * 255.0,
-+                                                 0, 255.0);
-+                        blue = (uint8_t) CLAMP (((blue / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0);
-+                }
- 
-                 pixel_value = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
-                 memcpy (data + i, &pixel_value, sizeof(uint32_t));
-diff --git a/src/libply-splash-graphics/ply-throbber.c b/src/libply-splash-graphics/ply-throbber.c
-index c9c5bbd..f18feb6 100644
---- a/src/libply-splash-graphics/ply-throbber.c
-+++ b/src/libply-splash-graphics/ply-throbber.c
-@@ -337,6 +337,15 @@ void
- ply_throbber_stop (ply_throbber_t *throbber,
-                    ply_trigger_t  *stop_trigger)
- {
-+        if (throbber->is_stopped) {
-+                ply_trace ("throbber already stopped");
-+                if (stop_trigger != NULL) {
-+                        ply_trace ("pulling stop trigger right away");
-+                        ply_trigger_pull (stop_trigger, NULL);
-+                }
-+                return;
-+        }
-+
-         if (stop_trigger == NULL) {
-                 ply_throbber_stop_now (throbber);
-                 return;
-diff --git a/src/libply/ply-logger.h b/src/libply/ply-logger.h
-index de23181..545e64c 100644
---- a/src/libply/ply-logger.h
-+++ b/src/libply/ply-logger.h
-@@ -92,7 +92,7 @@ bool ply_logger_is_tracing_enabled (ply_logger_t *logger);
-                         ply_logger_flush (logger);                                             \
-                         errno = _old_errno;                                                    \
-                         ply_logger_inject (logger,                                             \
--                                           "[%s:%d] %45.45s:" format "\r\n",                   \
-+                                           "[%s:%d] %45.45s:" format "\n",                   \
-                                            __FILE__, __LINE__, __func__, ## args);              \
-                         ply_logger_flush (logger);                                             \
-                         errno = _old_errno;                                                    \
-diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c
-index 5c8510c..89e37e9 100644
---- a/src/libply/ply-utils.c
-+++ b/src/libply/ply-utils.c
-@@ -78,6 +78,8 @@
- static int errno_stack[PLY_ERRNO_STACK_SIZE];
- static int errno_stack_position = 0;
- 
-+static int overridden_device_scale = 0;
-+
- bool
- ply_open_unidirectional_pipe (int *sender_fd,
-                               int *receiver_fd)
-@@ -421,6 +423,29 @@ ply_fd_may_block (int fd)
-         return (flags & O_NONBLOCK) != 0;
- }
- 
-+bool
-+ply_set_fd_as_blocking (int fd)
-+{
-+        int flags;
-+        int ret = 0;
-+
-+        assert (fd >= 0);
-+
-+        flags = fcntl (fd, F_GETFL);
-+
-+        if (flags == -1) {
-+                return false;
-+        }
-+
-+        if (flags & O_NONBLOCK) {
-+                flags &= ~O_NONBLOCK;
-+
-+                ret = fcntl (fd, F_SETFL, flags);
-+        }
-+
-+        return ret == 0;
-+}
-+
- char **
- ply_copy_string_array (const char *const *array)
- {
-@@ -936,4 +961,58 @@ out:
- 
-         return (pid_t) ppid;
- }
-+
-+void
-+ply_set_device_scale (int device_scale)
-+{
-+    overridden_device_scale = device_scale;
-+    ply_trace ("Device scale is set to %d", device_scale);
-+}
-+
-+/* The minimum resolution at which we turn on a device-scale of 2 */
-+#define HIDPI_LIMIT 192
-+#define HIDPI_MIN_HEIGHT 1200
-+
-+int
-+ply_get_device_scale (uint32_t width,
-+                      uint32_t height,
-+                      uint32_t width_mm,
-+                      uint32_t height_mm)
-+{
-+        int device_scale;
-+        double dpi_x, dpi_y;
-+        const char *force_device_scale;
-+
-+        device_scale = 1;
-+
-+        if ((force_device_scale = getenv ("PLYMOUTH_FORCE_SCALE")))
-+                return strtoul (force_device_scale, NULL, 0);
-+
-+        if (overridden_device_scale != 0)
-+                return overridden_device_scale;
-+
-+        if (height < HIDPI_MIN_HEIGHT)
-+                return 1;
-+
-+        /* Somebody encoded the aspect ratio (16/9 or 16/10)
-+         * instead of the physical size */
-+        if ((width_mm == 160 && height_mm == 90) ||
-+            (width_mm == 160 && height_mm == 100) ||
-+            (width_mm == 16 && height_mm == 9) ||
-+            (width_mm == 16 && height_mm == 10))
-+                return 1;
-+
-+        if (width_mm > 0 && height_mm > 0) {
-+                dpi_x = (double)width / (width_mm / 25.4);
-+                dpi_y = (double)height / (height_mm / 25.4);
-+                /* We don't completely trust these values so both
-+                   must be high, and never pick higher ratio than
-+                   2 automatically */
-+                if (dpi_x > HIDPI_LIMIT && dpi_y > HIDPI_LIMIT)
-+                        device_scale = 2;
-+        }
-+
-+        return device_scale;
-+}
-+
- /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
-diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h
-index b9a28d0..c46603e 100644
---- a/src/libply/ply-utils.h
-+++ b/src/libply/ply-utils.h
-@@ -82,6 +82,7 @@ bool ply_read_uint32 (int       fd,
- bool ply_fd_has_data (int fd);
- bool ply_fd_can_take_data (int fd);
- bool ply_fd_may_block (int fd);
-+bool ply_set_fd_as_blocking (int fd);
- char **ply_copy_string_array (const char *const *array);
- void ply_free_string_array (char **array);
- bool ply_string_has_prefix (const char *string,
-@@ -120,6 +121,13 @@ int ply_utf8_string_get_length (const char *string,
- char *ply_get_process_command_line (pid_t pid);
- pid_t ply_get_process_parent_pid (pid_t pid);
- 
-+void ply_set_device_scale (int device_scale);
-+
-+int ply_get_device_scale (uint32_t width,
-+                          uint32_t height,
-+                          uint32_t width_mm,
-+                          uint32_t height_mm);
-+
- #endif
- 
- #endif /* PLY_UTILS_H */
-diff --git a/src/main.c b/src/main.c
-index da6e95d..0864e5e 100644
---- a/src/main.c
-+++ b/src/main.c
-@@ -107,6 +107,7 @@ typedef struct
- 
-         double                  start_time;
-         double                  splash_delay;
-+        double                  device_timeout;
- 
-         char                    kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE];
-         uint32_t                kernel_command_line_is_set : 1;
-@@ -136,8 +137,8 @@ static ply_boot_splash_t *load_theme (state_t    *state,
- static ply_boot_splash_t *show_theme (state_t    *state,
-                                       const char *theme_path);
- 
--static void attach_splash_to_seats (state_t           *state,
--                                    ply_boot_splash_t *splash);
-+static void attach_splash_to_devices (state_t           *state,
-+                                      ply_boot_splash_t *splash);
- static bool attach_to_running_session (state_t *state);
- static void detach_from_running_session (state_t *state);
- static void on_escape_pressed (state_t *state);
-@@ -293,8 +294,8 @@ load_settings (state_t    *state,
-                char      **theme_path)
- {
-         ply_key_file_t *key_file = NULL;
--        const char *delay_string;
-         bool settings_loaded = false;
-+        const char *scale_string;
-         const char *splash_string;
- 
-         ply_trace ("Trying to load %s", path);
-@@ -313,6 +314,8 @@ load_settings (state_t    *state,
-                   splash_string, splash_string);
- 
-         if (isnan (state->splash_delay)) {
-+                const char *delay_string;
-+
-                 delay_string = ply_key_file_get_value (key_file, "Daemon", "ShowDelay");
- 
-                 if (delay_string != NULL) {
-@@ -321,6 +324,23 @@ load_settings (state_t    *state,
-                 }
-         }
- 
-+        if (isnan (state->device_timeout)) {
-+                const char *timeout_string;
-+
-+                timeout_string = ply_key_file_get_value (key_file, "Daemon", "DeviceTimeout");
-+
-+                if (timeout_string != NULL) {
-+                        state->device_timeout = atof (timeout_string);
-+                        ply_trace ("Device timeout is set to %lf", state->device_timeout);
-+                }
-+        }
-+
-+        scale_string = ply_key_file_get_value (key_file, "Daemon", "DeviceScale");
-+
-+        if (scale_string != NULL) {
-+                ply_set_device_scale (strtoul (scale_string, NULL, 0));
-+        }
-+
-         settings_loaded = true;
- out:
-         ply_key_file_free (key_file);
-@@ -345,6 +365,8 @@ show_detailed_splash (state_t *state)
-         }
- 
-         state->boot_splash = splash;
-+
-+        show_messages (state);
-         update_display (state);
- }
- 
-@@ -419,6 +441,17 @@ find_override_splash (state_t *state)
- }
- 
- static void
-+find_force_scale (state_t *state)
-+{
-+        const char *scale_string;
-+
-+        scale_string = command_line_get_string_after_prefix (state->kernel_command_line, "plymouth.force-scale=");
-+
-+        if (scale_string != NULL)
-+                ply_set_device_scale (strtoul (scale_string, NULL, 0));
-+}
-+
-+static void
- find_system_default_splash (state_t *state)
- {
-         if (state->system_default_splash_path != NULL)
-@@ -492,6 +525,7 @@ show_default_splash (state_t *state)
-                 return;
-         }
- 
-+        show_messages (state);
-         update_display (state);
- }
- 
-@@ -520,14 +554,14 @@ on_ask_for_password (state_t       *state,
-                  * arrive shortly so just sit tight
-                  */
-                 if (state->is_shown) {
--                        bool has_open_seats;
-+                        bool has_displays;
- 
-                         cancel_pending_delayed_show (state);
- 
--                        has_open_seats = ply_device_manager_has_open_seats (state->device_manager);
-+                        has_displays = ply_device_manager_has_displays (state->device_manager);
- 
--                        if (has_open_seats) {
--                                ply_trace ("seats open now, showing splash immediately");
-+                        if (has_displays) {
-+                                ply_trace ("displays available now, showing splash immediately");
-                                 show_splash (state);
-                         } else {
-                                 ply_trace ("splash still coming up, waiting a bit");
-@@ -891,7 +925,7 @@ plymouth_should_show_default_splash (state_t *state)
- static void
- on_show_splash (state_t *state)
- {
--        bool has_open_seats;
-+        bool has_displays;
- 
-         if (state->is_shown) {
-                 ply_trace ("show splash called while already shown");
-@@ -910,49 +944,20 @@ on_show_splash (state_t *state)
-         }
- 
-         state->is_shown = true;
--        has_open_seats = ply_device_manager_has_open_seats (state->device_manager);
-+        has_displays = ply_device_manager_has_displays (state->device_manager);
- 
--        if (!state->is_attached && state->should_be_attached && has_open_seats)
-+        if (!state->is_attached && state->should_be_attached && has_displays)
-                 attach_to_running_session (state);
- 
--        if (has_open_seats) {
--                ply_trace ("at least one seat already open, so loading splash");
-+        if (has_displays) {
-+                ply_trace ("at least one display already available, so loading splash");
-                 show_splash (state);
-         } else {
--                ply_trace ("no seats available to show splash on, waiting...");
-+                ply_trace ("no displays available to show splash on, waiting...");
-         }
- }
- 
- static void
--on_seat_removed (state_t    *state,
--                 ply_seat_t *seat)
--{
--        ply_keyboard_t *keyboard;
--
--        keyboard = ply_seat_get_keyboard (seat);
--
--        ply_trace ("no longer listening for keystrokes");
--        ply_keyboard_remove_input_handler (keyboard,
--                                           (ply_keyboard_input_handler_t)
--                                           on_keyboard_input);
--        ply_trace ("no longer listening for escape");
--        ply_keyboard_remove_escape_handler (keyboard,
--                                            (ply_keyboard_escape_handler_t)
--                                            on_escape_pressed);
--        ply_trace ("no longer listening for backspace");
--        ply_keyboard_remove_backspace_handler (keyboard,
--                                               (ply_keyboard_backspace_handler_t)
--                                               on_backspace);
--        ply_trace ("no longer listening for enter");
--        ply_keyboard_remove_enter_handler (keyboard,
--                                           (ply_keyboard_enter_handler_t)
--                                           on_enter);
--
--        if (state->boot_splash != NULL)
--                ply_boot_splash_detach_from_seat (state->boot_splash, seat);
--}
--
--static void
- show_splash (state_t *state)
- {
-         if (state->boot_splash != NULL)
-@@ -991,23 +996,9 @@ show_splash (state_t *state)
- }
- 
- static void
--on_seat_added (state_t    *state,
--               ply_seat_t *seat)
-+on_keyboard_added (state_t        *state,
-+                   ply_keyboard_t *keyboard)
- {
--        ply_keyboard_t *keyboard;
--
--        if (state->is_shown && !state->is_inactive) {
--                if (state->boot_splash == NULL) {
--                        ply_trace ("seat added before splash loaded, so loading splash now");
--                        show_splash (state);
--                } else {
--                        ply_trace ("seat added after splash loaded, so attaching to splash");
--                        ply_boot_splash_attach_to_seat (state->boot_splash, seat);
--                }
--        }
--
--        keyboard = ply_seat_get_keyboard (seat);
--
-         ply_trace ("listening for keystrokes");
-         ply_keyboard_add_input_handler (keyboard,
-                                         (ply_keyboard_input_handler_t)
-@@ -1024,6 +1015,90 @@ on_seat_added (state_t    *state,
-         ply_keyboard_add_enter_handler (keyboard,
-                                         (ply_keyboard_enter_handler_t)
-                                         on_enter, state);
-+
-+        if (state->boot_splash != NULL) {
-+                ply_trace ("keyboard set after splash loaded, so attaching to splash");
-+                ply_boot_splash_set_keyboard (state->boot_splash, keyboard);
-+        }
-+}
-+
-+static void
-+on_keyboard_removed (state_t        *state,
-+                     ply_keyboard_t *keyboard)
-+{
-+    ply_trace ("no longer listening for keystrokes");
-+    ply_keyboard_remove_input_handler (keyboard,
-+                                       (ply_keyboard_input_handler_t)
-+                                       on_keyboard_input);
-+    ply_trace ("no longer listening for escape");
-+    ply_keyboard_remove_escape_handler (keyboard,
-+                                        (ply_keyboard_escape_handler_t)
-+                                        on_escape_pressed);
-+    ply_trace ("no longer listening for backspace");
-+    ply_keyboard_remove_backspace_handler (keyboard,
-+                                           (ply_keyboard_backspace_handler_t)
-+                                           on_backspace);
-+    ply_trace ("no longer listening for enter");
-+    ply_keyboard_remove_enter_handler (keyboard,
-+                                       (ply_keyboard_enter_handler_t)
-+                                       on_enter);
-+
-+    if (state->boot_splash != NULL)
-+            ply_boot_splash_unset_keyboard (state->boot_splash);
-+}
-+
-+static void
-+on_pixel_display_added (state_t             *state,
-+                        ply_pixel_display_t *display)
-+{
-+        if (state->is_shown) {
-+                if (state->boot_splash == NULL) {
-+                        ply_trace ("pixel display added before splash loaded, so loading splash now");
-+                        show_splash (state);
-+                } else {
-+                        ply_trace ("pixel display added after splash loaded, so attaching to splash");
-+                        ply_boot_splash_add_pixel_display (state->boot_splash, display);
-+
-+                        update_display (state);
-+                }
-+        }
-+}
-+
-+static void
-+on_pixel_display_removed (state_t             *state,
-+                          ply_pixel_display_t *display)
-+{
-+        if (state->boot_splash == NULL)
-+                return;
-+
-+        ply_boot_splash_remove_pixel_display (state->boot_splash, display);
-+}
-+
-+static void
-+on_text_display_added (state_t            *state,
-+                       ply_text_display_t *display)
-+{
-+        if (state->is_shown) {
-+                if (state->boot_splash == NULL) {
-+                        ply_trace ("text display added before splash loaded, so loading splash now");
-+                        show_splash (state);
-+                } else {
-+                        ply_trace ("text display added after splash loaded, so attaching to splash");
-+                        ply_boot_splash_add_text_display (state->boot_splash, display);
-+
-+                        update_display (state);
-+                }
-+        }
-+}
-+
-+static void
-+on_text_display_removed (state_t            *state,
-+                         ply_text_display_t *display)
-+{
-+        if (state->boot_splash == NULL)
-+                return;
-+
-+        ply_boot_splash_remove_text_display (state->boot_splash, display);
- }
- 
- static void
-@@ -1033,12 +1108,25 @@ load_devices (state_t                   *state,
-         state->device_manager = ply_device_manager_new (state->default_tty, flags);
-         state->local_console_terminal = ply_device_manager_get_default_terminal (state->device_manager);
- 
--        ply_device_manager_watch_seats (state->device_manager,
--                                        (ply_seat_added_handler_t)
--                                        on_seat_added,
--                                        (ply_seat_removed_handler_t)
--                                        on_seat_removed,
--                                        state);
-+        ply_device_manager_watch_devices (state->device_manager,
-+                                          state->device_timeout,
-+                                          (ply_keyboard_added_handler_t)
-+                                          on_keyboard_added,
-+                                          (ply_keyboard_removed_handler_t)
-+                                          on_keyboard_removed,
-+                                          (ply_pixel_display_added_handler_t)
-+                                          on_pixel_display_added,
-+                                          (ply_pixel_display_removed_handler_t)
-+                                          on_pixel_display_removed,
-+                                          (ply_text_display_added_handler_t)
-+                                          on_text_display_added,
-+                                          (ply_text_display_removed_handler_t)
-+                                          on_text_display_removed,
-+                                          state);
-+
-+        if (ply_device_manager_has_serial_consoles (state->device_manager)) {
-+                state->should_force_details = true;
-+        }
- }
- 
- static void
-@@ -1507,22 +1595,52 @@ on_enter (state_t    *state,
- }
- 
- static void
--attach_splash_to_seats (state_t           *state,
--                        ply_boot_splash_t *splash)
-+attach_splash_to_devices (state_t           *state,
-+                          ply_boot_splash_t *splash)
- {
--        ply_list_t *seats;
-+        ply_list_t *keyboards;
-+        ply_list_t *pixel_displays;
-+        ply_list_t *text_displays;
-         ply_list_node_t *node;
- 
--        seats = ply_device_manager_get_seats (state->device_manager);
--        node = ply_list_get_first_node (seats);
-+        keyboards = ply_device_manager_get_keyboards (state->device_manager);
-+        node = ply_list_get_first_node (keyboards);
-+        while (node != NULL) {
-+                ply_keyboard_t *keyboard;
-+                ply_list_node_t *next_node;
-+
-+                keyboard = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (keyboards, node);
-+
-+                ply_boot_splash_set_keyboard (splash, keyboard);
-+
-+                node = next_node;
-+        }
-+
-+        pixel_displays = ply_device_manager_get_pixel_displays (state->device_manager);
-+        node = ply_list_get_first_node (pixel_displays);
-         while (node != NULL) {
--                ply_seat_t *seat;
-+                ply_pixel_display_t *pixel_display;
-                 ply_list_node_t *next_node;
- 
--                seat = ply_list_node_get_data (node);
--                next_node = ply_list_get_next_node (seats, node);
-+                pixel_display = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (pixel_displays, node);
- 
--                ply_boot_splash_attach_to_seat (splash, seat);
-+                ply_boot_splash_add_pixel_display (splash, pixel_display);
-+
-+                node = next_node;
-+        }
-+
-+        text_displays = ply_device_manager_get_text_displays (state->device_manager);
-+        node = ply_list_get_first_node (text_displays);
-+        while (node != NULL) {
-+                ply_text_display_t *text_display;
-+                ply_list_node_t *next_node;
-+
-+                text_display = ply_list_node_get_data (node);
-+                next_node = ply_list_get_next_node (text_displays, node);
-+
-+                ply_boot_splash_add_text_display (splash, text_display);
- 
-                 node = next_node;
-         }
-@@ -1623,7 +1741,7 @@ show_theme (state_t    *state,
-         if (splash == NULL)
-                 return NULL;
- 
--        attach_splash_to_seats (state, splash);
-+        attach_splash_to_devices (state, splash);
-         ply_device_manager_activate_renderers (state->device_manager);
- 
-         splash_mode = get_splash_mode_from_mode (state->mode);
-@@ -1641,7 +1759,6 @@ show_theme (state_t    *state,
- #endif
- 
-         ply_device_manager_activate_keyboards (state->device_manager);
--        show_messages (state);
- 
-         return splash;
- }
-@@ -1978,12 +2095,15 @@ on_crash (int signum)
- {
-         struct termios term_attributes;
-         int fd;
-+        static const char *show_cursor_sequence = "\033[?25h";
- 
-         fd = open ("/dev/tty1", O_RDWR | O_NOCTTY);
-         if (fd < 0) fd = open ("/dev/hvc0", O_RDWR | O_NOCTTY);
- 
-         ioctl (fd, KDSETMODE, KD_TEXT);
- 
-+        write (fd, show_cursor_sequence, sizeof (show_cursor_sequence) - 1);
-+
-         tcgetattr (fd, &term_attributes);
- 
-         term_attributes.c_iflag |= BRKINT | IGNPAR | ICRNL | IXON;
-@@ -2191,6 +2311,7 @@ main (int    argc,
- 
-         state.progress = ply_progress_new ();
-         state.splash_delay = NAN;
-+        state.device_timeout = NAN;
- 
-         ply_progress_load_cache (state.progress,
-                                  get_cache_file_for_mode (state.mode));
-@@ -2223,6 +2344,8 @@ main (int    argc,
-                 state.splash_delay = NAN;
-         }
- 
-+        find_force_scale (&state);
-+
-         load_devices (&state, device_manager_flags);
- 
-         ply_trace ("entering event loop");
-diff --git a/src/plugins/controls/label/plugin.c b/src/plugins/controls/label/plugin.c
-index 5edce3b..acba52b 100644
---- a/src/plugins/controls/label/plugin.c
-+++ b/src/plugins/controls/label/plugin.c
-@@ -113,15 +113,18 @@ get_cairo_context_for_pixel_buffer (ply_label_plugin_control_t *label,
-         cairo_t *cairo_context;
-         unsigned char *data;
-         ply_rectangle_t size;
-+        uint32_t scale;
- 
-         data = (unsigned char *) ply_pixel_buffer_get_argb32_data (pixel_buffer);
-         ply_pixel_buffer_get_size (pixel_buffer, &size);
-+        scale = ply_pixel_buffer_get_device_scale (pixel_buffer);
- 
-         cairo_surface = cairo_image_surface_create_for_data (data,
-                                                              CAIRO_FORMAT_ARGB32,
--                                                             size.width,
--                                                             size.height,
--                                                             size.width * 4);
-+                                                             size.width * scale,
-+                                                             size.height * scale,
-+                                                             size.width * scale * 4);
-+        cairo_surface_set_device_scale (cairo_surface, scale, scale);
-         cairo_context = cairo_create (cairo_surface);
-         cairo_surface_destroy (cairo_surface);
- 
-diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am
-index 747f202..271b17f 100644
---- a/src/plugins/renderers/drm/Makefile.am
-+++ b/src/plugins/renderers/drm/Makefile.am
-@@ -16,12 +16,7 @@ drm_la_LDFLAGS = -module -avoid-version -export-dynamic
- drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS)                                  \
-                          ../../../libply/libply.la                            \
-                          ../../../libply-splash-core/libply-splash-core.la
--drm_la_SOURCES = $(srcdir)/plugin.c                                           \
--                 $(srcdir)/ply-renderer-driver.h
--drm_la_SOURCES += $(srcdir)/ply-renderer-generic-driver.h                     \
--                  $(srcdir)/ply-renderer-generic-driver.c
--
--
-+drm_la_SOURCES = $(srcdir)/plugin.c
- 
- endif
- 
-diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c
-index 45aab7d..b93e8e4 100644
---- a/src/plugins/renderers/drm/plugin.c
-+++ b/src/plugins/renderers/drm/plugin.c
-@@ -54,12 +54,11 @@
- #include "ply-hashtable.h"
- #include "ply-rectangle.h"
- #include "ply-region.h"
-+#include "ply-utils.h"
- #include "ply-terminal.h"
- 
- #include "ply-renderer.h"
- #include "ply-renderer-plugin.h"
--#include "ply-renderer-driver.h"
--#include "ply-renderer-generic-driver.h"
- 
- #define BYTES_PER_PIXEL (4)
- 
-@@ -92,15 +91,27 @@ struct _ply_renderer_input_source
-         void                               *user_data;
- };
- 
-+typedef struct
-+{
-+        uint32_t id;
-+
-+        uint32_t handle;
-+        uint32_t width;
-+        uint32_t height;
-+        uint32_t row_stride;
-+
-+        void    *map_address;
-+        uint32_t map_size;
-+        int      map_count;
-+
-+        uint32_t added_fb : 1;
-+} ply_renderer_buffer_t;
-+
- struct _ply_renderer_backend
- {
-         ply_event_loop_t                *loop;
-         ply_terminal_t                  *terminal;
- 
--        ply_renderer_driver_interface_t *driver_interface;
--        ply_renderer_driver_t           *driver;
--        uint32_t                         driver_supports_mapping_console;
--
-         int                              device_fd;
-         char                            *device_name;
-         drmModeRes                      *resources;
-@@ -109,11 +120,14 @@ struct _ply_renderer_backend
-         ply_list_t                      *heads;
-         ply_hashtable_t                 *heads_by_connector_id;
- 
-+        ply_hashtable_t                 *output_buffers;
-+
-         int32_t                          dither_red;
-         int32_t                          dither_green;
-         int32_t                          dither_blue;
- 
-         uint32_t                         is_active : 1;
-+        uint32_t        requires_explicit_flushing : 1;
- };
- 
- ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void);
-@@ -127,6 +141,233 @@ static void flush_head (ply_renderer_backend_t *backend,
-                         ply_renderer_head_t    *head);
- 
- static bool
-+ply_renderer_buffer_map (ply_renderer_backend_t *backend,
-+                         ply_renderer_buffer_t  *buffer)
-+{
-+        struct drm_mode_map_dumb map_dumb_buffer_request;
-+        void *map_address;
-+
-+        if (buffer->map_address != MAP_FAILED) {
-+                buffer->map_count++;
-+                return true;
-+        }
-+
-+        memset (&map_dumb_buffer_request, 0, sizeof(struct drm_mode_map_dumb));
-+        map_dumb_buffer_request.handle = buffer->handle;
-+        if (drmIoctl (backend->device_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb_buffer_request) < 0) {
-+                ply_trace ("Could not map GEM object %u: %m", buffer->handle);
-+                return false;
-+        }
-+
-+        map_address = mmap (0, buffer->map_size,
-+                            PROT_READ | PROT_WRITE, MAP_SHARED,
-+                            backend->device_fd, map_dumb_buffer_request.offset);
-+
-+        if (map_address == MAP_FAILED)
-+                return false;
-+
-+        buffer->map_address = map_address;
-+        buffer->map_count++;
-+
-+        return true;
-+}
-+
-+static void
-+ply_renderer_buffer_unmap (ply_renderer_backend_t *backend,
-+                           ply_renderer_buffer_t  *buffer)
-+{
-+        buffer->map_count--;
-+
-+        assert (buffer->map_count >= 0);
-+}
-+
-+static ply_renderer_buffer_t *
-+ply_renderer_buffer_new (ply_renderer_backend_t *backend,
-+                         uint32_t                width,
-+                         uint32_t                height)
-+{
-+        ply_renderer_buffer_t *buffer;
-+        struct drm_mode_create_dumb create_dumb_buffer_request;
-+
-+        buffer = calloc (1, sizeof(ply_renderer_buffer_t));
-+        buffer->width = width;
-+        buffer->height = height;
-+        buffer->map_address = MAP_FAILED;
-+
-+        memset (&create_dumb_buffer_request, 0, sizeof(struct drm_mode_create_dumb));
-+
-+        create_dumb_buffer_request.width = width;
-+        create_dumb_buffer_request.height = height;
-+        create_dumb_buffer_request.bpp = 32;
-+        create_dumb_buffer_request.flags = 0;
-+
-+        if (drmIoctl (backend->device_fd,
-+                      DRM_IOCTL_MODE_CREATE_DUMB,
-+                      &create_dumb_buffer_request) < 0) {
-+                free (buffer);
-+                ply_trace ("Could not allocate GEM object for frame buffer: %m");
-+                return NULL;
-+        }
-+
-+        buffer->handle = create_dumb_buffer_request.handle;
-+        buffer->row_stride = create_dumb_buffer_request.pitch;
-+        buffer->map_size = create_dumb_buffer_request.size;
-+
-+        ply_trace ("returning %ux%u buffer with stride %u",
-+                   width, height, buffer->row_stride);
-+
-+        return buffer;
-+}
-+
-+static void
-+ply_renderer_buffer_free (ply_renderer_backend_t *backend,
-+                          ply_renderer_buffer_t  *buffer)
-+{
-+        struct drm_mode_destroy_dumb destroy_dumb_buffer_request;
-+
-+        if (buffer->added_fb)
-+                drmModeRmFB (backend->device_fd, buffer->id);
-+
-+        if (buffer->map_address != MAP_FAILED) {
-+                munmap (buffer->map_address, buffer->map_size);
-+                buffer->map_address = MAP_FAILED;
-+        }
-+
-+        memset (&destroy_dumb_buffer_request, 0, sizeof(struct drm_mode_destroy_dumb));
-+        destroy_dumb_buffer_request.handle = buffer->handle;
-+
-+        if (drmIoctl (backend->device_fd,
-+                      DRM_IOCTL_MODE_DESTROY_DUMB,
-+                      &destroy_dumb_buffer_request) < 0)
-+                ply_trace ("Could not deallocate GEM object %u: %m", buffer->handle);
-+
-+        free (buffer);
-+}
-+
-+static ply_renderer_buffer_t *
-+get_buffer_from_id (ply_renderer_backend_t *backend,
-+                    uint32_t                id)
-+{
-+        static ply_renderer_buffer_t *buffer;
-+
-+        buffer = ply_hashtable_lookup (backend->output_buffers, (void *) (uintptr_t) id);
-+
-+        return buffer;
-+}
-+
-+static uint32_t
-+create_output_buffer (ply_renderer_backend_t *backend,
-+                      unsigned long           width,
-+                      unsigned long           height,
-+                      unsigned long          *row_stride)
-+{
-+        ply_renderer_buffer_t *buffer;
-+
-+        buffer = ply_renderer_buffer_new (backend, width, height);
-+
-+        if (buffer == NULL) {
-+                ply_trace ("Could not allocate GEM object for frame buffer: %m");
-+                return 0;
-+        }
-+
-+        if (drmModeAddFB (backend->device_fd, width, height,
-+                          24, 32, buffer->row_stride, buffer->handle,
-+                          &buffer->id) != 0) {
-+                ply_trace ("Could not set up GEM object as frame buffer: %m");
-+                ply_renderer_buffer_free (backend, buffer);
-+                return 0;
-+        }
-+
-+        *row_stride = buffer->row_stride;
-+
-+        buffer->added_fb = true;
-+        ply_hashtable_insert (backend->output_buffers,
-+                              (void *) (uintptr_t) buffer->id,
-+                              buffer);
-+
-+        return buffer->id;
-+}
-+
-+static bool
-+map_buffer (ply_renderer_backend_t *backend,
-+            uint32_t                buffer_id)
-+{
-+        ply_renderer_buffer_t *buffer;
-+
-+        buffer = get_buffer_from_id (backend, buffer_id);
-+
-+        assert (buffer != NULL);
-+
-+        return ply_renderer_buffer_map (backend, buffer);
-+}
-+
-+static void
-+unmap_buffer (ply_renderer_backend_t *backend,
-+              uint32_t                buffer_id)
-+{
-+        ply_renderer_buffer_t *buffer;
-+
-+        buffer = get_buffer_from_id (backend, buffer_id);
-+
-+        assert (buffer != NULL);
-+
-+        ply_renderer_buffer_unmap (backend, buffer);
-+}
-+
-+static char *
-+begin_flush (ply_renderer_backend_t *backend,
-+             uint32_t                buffer_id)
-+{
-+        ply_renderer_buffer_t *buffer;
-+
-+        buffer = get_buffer_from_id (backend, buffer_id);
-+
-+        assert (buffer != NULL);
-+
-+        return buffer->map_address;
-+}
-+
-+static void
-+end_flush (ply_renderer_backend_t *backend,
-+           uint32_t                buffer_id)
-+{
-+        ply_renderer_buffer_t *buffer;
-+
-+        buffer = get_buffer_from_id (backend, buffer_id);
-+
-+        assert (buffer != NULL);
-+
-+        if (backend->requires_explicit_flushing) {
-+                struct drm_clip_rect flush_area;
-+                int ret;
-+
-+                flush_area.x1 = 0;
-+                flush_area.y1 = 0;
-+                flush_area.x2 = buffer->width;
-+                flush_area.y2 = buffer->height;
-+
-+                ret = drmModeDirtyFB (backend->device_fd, buffer->id, &flush_area, 1);
-+
-+                if (ret == -ENOSYS)
-+                        backend->requires_explicit_flushing = false;
-+        }
-+}
-+
-+static void
-+destroy_output_buffer (ply_renderer_backend_t *backend,
-+                       uint32_t                buffer_id)
-+{
-+        ply_renderer_buffer_t *buffer;
-+
-+        buffer = ply_hashtable_remove (backend->output_buffers,
-+                                       (void *) (uintptr_t) buffer_id);
-+
-+        assert (buffer != NULL);
-+
-+        ply_renderer_buffer_free (backend, buffer);
-+}
-+
-+static bool
- ply_renderer_head_add_connector (ply_renderer_head_t *head,
-                                  drmModeConnector    *connector,
-                                  int                  connector_mode_index)
-@@ -185,6 +426,11 @@ ply_renderer_head_new (ply_renderer_backend_t *backend,
-         assert (ply_array_get_size (head->connector_ids) > 0);
- 
-         head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height);
-+        ply_pixel_buffer_set_device_scale (head->pixel_buffer,
-+                                           ply_get_device_scale (head->area.width,
-+                                                                 head->area.height,
-+                                                                 connector->mmWidth,
-+                                                                 connector->mmHeight));
- 
-         ply_trace ("Creating %ldx%ld renderer head", head->area.width, head->area.height);
-         ply_pixel_buffer_fill_with_color (head->pixel_buffer, NULL,
-@@ -241,25 +487,21 @@ ply_renderer_head_map (ply_renderer_backend_t *backend,
- 
-         assert (backend != NULL);
-         assert (backend->device_fd >= 0);
--        assert (backend->driver_interface != NULL);
--        assert (backend->driver != NULL);
-+        assert (backend != NULL);
- 
-         assert (head != NULL);
- 
-         ply_trace ("Creating buffer for %ldx%ld renderer head", head->area.width, head->area.height);
--        head->scan_out_buffer_id =
--                backend->driver_interface->create_buffer (backend->driver,
--                                                          head->area.width, head->area.height,
--                                                          &head->row_stride);
-+        head->scan_out_buffer_id = create_output_buffer (backend,
-+                                                         head->area.width, head->area.height,
-+                                                         &head->row_stride);
- 
-         if (head->scan_out_buffer_id == 0)
-                 return false;
- 
-         ply_trace ("Mapping buffer for %ldx%ld renderer head", head->area.width, head->area.height);
--        if (!backend->driver_interface->map_buffer (backend->driver,
--                                                    head->scan_out_buffer_id)) {
--                backend->driver_interface->destroy_buffer (backend->driver,
--                                                           head->scan_out_buffer_id);
-+        if (!map_buffer (backend, head->scan_out_buffer_id)) {
-+                destroy_output_buffer (backend, head->scan_out_buffer_id);
-                 head->scan_out_buffer_id = 0;
-                 return false;
-         }
-@@ -271,8 +513,7 @@ ply_renderer_head_map (ply_renderer_backend_t *backend,
- 
-         scan_out_set = reset_scan_out_buffer_if_needed (backend, head);
-         if (!scan_out_set && backend->is_active) {
--                backend->driver_interface->destroy_buffer (backend->driver,
--                                                           head->scan_out_buffer_id);
-+                destroy_output_buffer (backend, head->scan_out_buffer_id);
-                 head->scan_out_buffer_id = 0;
-                 return false;
-         }
-@@ -285,11 +526,9 @@ ply_renderer_head_unmap (ply_renderer_backend_t *backend,
-                          ply_renderer_head_t    *head)
- {
-         ply_trace ("unmapping %ldx%ld renderer head", head->area.width, head->area.height);
--        backend->driver_interface->unmap_buffer (backend->driver,
--                                                 head->scan_out_buffer_id);
-+        unmap_buffer (backend, head->scan_out_buffer_id);
- 
--        backend->driver_interface->destroy_buffer (backend->driver,
--                                                   head->scan_out_buffer_id);
-+        destroy_output_buffer (backend, head->scan_out_buffer_id);
-         head->scan_out_buffer_id = 0;
- }
- 
-@@ -375,10 +614,19 @@ create_backend (const char     *device_name,
-         backend->heads = ply_list_new ();
-         backend->input_source.key_buffer = ply_buffer_new ();
-         backend->terminal = terminal;
-+        backend->requires_explicit_flushing = true;
-+        backend->output_buffers = ply_hashtable_new (ply_hashtable_direct_hash,
-+                                                     ply_hashtable_direct_compare);
- 
-         return backend;
- }
- 
-+static const char *
-+get_device_name (ply_renderer_backend_t *backend)
-+{
-+        return backend->device_name;
-+}
-+
- static void
- destroy_backend (ply_renderer_backend_t *backend)
- {
-@@ -386,6 +634,9 @@ destroy_backend (ply_renderer_backend_t *backend)
-         free_heads (backend);
- 
-         free (backend->device_name);
-+        ply_hashtable_free (backend->output_buffers);
-+
-+        drmModeFreeResources (backend->resources);
- 
-         free (backend);
- }
-@@ -455,44 +706,29 @@ load_driver (ply_renderer_backend_t *backend)
-                 return false;
-         }
- 
--        backend->driver_interface = ply_renderer_generic_driver_get_interface (device_fd);
--        backend->driver_supports_mapping_console = false;
--
--        if (backend->driver_interface == NULL) {
--                close (device_fd);
--                return false;
--        }
--
--        backend->driver = backend->driver_interface->create_driver (device_fd);
--
--        if (backend->driver == NULL) {
--                close (device_fd);
--                return false;
--        }
--
-         backend->device_fd = device_fd;
- 
-+        drmDropMaster (device_fd);
-+
-         return true;
- }
- 
- static void
--unload_driver (ply_renderer_backend_t *backend)
-+unload_backend (ply_renderer_backend_t *backend)
- {
--        if (backend->driver == NULL)
-+        if (backend == NULL)
-                 return;
- 
--        ply_trace ("unloading driver");
--        assert (backend->driver_interface != NULL);
--
--        backend->driver_interface->destroy_driver (backend->driver);
--        backend->driver = NULL;
--
--        backend->driver_interface = NULL;
-+        ply_trace ("unloading backend");
- 
-         if (backend->device_fd >= 0) {
-                 drmClose (backend->device_fd);
-                 backend->device_fd = -1;
-         }
-+
-+        destroy_backend (backend);
-+        backend = NULL;
-+
- }
- 
- static bool
-@@ -540,7 +776,7 @@ close_device (ply_renderer_backend_t *backend)
-                                                                  backend);
-         }
- 
--        unload_driver (backend);
-+        unload_backend (backend);
- }
- 
- static drmModeCrtc *
-@@ -732,34 +968,6 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend)
- 
-         ply_hashtable_free (heads_by_controller_id);
- 
--#ifdef PLY_ENABLE_DEPRECATED_GDM_TRANSITION
--        /* If the driver doesn't support mapping the fb console
--         * then we can't get a smooth crossfade transition to
--         * the display manager unless we use the /dev/fb interface
--         * or the plymouth deactivate interface.
--         *
--         * In multihead configurations, we'd rather have working
--         * multihead, but otherwise bail now.
--         */
--        if (!backend->driver_supports_mapping_console &&
--            ply_list_get_length (backend->heads) == 1) {
--                ply_list_node_t *node;
--                ply_renderer_head_t *head;
--
--                node = ply_list_get_first_node (backend->heads);
--                head = (ply_renderer_head_t *) ply_list_node_get_data (node);
--
--                if (ply_array_get_size (head->connector_ids) == 1) {
--                        ply_trace ("Only one monitor configured, and driver doesn't "
--                                   "support mapping console, so letting frame-buffer "
--                                   "take over");
--
--                        free_heads (backend);
--                        return false;
--                }
--        }
--#endif
--
-         return ply_list_get_length (backend->heads) > 0;
- }
- 
-@@ -774,7 +982,7 @@ has_32bpp_support (ply_renderer_backend_t *backend)
-         min_width = backend->resources->min_width;
-         min_height = backend->resources->min_height;
- 
--        /* Some drivers set min_width/min_height to 0,
-+        /* Some backends set min_width/min_height to 0,
-          * but 0x0 sized buffers don't work.
-          */
-         if (min_width == 0)
-@@ -783,10 +991,7 @@ has_32bpp_support (ply_renderer_backend_t *backend)
-         if (min_height == 0)
-                 min_height = 1;
- 
--        buffer_id = backend->driver_interface->create_buffer (backend->driver,
--                                                              min_width,
--                                                              min_height,
--                                                              &row_stride);
-+        buffer_id = create_output_buffer (backend, min_width, min_height, &row_stride);
- 
-         if (buffer_id == 0) {
-                 ply_trace ("Could not create minimal (%ux%u) 32bpp dummy buffer",
-@@ -795,8 +1000,7 @@ has_32bpp_support (ply_renderer_backend_t *backend)
-                 return false;
-         }
- 
--        backend->driver_interface->destroy_buffer (backend->driver,
--                                                   buffer_id);
-+        destroy_output_buffer (backend, buffer_id);
- 
-         return true;
- }
-@@ -860,93 +1064,10 @@ map_to_device (ply_renderer_backend_t *backend)
-         return head_mapped;
- }
- 
--static bool
--ply_renderer_head_set_scan_out_buffer_to_console (ply_renderer_backend_t *backend,
--                                                  ply_renderer_head_t    *head,
--                                                  bool                    should_set_to_black)
--{
--        unsigned long width;
--        unsigned long height;
--        unsigned long row_stride;
--        uint32_t *shadow_buffer;
--        ply_pixel_buffer_t *pixel_buffer;
--        char *map_address;
--        ply_rectangle_t area;
--
--        if (!backend->driver_interface->fetch_buffer (backend->driver,
--                                                      head->console_buffer_id,
--                                                      &width, &height, &row_stride))
--                return false;
--
--        if (!backend->driver_interface->map_buffer (backend->driver,
--                                                    head->console_buffer_id)) {
--                backend->driver_interface->destroy_buffer (backend->driver,
--                                                           head->console_buffer_id);
--                return false;
--        }
--
--        if (head->area.width != width || head->area.height != height) {
--                /* Force black if the fb console resolution doesn't match our resolution
--                 */
--                area.x = 0;
--                area.y = 0;
--                area.width = width;
--                area.height = height;
--
--                should_set_to_black = true;
--                ply_trace ("Console fb is %ldx%ld and screen contents are %ldx%ld. "
--                           "They aren't the same dimensions; forcing black",
--                           width, height, head->area.width, head->area.height);
--        } else {
--                area = head->area;
--        }
--
--        if (should_set_to_black) {
--                pixel_buffer = ply_pixel_buffer_new (width, height);
--                shadow_buffer = ply_pixel_buffer_get_argb32_data (pixel_buffer);
--        } else {
--                pixel_buffer = NULL;
--                shadow_buffer = ply_pixel_buffer_get_argb32_data (head->pixel_buffer);
--        }
--
--        ply_trace ("Drawing %s to console fb", should_set_to_black ? "black" : "screen contents");
--        map_address =
--                backend->driver_interface->begin_flush (backend->driver,
--                                                        head->console_buffer_id);
--
--        flush_area ((char *) shadow_buffer, area.width * 4,
--                    map_address, row_stride, &area);
--
--        backend->driver_interface->end_flush (backend->driver,
--                                              head->console_buffer_id);
--
--        backend->driver_interface->unmap_buffer (backend->driver,
--                                                 head->console_buffer_id);
--
--        ply_trace ("Setting scan out hardware to console fb");
--        ply_renderer_head_set_scan_out_buffer (backend,
--                                               head, head->console_buffer_id);
--
--        backend->driver_interface->destroy_buffer (backend->driver,
--                                                   head->console_buffer_id);
--
--        if (pixel_buffer != NULL)
--                ply_pixel_buffer_free (pixel_buffer);
--
--        return true;
--}
--
- static void
- unmap_from_device (ply_renderer_backend_t *backend)
- {
-         ply_list_node_t *node;
--        bool should_set_to_black;
--
--        /* We only copy what's on screen back to the fb console
--         * if there's one head (since in multihead set ups the fb console
--         * is cloned).
--         */
--        should_set_to_black = ply_list_get_length (backend->heads) > 1;
- 
-         node = ply_list_get_first_node (backend->heads);
-         while (node != NULL) {
-@@ -956,13 +1077,6 @@ unmap_from_device (ply_renderer_backend_t *backend)
-                 head = (ply_renderer_head_t *) ply_list_node_get_data (node);
-                 next_node = ply_list_get_next_node (backend->heads, node);
- 
--                if (backend->is_active) {
--                        ply_trace ("scanning out %s directly to console",
--                                   should_set_to_black ? "black" : "splash");
--                        ply_renderer_head_set_scan_out_buffer_to_console (backend, head,
--                                                                          should_set_to_black);
--                }
--
-                 ply_renderer_head_unmap (backend, head);
- 
-                 node = next_node;
-@@ -1019,9 +1133,7 @@ flush_head (ply_renderer_backend_t *backend,
-         updated_region = ply_pixel_buffer_get_updated_areas (pixel_buffer);
-         areas_to_flush = ply_region_get_sorted_rectangle_list (updated_region);
- 
--        map_address =
--                backend->driver_interface->begin_flush (backend->driver,
--                                                        head->scan_out_buffer_id);
-+        map_address = begin_flush (backend, head->scan_out_buffer_id);
- 
-         node = ply_list_get_first_node (areas_to_flush);
-         while (node != NULL) {
-@@ -1041,8 +1153,7 @@ flush_head (ply_renderer_backend_t *backend,
-                 node = next_node;
-         }
- 
--        backend->driver_interface->end_flush (backend->driver,
--                                              head->scan_out_buffer_id);
-+        end_flush (backend, head->scan_out_buffer_id);
- 
-         ply_region_clear (updated_region);
- }
-@@ -1180,7 +1291,8 @@ ply_renderer_backend_get_interface (void)
-                 .get_input_source             = get_input_source,
-                 .open_input_source            = open_input_source,
-                 .set_handler_for_input_source = set_handler_for_input_source,
--                .close_input_source           = close_input_source
-+                .close_input_source           = close_input_source,
-+                .get_device_name              = get_device_name
-         };
- 
-         return &plugin_interface;
-diff --git a/src/plugins/renderers/drm/ply-renderer-driver.h b/src/plugins/renderers/drm/ply-renderer-driver.h
-deleted file mode 100644
-index f3febcf..0000000
---- a/src/plugins/renderers/drm/ply-renderer-driver.h
-+++ /dev/null
-@@ -1,66 +0,0 @@
--/* ply-renderer-driver.h
-- *
-- * Copyright (C) 2009 Red Hat, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This program 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 General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-- * 02111-1307, USA.
-- *
-- * Written By: Ray Strode <rstrode@redhat.com>
-- */
--#ifndef PLY_RENDERER_DRIVER_H
--#define PLY_RENDERER_DRIVER_H
--
--#include <stdbool.h>
--#include <stdint.h>
--
--#include "ply-list.h"
--#include "ply-rectangle.h"
--#include "ply-utils.h"
--
--typedef struct _ply_renderer_driver ply_renderer_driver_t;
--
--typedef struct
--{
--        ply_renderer_driver_t * (*create_driver)(int device_fd);
--
--        void (*destroy_driver)(ply_renderer_driver_t *driver);
--
--        uint32_t (*create_buffer)(ply_renderer_driver_t *driver,
--                                  unsigned long          width,
--                                  unsigned long          height,
--                                  unsigned long         *row_stride);
--        bool (*fetch_buffer)(ply_renderer_driver_t *driver,
--                             uint32_t               buffer_id,
--                             unsigned long         *width,
--                             unsigned long         *height,
--                             unsigned long         *row_stride);
--
--        bool (*map_buffer)(ply_renderer_driver_t *driver,
--                           uint32_t               buffer_id);
--
--        void (*unmap_buffer)(ply_renderer_driver_t *driver,
--                             uint32_t               buffer_id);
--
--        char * (*begin_flush)(ply_renderer_driver_t * driver,
--                              uint32_t buffer_id);
--        void (*end_flush)(ply_renderer_driver_t *driver,
--                          uint32_t               buffer_id);
--
--        void (*destroy_buffer)(ply_renderer_driver_t *driver,
--                               uint32_t               buffer_id);
--} ply_renderer_driver_interface_t;
--
--#endif /* PLY_RENDERER_DRIVER_H */
--/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
-diff --git a/src/plugins/renderers/drm/ply-renderer-generic-driver.c b/src/plugins/renderers/drm/ply-renderer-generic-driver.c
-deleted file mode 100644
-index b1be714..0000000
---- a/src/plugins/renderers/drm/ply-renderer-generic-driver.c
-+++ /dev/null
-@@ -1,385 +0,0 @@
--/* ply-renderer-generic-driver.c - interface to generic drm kms api
-- *
-- * Copyright (C) 2012 Red Hat, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This program 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 General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-- * 02111-1307, USA.
-- *
-- * Written by: Dave Airlie
-- * Based on other renderer drivers written by Ray Strode
-- */
--#include "config.h"
--
--#include "ply-renderer-generic-driver.h"
--
--#include <arpa/inet.h>
--#include <assert.h>
--#include <errno.h>
--#include <fcntl.h>
--#include <signal.h>
--#include <string.h>
--#include <stdbool.h>
--#include <stdint.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <sys/ioctl.h>
--#include <sys/mman.h>
--#include <sys/stat.h>
--#include <sys/types.h>
--#include <values.h>
--#include <unistd.h>
--
--#include <drm.h>
--#include <xf86drm.h>
--#include <xf86drmMode.h>
--
--#include "ply-hashtable.h"
--#include "ply-logger.h"
--#include "ply-renderer-driver.h"
--
--typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
--
--struct _ply_renderer_buffer
--{
--        uint32_t id;
--
--        uint32_t handle;
--        uint32_t width;
--        uint32_t height;
--        uint32_t row_stride;
--
--        void    *map_address;
--        uint32_t map_size;
--        int      map_count;
--
--        uint32_t added_fb : 1;
--};
--
--struct _ply_renderer_driver
--{
--        int              device_fd;
--        ply_hashtable_t *buffers;
--
--        uint32_t         requires_explicit_flushing : 1;
--};
--
--static bool
--ply_renderer_buffer_map (ply_renderer_driver_t *driver,
--                         ply_renderer_buffer_t *buffer)
--{
--        struct drm_mode_map_dumb map_dumb_buffer_request;
--        void *map_address;
--
--        if (buffer->map_address != MAP_FAILED) {
--                buffer->map_count++;
--                return true;
--        }
--
--        memset (&map_dumb_buffer_request, 0, sizeof(struct drm_mode_map_dumb));
--        map_dumb_buffer_request.handle = buffer->handle;
--        if (drmIoctl (driver->device_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb_buffer_request) < 0) {
--                ply_trace ("Could not map GEM object %u: %m", buffer->handle);
--                return false;
--        }
--
--        map_address = mmap (0, buffer->map_size,
--                            PROT_READ | PROT_WRITE, MAP_SHARED,
--                            driver->device_fd, map_dumb_buffer_request.offset);
--
--        if (map_address == MAP_FAILED)
--                return false;
--
--        buffer->map_address = map_address;
--        buffer->map_count++;
--
--        return true;
--}
--
--static void
--ply_renderer_buffer_unmap (ply_renderer_driver_t *driver,
--                           ply_renderer_buffer_t *buffer)
--{
--        buffer->map_count--;
--
--        assert (buffer->map_count >= 0);
--}
--
--static ply_renderer_driver_t *
--create_driver (int device_fd)
--{
--        ply_renderer_driver_t *driver;
--
--        driver = calloc (1, sizeof(ply_renderer_driver_t));
--        driver->device_fd = device_fd;
--        driver->requires_explicit_flushing = true;
--        driver->buffers = ply_hashtable_new (ply_hashtable_direct_hash,
--                                             ply_hashtable_direct_compare);
--
--        return driver;
--}
--
--static void
--destroy_driver (ply_renderer_driver_t *driver)
--{
--        ply_hashtable_free (driver->buffers);
--
--        free (driver);
--}
--
--static ply_renderer_buffer_t *
--ply_renderer_buffer_new (ply_renderer_driver_t *driver,
--                         uint32_t               width,
--                         uint32_t               height)
--{
--        ply_renderer_buffer_t *buffer;
--        struct drm_mode_create_dumb create_dumb_buffer_request;
--
--        buffer = calloc (1, sizeof(ply_renderer_buffer_t));
--        buffer->width = width;
--        buffer->height = height;
--        buffer->map_address = MAP_FAILED;
--
--        memset (&create_dumb_buffer_request, 0, sizeof(struct drm_mode_create_dumb));
--
--        create_dumb_buffer_request.width = width;
--        create_dumb_buffer_request.height = height;
--        create_dumb_buffer_request.bpp = 32;
--        create_dumb_buffer_request.flags = 0;
--
--        if (drmIoctl (driver->device_fd,
--                      DRM_IOCTL_MODE_CREATE_DUMB,
--                      &create_dumb_buffer_request) < 0) {
--                free (buffer);
--                ply_trace ("Could not allocate GEM object for frame buffer: %m");
--                return NULL;
--        }
--
--        buffer->handle = create_dumb_buffer_request.handle;
--        buffer->row_stride = create_dumb_buffer_request.pitch;
--        buffer->map_size = create_dumb_buffer_request.size;
--
--        ply_trace ("returning %ux%u buffer with stride %u",
--                   width, height, buffer->row_stride);
--
--        return buffer;
--}
--
--static void
--ply_renderer_buffer_free (ply_renderer_driver_t *driver,
--                          ply_renderer_buffer_t *buffer)
--{
--        struct drm_mode_destroy_dumb destroy_dumb_buffer_request;
--
--        if (buffer->added_fb)
--                drmModeRmFB (driver->device_fd, buffer->id);
--
--        if (buffer->map_address != MAP_FAILED) {
--                munmap (buffer->map_address, buffer->map_size);
--                buffer->map_address = MAP_FAILED;
--        }
--
--        memset (&destroy_dumb_buffer_request, 0, sizeof(struct drm_mode_destroy_dumb));
--        destroy_dumb_buffer_request.handle = buffer->handle;
--
--        if (drmIoctl (driver->device_fd,
--                      DRM_IOCTL_MODE_DESTROY_DUMB,
--                      &destroy_dumb_buffer_request) < 0)
--                ply_trace ("Could not deallocate GEM object %u: %m", buffer->handle);
--
--        free (buffer);
--}
--
--static ply_renderer_buffer_t *
--get_buffer_from_id (ply_renderer_driver_t *driver,
--                    uint32_t               id)
--{
--        static ply_renderer_buffer_t *buffer;
--
--        buffer = ply_hashtable_lookup (driver->buffers, (void *) (uintptr_t) id);
--
--        return buffer;
--}
--
--static bool
--fetch_buffer (ply_renderer_driver_t *driver,
--              uint32_t               buffer_id,
--              unsigned long         *width,
--              unsigned long         *height,
--              unsigned long         *row_stride)
--{
--        ply_renderer_buffer_t *buffer;
--
--        buffer = get_buffer_from_id (driver, buffer_id);
--
--        if (buffer == NULL) {
--                ply_trace ("could not fetch buffer %u", buffer_id);
--                return false;
--        }
--
--        if (width != NULL)
--                *width = buffer->width;
--
--        if (height != NULL)
--                *height = buffer->height;
--
--        if (row_stride != NULL)
--                *row_stride = buffer->row_stride;
--
--        ply_trace ("fetched %ux%u buffer with stride %u",
--                   buffer->width, buffer->height, buffer->row_stride);
--        return true;
--}
--
--static uint32_t
--create_buffer (ply_renderer_driver_t *driver,
--               unsigned long          width,
--               unsigned long          height,
--               unsigned long         *row_stride)
--{
--        ply_renderer_buffer_t *buffer;
--
--        buffer = ply_renderer_buffer_new (driver, width, height);
--
--        if (buffer == NULL) {
--                ply_trace ("Could not allocate GEM object for frame buffer: %m");
--                return 0;
--        }
--
--        if (drmModeAddFB (driver->device_fd, width, height,
--                          24, 32, buffer->row_stride, buffer->handle,
--                          &buffer->id) != 0) {
--                ply_trace ("Could not set up GEM object as frame buffer: %m");
--                ply_renderer_buffer_free (driver, buffer);
--                return 0;
--        }
--
--        *row_stride = buffer->row_stride;
--
--        buffer->added_fb = true;
--        ply_hashtable_insert (driver->buffers,
--                              (void *) (uintptr_t) buffer->id,
--                              buffer);
--
--        return buffer->id;
--}
--
--static bool
--map_buffer (ply_renderer_driver_t *driver,
--            uint32_t               buffer_id)
--{
--        ply_renderer_buffer_t *buffer;
--
--        buffer = get_buffer_from_id (driver, buffer_id);
--
--        assert (buffer != NULL);
--
--        return ply_renderer_buffer_map (driver, buffer);
--}
--
--static void
--unmap_buffer (ply_renderer_driver_t *driver,
--              uint32_t               buffer_id)
--{
--        ply_renderer_buffer_t *buffer;
--
--        buffer = get_buffer_from_id (driver, buffer_id);
--
--        assert (buffer != NULL);
--
--        ply_renderer_buffer_unmap (driver, buffer);
--}
--
--static char *
--begin_flush (ply_renderer_driver_t *driver,
--             uint32_t               buffer_id)
--{
--        ply_renderer_buffer_t *buffer;
--
--        buffer = get_buffer_from_id (driver, buffer_id);
--
--        assert (buffer != NULL);
--
--        return buffer->map_address;
--}
--
--static void
--end_flush (ply_renderer_driver_t *driver,
--           uint32_t               buffer_id)
--{
--        ply_renderer_buffer_t *buffer;
--
--        buffer = get_buffer_from_id (driver, buffer_id);
--
--        assert (buffer != NULL);
--
--        if (driver->requires_explicit_flushing) {
--                struct drm_clip_rect flush_area;
--                int ret;
--
--                flush_area.x1 = 0;
--                flush_area.y1 = 0;
--                flush_area.x2 = buffer->width;
--                flush_area.y2 = buffer->height;
--
--                ret = drmModeDirtyFB (driver->device_fd, buffer->id, &flush_area, 1);
--
--                if (ret == -ENOSYS)
--                        driver->requires_explicit_flushing = false;
--        }
--}
--
--static void
--destroy_buffer (ply_renderer_driver_t *driver,
--                uint32_t               buffer_id)
--{
--        ply_renderer_buffer_t *buffer;
--
--        buffer = ply_hashtable_remove (driver->buffers,
--                                       (void *) (uintptr_t) buffer_id);
--
--        assert (buffer != NULL);
--
--        ply_renderer_buffer_free (driver, buffer);
--}
--
--ply_renderer_driver_interface_t *
--ply_renderer_generic_driver_get_interface (int device_fd)
--{
--        uint64_t supports_dumb_buffers;
--
--        static ply_renderer_driver_interface_t driver_interface =
--        {
--                .create_driver  = create_driver,
--                .destroy_driver = destroy_driver,
--                .create_buffer  = create_buffer,
--                .fetch_buffer   = fetch_buffer,
--                .map_buffer     = map_buffer,
--                .unmap_buffer   = unmap_buffer,
--                .begin_flush    = begin_flush,
--                .end_flush      = end_flush,
--                .destroy_buffer = destroy_buffer,
--        };
--
--
--        if (drmGetCap (device_fd, DRM_CAP_DUMB_BUFFER, &supports_dumb_buffers) < 0)
--                return NULL;
--
--        if (!supports_dumb_buffers)
--                return NULL;
--
--        return &driver_interface;
--}
--
--/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s, (0,=.5s,:.5s */
-diff --git a/src/plugins/renderers/drm/ply-renderer-generic-driver.h b/src/plugins/renderers/drm/ply-renderer-generic-driver.h
-deleted file mode 100644
-index 053587a..0000000
---- a/src/plugins/renderers/drm/ply-renderer-generic-driver.h
-+++ /dev/null
-@@ -1,33 +0,0 @@
--/* ply-renderer-generic-driver.h
-- *
-- * Copyright (C) 2012 Red Hat, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2, or (at your option)
-- * any later version.
-- *
-- * This program 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 General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-- * 02111-1307, USA.
-- *
-- * Written by: Dave Airlie
-- * Based on other renderer drivers written by Ray Strode
-- */
--#ifndef PLY_RENDERER_DUMB_DRIVER_H
--#define PLY_RENDERER_DUMB_DRIVER_H
--
--#include "ply-renderer-driver.h"
--
--#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
--ply_renderer_driver_interface_t *ply_renderer_generic_driver_get_interface (int device_fd);
--#endif
--
--#endif /* PLY_RENDERER_GENERIC_DRIVER_H */
--/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
-diff --git a/src/plugins/renderers/frame-buffer/plugin.c b/src/plugins/renderers/frame-buffer/plugin.c
-index 418855a..41ad6cd 100644
---- a/src/plugins/renderers/frame-buffer/plugin.c
-+++ b/src/plugins/renderers/frame-buffer/plugin.c
-@@ -365,6 +365,12 @@ open_device (ply_renderer_backend_t *backend)
-         return true;
- }
- 
-+static const char *
-+get_device_name (ply_renderer_backend_t *backend)
-+{
-+        return backend->device_name;
-+}
-+
- static void
- close_device (ply_renderer_backend_t *backend)
- {
-@@ -732,7 +738,8 @@ ply_renderer_backend_get_interface (void)
-                 .get_input_source             = get_input_source,
-                 .open_input_source            = open_input_source,
-                 .set_handler_for_input_source = set_handler_for_input_source,
--                .close_input_source           = close_input_source
-+                .close_input_source           = close_input_source,
-+                .get_device_name              = get_device_name
-         };
- 
-         return &plugin_interface;
-diff --git a/src/plugins/renderers/x11/plugin.c b/src/plugins/renderers/x11/plugin.c
-index 1e1fe31..8948f69 100644
---- a/src/plugins/renderers/x11/plugin.c
-+++ b/src/plugins/renderers/x11/plugin.c
-@@ -56,6 +56,7 @@
- #include "ply-logger.h"
- #include "ply-rectangle.h"
- #include "ply-region.h"
-+#include "ply-utils.h"
- 
- #include "ply-renderer.h"
- #include "ply-renderer-plugin.h"
-@@ -64,9 +65,10 @@ struct _ply_renderer_head
- {
-         ply_renderer_backend_t *backend;
-         ply_pixel_buffer_t     *pixel_buffer;
--        ply_rectangle_t         area;
-+        ply_rectangle_t         area; /* in device pixels */
-         GtkWidget              *window;
-         cairo_surface_t        *image;
-+        uint32_t                scale;
-         uint32_t                is_fullscreen : 1;
- };
- 
-@@ -148,9 +150,14 @@ open_device (ply_renderer_backend_t *backend)
-         Display *display;
-         int display_fd;
- 
-+        gdk_set_allowed_backends ("x11");
-+
-         if (!gtk_init_check (0, NULL))
-                 return false;
- 
-+        /* Force gtk+ to deal in device pixels */
-+        gdk_x11_display_set_window_scale (gdk_display_get_default (), 1);
-+
-         display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-         display_fd = ConnectionNumber (display);
-         backend->display_watch = ply_event_loop_watch_fd (backend->loop,
-@@ -163,6 +170,12 @@ open_device (ply_renderer_backend_t *backend)
-         return true;
- }
- 
-+static const char *
-+get_device_name (ply_renderer_backend_t *backend)
-+{
-+        return gdk_display_get_name (gdk_display_get_default ());
-+}
-+
- static void
- close_device (ply_renderer_backend_t *backend)
- {
-@@ -183,7 +196,9 @@ create_fake_multi_head_setup (ply_renderer_backend_t *backend)
-         head->area.y = 0;
-         head->area.width = 800;   /* FIXME hardcoded */
-         head->area.height = 600;
-+        head->scale = 1;
-         head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height);
-+        ply_pixel_buffer_set_device_scale (head->pixel_buffer, head->scale);
- 
-         ply_list_append_data (backend->heads, head);
- 
-@@ -194,7 +209,9 @@ create_fake_multi_head_setup (ply_renderer_backend_t *backend)
-         head->area.y = 0;
-         head->area.width = 640;   /* FIXME hardcoded */
-         head->area.height = 480;
-+        head->scale = 1;
-         head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height);
-+        ply_pixel_buffer_set_device_scale (head->pixel_buffer, head->scale);
- 
-         ply_list_append_data (backend->heads, head);
- }
-@@ -204,8 +221,11 @@ create_fullscreen_single_head_setup (ply_renderer_backend_t *backend)
- {
-         ply_renderer_head_t *head;
-         GdkRectangle monitor_geometry;
-+        int width_mm, height_mm;
- 
-         gdk_screen_get_monitor_geometry (gdk_screen_get_default (), 0, &monitor_geometry);
-+        width_mm = gdk_screen_get_monitor_width_mm (gdk_screen_get_default (), 0);
-+        height_mm = gdk_screen_get_monitor_height_mm (gdk_screen_get_default (), 0);
- 
-         head = calloc (1, sizeof(ply_renderer_head_t));
- 
-@@ -215,7 +235,11 @@ create_fullscreen_single_head_setup (ply_renderer_backend_t *backend)
-         head->area.width = monitor_geometry.width;
-         head->area.height = monitor_geometry.height;
-         head->is_fullscreen = true;
-+        head->scale = ply_get_device_scale (monitor_geometry.width,
-+                                            monitor_geometry.height,
-+                                            width_mm, height_mm);
-         head->pixel_buffer = ply_pixel_buffer_new (head->area.width, head->area.height);
-+        ply_pixel_buffer_set_device_scale (head->pixel_buffer, head->scale);
- 
-         ply_list_append_data (backend->heads, head);
- }
-@@ -380,6 +404,12 @@ flush_head (ply_renderer_backend_t *backend,
-                 area_to_flush = (ply_rectangle_t *) ply_list_node_get_data (node);
-                 next_node = ply_list_get_next_node (areas_to_flush, node);
- 
-+                cairo_surface_mark_dirty_rectangle (head->image,
-+                                                    area_to_flush->x,
-+                                                    area_to_flush->y,
-+                                                    area_to_flush->width,
-+                                                    area_to_flush->height);
-+
-                 gtk_widget_queue_draw_area (head->window,
-                                             area_to_flush->x,
-                                             area_to_flush->y,
-@@ -515,7 +545,8 @@ ply_renderer_backend_get_interface (void)
-                 .get_input_source             = get_input_source,
-                 .open_input_source            = open_input_source,
-                 .set_handler_for_input_source = set_handler_for_input_source,
--                .close_input_source           = close_input_source
-+                .close_input_source           = close_input_source,
-+                .get_device_name              = get_device_name
-         };
- 
-         return &plugin_interface;
-diff --git a/src/plugins/splash/details/plugin.c b/src/plugins/splash/details/plugin.c
-index 8e55d05..f534450 100644
---- a/src/plugins/splash/details/plugin.c
-+++ b/src/plugins/splash/details/plugin.c
-@@ -77,6 +77,8 @@ struct _ply_boot_splash_plugin
-         ply_list_t                    *views;
-         ply_boot_splash_display_type_t state;
-         ply_list_t                    *messages;
-+
-+        ply_buffer_t                  *boot_buffer;
- };
- 
- static view_t *
-@@ -239,6 +241,15 @@ add_text_display (ply_boot_splash_plugin_t *plugin,
-                 ply_terminal_activate_vt (terminal);
- 
-         ply_list_append_data (plugin->views, view);
-+
-+        if (plugin->boot_buffer != NULL) {
-+                size_t size;
-+                const char *bytes;
-+
-+                size = ply_buffer_get_size (plugin->boot_buffer);
-+                bytes = ply_buffer_get_bytes (plugin->boot_buffer);
-+                view_write (view, bytes, size);
-+        }
- }
- 
- static void
-@@ -282,8 +293,9 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
-                                        plugin);
- 
-         if (boot_buffer) {
--                size = ply_buffer_get_size (boot_buffer);
-+                plugin->boot_buffer = boot_buffer;
- 
-+                size = ply_buffer_get_size (boot_buffer);
-                 write_on_views (plugin, ply_buffer_get_bytes (boot_buffer), size);
-         }
- 
-@@ -330,7 +342,7 @@ display_normal (ply_boot_splash_plugin_t *plugin)
-         ply_list_node_t *node;
- 
-         if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL)
--                write_on_views (plugin, "\r\n", strlen ("\r\n"));
-+                write_on_views (plugin, "\n", strlen ("\n"));
- 
-         plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
- 
-@@ -343,7 +355,7 @@ display_normal (ply_boot_splash_plugin_t *plugin)
-                 next_node = ply_list_get_next_node (plugin->messages, node);
- 
-                 write_on_views (plugin, message, strlen (message));
--                write_on_views (plugin, "\r\n", strlen ("\r\n"));
-+                write_on_views (plugin, "\n", strlen ("\n"));
- 
-                 ply_list_remove_node (plugin->messages, node);
-                 node = next_node;
-@@ -358,7 +370,7 @@ display_password (ply_boot_splash_plugin_t *plugin,
-         int i;
- 
-         if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY)
--                write_on_views (plugin, "\r\n", strlen ("\r\n"));
-+                write_on_views (plugin, "\n", strlen ("\n"));
-         else
-                 write_on_views (plugin,
-                                 CLEAR_LINE_SEQUENCE,
-@@ -387,7 +399,7 @@ display_question (ply_boot_splash_plugin_t *plugin,
-                   const char               *entry_text)
- {
-         if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY)
--                write_on_views (plugin, "\r\n", strlen ("\r\n"));
-+                write_on_views (plugin, "\n", strlen ("\n"));
-         else
-                 write_on_views (plugin,
-                                 CLEAR_LINE_SEQUENCE,
-@@ -407,7 +419,7 @@ display_message (ply_boot_splash_plugin_t *plugin,
- {
-         if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) {
-                 write_on_views (plugin, message, strlen (message));
--                write_on_views (plugin, "\r\n", strlen ("\r\n"));
-+                write_on_views (plugin, "\n", strlen ("\n"));
-         } else {
-                 ply_list_append_data (plugin->messages, strdup (message));
-         }
-diff --git a/src/plugins/splash/fade-throbber/plugin.c b/src/plugins/splash/fade-throbber/plugin.c
-index 1643b87..a7ab4ef 100644
---- a/src/plugins/splash/fade-throbber/plugin.c
-+++ b/src/plugins/splash/fade-throbber/plugin.c
-@@ -104,6 +104,7 @@ struct _ply_boot_splash_plugin
-         double                         now;
- 
-         uint32_t                       is_animating : 1;
-+        uint32_t                       is_visible : 1;
- };
- 
- ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void);
-@@ -264,6 +265,8 @@ view_free (view_t *view)
-         ply_label_free (view->message_label);
-         free_stars (view);
- 
-+        ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
-+
-         free (view);
- }
- 
-@@ -293,8 +296,12 @@ load_views (ply_boot_splash_plugin_t *plugin)
-                 view = ply_list_node_get_data (node);
-                 next_node = ply_list_get_next_node (plugin->views, node);
- 
--                if (view_load (view))
-+                if (view_load (view)) {
-                         view_loaded = true;
-+                } else {
-+                        ply_list_remove_node (plugin->views, node);
-+                        view_free (view);
-+                }
- 
-                 node = next_node;
-         }
-@@ -745,7 +752,14 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin,
-                                             (ply_pixel_display_draw_handler_t)
-                                             on_draw, view);
- 
--        ply_list_append_data (plugin->views, view);
-+        if (plugin->is_visible) {
-+                if (view_load (view))
-+                        ply_list_append_data (plugin->views, view);
-+                else
-+                        view_free (view);
-+        } else {
-+                ply_list_append_data (plugin->views, view);
-+        }
- }
- 
- static void
-@@ -763,7 +777,6 @@ remove_pixel_display (ply_boot_splash_plugin_t *plugin,
-                 next_node = ply_list_get_next_node (plugin->views, node);
- 
-                 if (view->display == display) {
--                        ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
-                         view_free (view);
-                         ply_list_remove_node (plugin->views, node);
-                         return;
-@@ -806,6 +819,8 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
-                 return false;
-         }
- 
-+        plugin->is_visible = true;
-+
-         ply_trace ("starting boot animation");
-         start_animation (plugin);
- 
-@@ -940,6 +955,8 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
- {
-         assert (plugin != NULL);
- 
-+        plugin->is_visible = false;
-+
-         if (plugin->loop != NULL) {
-                 stop_animation (plugin);
- 
-diff --git a/src/plugins/splash/script/script-lib-sprite.c b/src/plugins/splash/script/script-lib-sprite.c
-index f292d90..c49297d 100644
---- a/src/plugins/splash/script/script-lib-sprite.c
-+++ b/src/plugins/splash/script/script-lib-sprite.c
-@@ -416,6 +416,22 @@ static script_return_t sprite_window_set_background_bottom_color (script_state_t
-         return script_return_obj_null ();
- }
- 
-+static void script_lib_draw_brackground (ply_pixel_buffer_t *pixel_buffer,
-+                                         ply_rectangle_t *clip_area,
-+                                         script_lib_sprite_data_t *data)
-+{
-+        if (data->background_color_start == data->background_color_end) {
-+                ply_pixel_buffer_fill_with_hex_color (pixel_buffer,
-+                                                      clip_area,
-+                                                      data->background_color_start);
-+        } else {
-+                ply_pixel_buffer_fill_with_gradient (pixel_buffer,
-+                                                     clip_area,
-+                                                     data->background_color_start,
-+                                                     data->background_color_end);
-+        }
-+}
-+
- static void script_lib_sprite_draw_area (script_lib_display_t *display,
-                                          ply_pixel_buffer_t   *pixel_buffer,
-                                          int                   x,
-@@ -425,6 +441,7 @@ static void script_lib_sprite_draw_area (script_lib_display_t *display,
- {
-         ply_rectangle_t clip_area;
-         ply_list_node_t *node;
-+        sprite_t *sprite;
-         script_lib_sprite_data_t *data = display->data;
- 
-         clip_area.x = x;
-@@ -432,22 +449,33 @@ static void script_lib_sprite_draw_area (script_lib_display_t *display,
-         clip_area.width = width;
-         clip_area.height = height;
- 
--        if (data->background_color_start == data->background_color_end) {
--                ply_pixel_buffer_fill_with_hex_color (pixel_buffer,
--                                                      &clip_area,
--                                                      data->background_color_start);
-+
-+        node = ply_list_get_first_node (data->sprite_list);
-+        sprite = ply_list_node_get_data (node);
-+
-+        /* Check If the first sprite should be rendered opaque */
-+        if (sprite->image && !sprite->remove_me &&
-+            ply_pixel_buffer_is_opaque (sprite->image) && sprite->opacity == 1.0)  {
-+                int position_x = sprite->x - display->x;
-+                int position_y = sprite->y - display->y;
-+
-+                /* In that case only draw the background if the sprite doesn't
-+                 * cover the complete area */
-+                if (position_x > x || position_y > y ||
-+                    (ply_pixel_buffer_get_width (sprite->image) + position_x) < (x + width) ||
-+                    (ply_pixel_buffer_get_height (sprite->image) + position_y) < (y + height))
-+                        script_lib_draw_brackground (pixel_buffer, &clip_area, data);
-         } else {
--                ply_pixel_buffer_fill_with_gradient (pixel_buffer,
--                                                     &clip_area,
--                                                     data->background_color_start,
--                                                     data->background_color_end);
-+                script_lib_draw_brackground (pixel_buffer, &clip_area, data);
-         }
-+
-         for (node = ply_list_get_first_node (data->sprite_list);
-              node;
-              node = ply_list_get_next_node (data->sprite_list, node)) {
--                sprite_t *sprite = ply_list_node_get_data (node);
-                 int position_x, position_y;
- 
-+                sprite = ply_list_node_get_data (node);
-+
-                 if (!sprite->image) continue;
-                 if (sprite->remove_me) continue;
-                 if (sprite->opacity < 0.011) continue;
-diff --git a/src/plugins/splash/space-flares/plugin.c b/src/plugins/splash/space-flares/plugin.c
-index 5212c38..5af99c1 100644
---- a/src/plugins/splash/space-flares/plugin.c
-+++ b/src/plugins/splash/space-flares/plugin.c
-@@ -1387,7 +1387,14 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin,
-                                             (ply_pixel_display_draw_handler_t)
-                                             on_draw, view);
- 
--        ply_list_append_data (plugin->views, view);
-+        if (plugin->is_visible) {
-+                if (view_load (view))
-+                        ply_list_append_data (plugin->views, view);
-+                else
-+                        view_free (view);
-+        } else {
-+                ply_list_append_data (plugin->views, view);
-+        }
- }
- 
- static void
-diff --git a/src/plugins/splash/text/plugin.c b/src/plugins/splash/text/plugin.c
-index 468bb89..8260daa 100644
---- a/src/plugins/splash/text/plugin.c
-+++ b/src/plugins/splash/text/plugin.c
-@@ -472,6 +472,9 @@ add_text_display (ply_boot_splash_plugin_t *plugin,
-                                            on_draw, view);
- 
-         ply_list_append_data (plugin->views, view);
-+
-+        if (plugin->is_animating)
-+                view_start_animation (view);
- }
- 
- static void
-@@ -553,7 +556,9 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin,
-                 next_node = ply_list_get_next_node (plugin->views, node);
- 
-                 ply_text_step_bar_set_percent_done (view->step_bar, percent_done);
--                ply_text_step_bar_draw (view->step_bar);
-+
-+                if (plugin->is_animating)
-+                        ply_text_step_bar_draw (view->step_bar);
- 
-                 node = next_node;
-         }
-diff --git a/src/plugins/splash/throbgress/plugin.c b/src/plugins/splash/throbgress/plugin.c
-index c105e02..a1c8a90 100644
---- a/src/plugins/splash/throbgress/plugin.c
-+++ b/src/plugins/splash/throbgress/plugin.c
-@@ -625,7 +625,14 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin,
-                                             (ply_pixel_display_draw_handler_t)
-                                             on_draw, view);
- 
--        ply_list_append_data (plugin->views, view);
-+        if (plugin->is_visible) {
-+                if (view_load (view))
-+                        ply_list_append_data (plugin->views, view);
-+                else
-+                        view_free (view);
-+        } else {
-+                ply_list_append_data (plugin->views, view);
-+        }
- }
- 
- static void
-diff --git a/src/plugins/splash/tribar/plugin.c b/src/plugins/splash/tribar/plugin.c
-index 0dcd7f8..ecc17ea 100644
---- a/src/plugins/splash/tribar/plugin.c
-+++ b/src/plugins/splash/tribar/plugin.c
-@@ -478,6 +478,9 @@ add_text_display (ply_boot_splash_plugin_t *plugin,
-                                            on_draw, view);
- 
-         ply_list_append_data (plugin->views, view);
-+
-+        if (plugin->is_animating)
-+                view_start_animation (view);
- }
- 
- static void
-@@ -559,7 +562,9 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin,
-                 next_node = ply_list_get_next_node (plugin->views, node);
- 
-                 ply_text_progress_bar_set_percent_done (view->progress_bar, percent_done);
--                ply_text_progress_bar_draw (view->progress_bar);
-+
-+                if (plugin->is_animating)
-+                        ply_text_progress_bar_draw (view->progress_bar);
- 
-                 node = next_node;
-         }
-diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c
-index 0899ace..070741d 100644
---- a/src/plugins/splash/two-step/plugin.c
-+++ b/src/plugins/splash/two-step/plugin.c
-@@ -267,11 +267,15 @@ view_load (view_t *view)
- 
-         view_load_end_animation (view);
- 
--        ply_trace ("loading progress animation");
--        if (!ply_progress_animation_load (view->progress_animation)) {
--                ply_trace ("optional progress animation wouldn't load");
--                ply_progress_animation_free (view->progress_animation);
--                view->progress_animation = NULL;
-+        if (view->progress_animation != NULL) {
-+                ply_trace ("loading progress animation");
-+                if (!ply_progress_animation_load (view->progress_animation)) {
-+                        ply_trace ("optional progress animation wouldn't load");
-+                        ply_progress_animation_free (view->progress_animation);
-+                        view->progress_animation = NULL;
-+                }
-+        } else {
-+                ply_trace ("this theme has no progress animation");
-         }
- 
-         if (view->throbber != NULL) {
-@@ -875,7 +879,12 @@ draw_background (view_t             *view,
-         if (view->background_image != NULL) {
-                 uint32_t *data;
-                 data = ply_image_get_data (view->background_image);
--                ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &area, data);
-+
-+                /* We must pass NULL as fill area, because the fill area
-+                   must be sized as the image we're sourcing from, otherwise
-+                   sampling does not work
-+                */
-+                ply_pixel_buffer_fill_with_argb32_data_with_clip (pixel_buffer, NULL, NULL, data);
-         }
- 
-         if (plugin->watermark_image != NULL) {
-@@ -986,7 +995,14 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin,
-         ply_pixel_display_set_draw_handler (view->display,
-                                             (ply_pixel_display_draw_handler_t)
-                                             on_draw, view);
--        ply_list_append_data (plugin->views, view);
-+        if (plugin->is_visible) {
-+                if (view_load (view))
-+                        ply_list_append_data (plugin->views, view);
-+                else
-+                        view_free (view);
-+        } else {
-+                ply_list_append_data (plugin->views, view);
-+        }
- }
- 
- static void
-@@ -1329,8 +1345,8 @@ system_update (ply_boot_splash_plugin_t *plugin,
- 
-                 view = ply_list_node_get_data (node);
-                 next_node = ply_list_get_next_node (plugin->views, node);
--                ply_progress_animation_set_percent_done (view->progress_animation,
--                                                         (double) progress / 100.f);
-+                if (view->progress_animation != NULL)
-+                        ply_progress_animation_set_percent_done (view->progress_animation, (double) progress / 100.f);
-                 node = next_node;
-         }
- }
-diff --git a/src/plymouthd.defaults b/src/plymouthd.defaults
-index fc48b15..4d3b6d4 100644
---- a/src/plymouthd.defaults
-+++ b/src/plymouthd.defaults
-@@ -3,3 +3,4 @@
- [Daemon]
- Theme=spinner
- ShowDelay=5
-+DeviceTimeout=5
-diff --git a/systemd-units/Makefile.am b/systemd-units/Makefile.am
-index 89355ac..b1d843b 100644
---- a/systemd-units/Makefile.am
-+++ b/systemd-units/Makefile.am
-@@ -50,21 +50,20 @@ install-data-hook:
- 		$(LN_S) ../plymouth-halt.service)
- 
- uninstall-hook:
--	rm -f \
- 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/initrd-switch-root.target.wants && \
--		rm -f plymouth-start.service plymouth-switch-root.service)   \
-+		rm -f plymouth-start.service plymouth-switch-root.service)
- 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants &&            \
--		rm -f plymouth-start.service plymouth-read-write.service)    \
-+		rm -f plymouth-start.service plymouth-read-write.service)
- 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants &&         \
--		rm -f plymouth-quit.service plymouth-quit-wait.service)      \
-+		rm -f plymouth-quit.service plymouth-quit-wait.service)
- 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/reboot.target.wants &&             \
--		rm -f plymouth-reboot.service)                               \
-+		rm -f plymouth-reboot.service)
- 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/kexec.target.wants &&              \
--		rm -f plymouth-kexec.service)                                \
-+		rm -f plymouth-kexec.service)
- 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants &&           \
--		rm -f plymouth-poweroff.service)                             \
-+		rm -f plymouth-poweroff.service)
- 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants &&               \
--		rm -f plymouth-halt.service)                                 \
-+		rm -f plymouth-halt.service)
- 	rmdir --ignore-fail-on-non-empty                                     \
- 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants           \
- 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants        \
-diff --git a/themes/script/script.script b/themes/script/script.script
-index 7ea9d5e..25a2f2b 100644
---- a/themes/script/script.script
-+++ b/themes/script/script.script
-@@ -152,27 +152,19 @@ Plymouth.SetQuitFunction(quit_callback);
- 
- #----------------------------------------- Message --------------------------------
- 
--message_sprites = [];
--message_sprite_count = 0;
--message_sprite_y = 10;
-+message_sprite = Sprite();
-+message_sprite.SetPosition(10, 10, 10000);
- 
- fun display_message_callback (text)
- {
-   my_image = Image.Text(text, 1, 1, 1);
--  message_sprites[message_sprite_count] = Sprite(my_image);
--  message_sprites[message_sprite_count].SetPosition(10, message_sprite_y, 10000);
--  message_sprites[message_sprite_count].text = text;
--  message_sprite_count++;
--  message_sprite_y += my_image.GetHeight();
-+  message_sprite.SetImage(my_image);
- }
- 
- fun hide_message_callback (text)
- {
--  for (i = 0; i < message_sprite_count; i++)
--    {
--      if (message_sprites[i].text == text)
--        message_sprites[i] = NULL;
--    }
-+  message_sprite = Sprite();
-+  message_sprite.SetPosition(10, 10, 10000);
- }
- 
- Plymouth.SetDisplayMessageFunction (display_message_callback);
diff --git a/community/prosody/luasec-0.6-fix.patch b/community/prosody/luasec-0.6-fix.patch
deleted file mode 100644
index c8e37d09150a..000000000000
--- a/community/prosody/luasec-0.6-fix.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-diff --git a/util/dependencies.lua b/util/dependencies.lua
-index 4d50cf6..9ea211d 100644
---- a/util/dependencies.lua
-+++ b/util/dependencies.lua
-@@ -99,6 +99,9 @@ function check_dependencies()
- 				["luarocks"] = "luarocks install luasec";
- 				["Source"] = "http://www.inf.puc-rio.br/~brunoos/luasec/";
- 			}, "SSL/TLS support will not be available");
-+	elseif not _G.ssl then
-+		_G.ssl = ssl;
-+		_G.ssl.context = require "ssl.context";
- 	end
- 	
- 	local encodings, err = softreq "util.encodings"
diff --git a/community/prosody/mallinfo.patch b/community/prosody/mallinfo.patch
deleted file mode 100644
index 4f9247c9bc47..000000000000
--- a/community/prosody/mallinfo.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/util-src/pposix.c b/util-src/pposix.c
-index e70a9d7..b9729ab 100644
---- a/util-src/pposix.c
-+++ b/util-src/pposix.c
-@@ -52,7 +52,7 @@
- #include <linux/falloc.h>
- #endif
- 
--#if !defined(WITHOUT_MALLINFO) && defined(__linux__)
-+#ifdef __GLIBC__
- #include <malloc.h>
- #define WITH_MALLINFO
- #endif
diff --git a/community/prosody/prosodyctl.patch b/community/prosody/prosodyctl.patch
deleted file mode 100644
index 18333dd524f3..000000000000
--- a/community/prosody/prosodyctl.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- prosody-0.9.10.q/prosodyctl
-+++ prosody-0.9.10/prosodyctl
-@@ -244,7 +244,7 @@
- local modulemanager = require "core.modulemanager"
- 
- local prosodyctl = require "util.prosodyctl"
--require "socket"
-+local socket = require "socket"
- -----------------------
- 
-  -- FIXME: Duplicate code waiting for util.startup
diff --git a/community/py3-itypes/disable-flake8.patch b/community/py3-itypes/disable-flake8.patch
deleted file mode 100644
index 91ee70a28bdf..000000000000
--- a/community/py3-itypes/disable-flake8.patch
+++ /dev/null
@@ -1,30 +0,0 @@
---- itypes-1.1.0.orig/runtests
-+++ itypes-1.1.0/runtests
-@@ -6,7 +6,6 @@
- 
- 
- PYTEST_ARGS = ['tests.py', '--tb=short']
--FLAKE8_ARGS = ['itypes.py', 'tests.py', '--ignore=E501']
- COVERAGE_OPTIONS = {
-     'include': ['itypes.py', 'tests.py'],
- }
-@@ -25,13 +24,6 @@
-         sys.exit(ret)
- 
- 
--def flake8_main(args):
--    print('Running flake8 code linting')
--    ret = subprocess.call(['flake8'] + args)
--    print('flake8 failed' if ret else 'flake8 passed')
--    return ret
--
--
- def fail_if_lacking_coverage(cov):
-     precent_covered = cov.report(
-         file=NullFile(), **COVERAGE_OPTIONS
-@@ -82,5 +74,4 @@
-     # cov.start()
-     exit_on_failure(pytest.main(pytest_args))
-     # cov.stop()
--    exit_on_failure(flake8_main(FLAKE8_ARGS))
-     # fail_if_lacking_coverage(cov)
diff --git a/community/raptor2/raptor-curl.patch b/community/raptor2/raptor-curl.patch
deleted file mode 100644
index e47a496c4ca5..000000000000
--- a/community/raptor2/raptor-curl.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/src/raptor_internal.h b/src/raptor_internal.h
-index f7944db..d9c2068 100644
---- a/src/raptor_internal.h
-+++ b/src/raptor_internal.h
-@@ -852,7 +852,6 @@ int raptor_utf8_is_nfc(const unsigned char *input, size_t length);
- 
- #ifdef RAPTOR_WWW_LIBCURL
- #include <curl/curl.h>
--#include <curl/types.h>
- #include <curl/easy.h>
- #endif
- 
diff --git a/community/rethinkdb/musl-fixes-all.patch b/community/rethinkdb/musl-fixes-all.patch
deleted file mode 100644
index 7828f7fd0ba6..000000000000
--- a/community/rethinkdb/musl-fixes-all.patch
+++ /dev/null
@@ -1,95 +0,0 @@
---- ./src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc.orig
-+++ ./src/rdb_protocol/geo/s2/util/math/exactfloat/exactfloat.cc
-@@ -104,9 +104,9 @@
- ExactFloat::ExactFloat(double v) {
-   BN_init(&bn_);
-   sign_ = signbit(v) ? -1 : 1;
--  if (isnan(v)) {
-+  if (std::isnan(v)) {
-     set_nan();
--  } else if (isinf(v)) {
-+  } else if (std::isinf(v)) {
-     set_inf(sign_);
-   } else {
-     // The following code is much simpler than messing about with bit masks,
---- ./src/rdb_protocol/geo/s2/util/math/mathlimits.h.orig
-+++ ./src/rdb_protocol/geo/s2/util/math/mathlimits.h
-@@ -195,11 +195,11 @@
-   static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; }
- #else
- #define DECL_FP_LIMIT_FUNCS \
--  static bool IsFinite(const Type x) { return !isinf(x)  &&  !isnan(x); } \
--  static bool IsNaN(const Type x) { return isnan(x); } \
--  static bool IsInf(const Type x) { return isinf(x); } \
--  static bool IsPosInf(const Type x) { return isinf(x)  &&  x > 0; } \
--  static bool IsNegInf(const Type x) { return isinf(x)  &&  x < 0; }
-+  static bool IsFinite(const Type x) { return !std::isinf(x)  &&  !std::isnan(x); } \
-+  static bool IsNaN(const Type x) { return std::isnan(x); } \
-+  static bool IsInf(const Type x) { return std::isinf(x); } \
-+  static bool IsPosInf(const Type x) { return std::isinf(x)  &&  x > 0; } \
-+  static bool IsNegInf(const Type x) { return std::isinf(x)  &&  x < 0; }
- #endif
- 
- // We can't put floating-point constant values in the header here because
---- ./src/rdb_protocol/geo/s2/util/math/mathlimits.h.orig
-+++ ./src/rdb_protocol/geo/s2/util/math/mathlimits.h
-@@ -14,7 +14,7 @@
- #define UTIL_MATH_MATHLIMITS_H__
- 
- #include <string.h>
--#include <math.h>
-+#include <cmath>
- #include <cfloat>
- 
- #include "rdb_protocol/geo/s2/base/basictypes.h"
---- ./src/threading.hpp.orig
-+++ ./src/threading.hpp
-@@ -1,6 +1,7 @@
- #ifndef THREADING_HPP_
- #define THREADING_HPP_
- 
-+#include <unistd.h>
- #include "errors.hpp"
- 
- // A thread number as used by the thread pool.
---- ./src/threading.hpp.orig
-+++ ./src/threading.hpp
-@@ -2,6 +2,7 @@
- #define THREADING_HPP_
- 
- #include <unistd.h>
-+#include <sys/types.h>
- #include "errors.hpp"
- 
- // A thread number as used by the thread pool.
---- ./src/containers/printf_buffer.hpp.orig
-+++ ./src/containers/printf_buffer.hpp
-@@ -5,6 +5,7 @@
- #include <stdarg.h>
- #include <stdio.h>
- #include <string.h>
-+#include <sys/types.h>
- 
- // Cannot include utils.hpp, we are included by utils.hpp.
- #include "errors.hpp"
---- ./src/containers/buffer_group.hpp.orig
-+++ ./src/containers/buffer_group.hpp
-@@ -4,6 +4,7 @@
- 
- #include <stdlib.h>
- #include <vector>
-+#include <sys/types.h>
- 
- #include "errors.hpp"
- 
---- ./src/errors.cc.orig
-+++ ./src/errors.cc
-@@ -87,7 +87,7 @@
- }
- 
- const char *errno_string_maybe_using_buffer(int errsv, char *buf, size_t buflen) {
--#ifdef _GNU_SOURCE
-+#ifdef __GLIBC__
-     return strerror_r(errsv, buf, buflen);
- #else
-     // The result is either 0 or ERANGE (if the buffer is too small) or EINVAL (if the error number
diff --git a/community/sleuthkit/20_fix_spelling_errors.patch b/community/sleuthkit/20_fix_spelling_errors.patch
deleted file mode 100644
index ec788ea29df5..000000000000
--- a/community/sleuthkit/20_fix_spelling_errors.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-Description: fix spelling errors.
-Author: Joao Eriberto Mota Filho <eriberto@debian.org>
-Last-Update: 2015-11-12
-Index: sleuthkit-4.2.0/tsk/auto/auto_db.cpp
-===================================================================
---- sleuthkit-4.2.0.orig/tsk/auto/auto_db.cpp
-+++ sleuthkit-4.2.0/tsk/auto/auto_db.cpp
-@@ -395,7 +395,7 @@ uint8_t
-     if (m_db->inTransaction()) {
-         tsk_error_reset();
-         tsk_error_set_errno(TSK_ERR_AUTO_DB);
--        tsk_error_set_errstr("TskAutoDb::startAddImage(): Already in a transaction, image might not be commited");
-+        tsk_error_set_errstr("TskAutoDb::startAddImage(): Already in a transaction, image might not be committed");
-         registerError();
-         return 1;
-     }
-@@ -439,7 +439,7 @@ uint8_t
-     if (m_db->inTransaction()) {
-         tsk_error_reset();
-         tsk_error_set_errno(TSK_ERR_AUTO_DB);
--        tsk_error_set_errstr("TskAutoDb::startAddImage(): Already in a transaction, image might not be commited");
-+        tsk_error_set_errstr("TskAutoDb::startAddImage(): Already in a transaction, image might not be committed");
-         registerError();
-         return 1;
-     }
-@@ -517,7 +517,7 @@ int64_t
- TskAutoDb::commitAddImage()
- {
-     if (tsk_verbose)
--        tsk_fprintf(stderr, "TskAutoDb::commitAddImage: Commiting add image process\n");
-+        tsk_fprintf(stderr, "TskAutoDb::commitAddImage: Committing add image process\n");
- 
-     if (m_imgTransactionOpen == false) {
-         tsk_error_reset();
diff --git a/community/thttpd/discreet.patch b/community/thttpd/discreet.patch
deleted file mode 100644
index b427ecc2cb7b..000000000000
--- a/community/thttpd/discreet.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-diff -Naur old/libhttpd.c new/libhttpd.c
---- old/libhttpd.c	2012-04-27 14:24:50.971711600 +0200
-+++ new/libhttpd.c	2012-04-27 14:33:24.559135581 +0200
-@@ -744,7 +744,7 @@
-     (void) my_snprintf( buf, sizeof(buf), "\
- <HTML>\n\
- <HEAD><TITLE>%d %s</TITLE></HEAD>\n\
--<BODY BGCOLOR=\"#cc9999\" TEXT=\"#000000\" LINK=\"#2020ff\" VLINK=\"#4040cc\">\n\
-+<BODY>\n\
- <H2>%d %s</H2>\n",
- 	status, title, status, title );
-     add_response( hc, buf );
-@@ -769,11 +769,8 @@
-     char buf[1000];
- 
-     (void) my_snprintf( buf, sizeof(buf), "\
--<HR>\n\
--<ADDRESS><A HREF=\"%s\">%s</A></ADDRESS>\n\
- </BODY>\n\
--</HTML>\n",
--	SERVER_ADDRESS, EXPOSED_SERVER_SOFTWARE );
-+</HTML>\n" );
-     add_response( hc, buf );
-     }
- 
-@@ -2766,7 +2763,7 @@
- 	    (void) fprintf( fp, "\
- <HTML>\n\
- <HEAD><TITLE>Index of %.80s</TITLE></HEAD>\n\
--<BODY BGCOLOR=\"#99cc99\" TEXT=\"#000000\" LINK=\"#2020ff\" VLINK=\"#4040cc\">\n\
-+<BODY>\n\
- <H2>Index of %.80s</H2>\n\
- <PRE>\n\
- mode  links  bytes  last-changed  name\n\
diff --git a/community/thttpd/getline.patch b/community/thttpd/getline.patch
deleted file mode 100644
index 1ec3946b10d9..000000000000
--- a/community/thttpd/getline.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff -Nur thttpd-2.25b.orig/extras/htpasswd.c thttpd-2.25b/extras/htpasswd.c
---- thttpd-2.25b.orig/extras/htpasswd.c	2001-12-19 02:08:08.000000000 +0200
-+++ thttpd-2.25b/extras/htpasswd.c	2010-04-11 14:43:31.037809054 +0300
-@@ -49,7 +49,7 @@
-     while((line[y++] = line[x++]));
- }
- 
--static int getline(char *s, int n, FILE *f) {
-+static int get_line(char *s, int n, FILE *f) {
-     register int i=0;
- 
-     while(1) {
-@@ -189,7 +189,7 @@
-     strcpy(user,argv[2]);
- 
-     found = 0;
--    while(!(getline(line,MAX_STRING_LEN,f))) {
-+    while(!(get_line(line,MAX_STRING_LEN,f))) {
-         if(found || (line[0] == '#') || (!line[0])) {
-             putline(tfp,line);
-             continue;
diff --git a/community/tint2/musl-fixes.patch b/community/tint2/musl-fixes.patch
deleted file mode 100644
index 6d1aeee7b4d4..000000000000
--- a/community/tint2/musl-fixes.patch
+++ /dev/null
@@ -1,16 +0,0 @@
---- src/util/common.c.orig	2016-01-29 08:21:02.000701749 +0100
-+++ src/util/common.c	2016-01-29 08:21:49.545577920 +0100
-@@ -38,9 +38,12 @@
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <errno.h>
--#include <sys/sysctl.h>
- #include <dirent.h>
- 
-+#if !defined(__linux__) || defined(__linux__) && defined(__GLIBC__)
-+#include <sys/sysctl.h>
-+#endif
-+
- #ifdef HAVE_RSVG
- #include <librsvg/rsvg.h>
- #endif
diff --git a/community/unarj/format.patch b/community/unarj/format.patch
deleted file mode 100644
index 2c4c0ab7df52..000000000000
--- a/community/unarj/format.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-diff --git a/unarj.c b/unarj.c
-index 02b1a63..85e7b05 100644
---- a/unarj.c
-+++ b/unarj.c
-@@ -696,7 +696,7 @@ check_flags()
-     }
-     if ((arj_flags & GARBLE_FLAG) != 0)
-     {
--        printf(M_ENCRYPT);
-+        printf("%s", M_ENCRYPT);
-         printf(M_SKIPPED, filename);
-         skip();
-         return -1;
-@@ -777,7 +777,7 @@ extract()
-     }
-     printf(M_EXTRACT, name);
-     if (host_os != OS && file_type == BINARY_TYPE)
--        printf(M_DIFFHOST);
-+        printf("%s", M_DIFFHOST);
-     printf("  ");
- 
-     crc = CRC_MASK;
-@@ -793,10 +793,10 @@ extract()
-     set_ftime_mode(name, time_stamp, file_mode, (uint) host_os);
- 
-     if ((crc ^ CRC_MASK) == file_crc)
--        printf(M_CRCOK);
-+        printf("%s", M_CRCOK);
-     else
-     {
--        printf(M_CRCERROR);
-+        printf("%s", M_CRCERROR);
-         error_count++;
-     }
-     return 1;
-@@ -822,10 +822,10 @@ test()
-         decode_f();
- 
-     if ((crc ^ CRC_MASK) == file_crc)
--        printf(M_CRCOK);
-+        printf("%s", M_CRCOK);
-     else
-     {
--        printf(M_CRCERROR);
-+        printf("%s", M_CRCERROR);
-         error_count++;
-     }
-     return 1;
-@@ -972,7 +972,7 @@ help()
-     int i;
- 
-     for (i = 0; M_USAGE[i] != NULL; i++)
--        printf(M_USAGE[i]);
-+        printf("%s", M_USAGE[i]);
- }
- 
- int
-@@ -987,7 +987,7 @@ char *argv[];
-     argc = ccommand(&argv);
- #endif
- 
--    printf(M_VERSION);
-+    printf("%s", M_VERSION);
- 
-     if (argc == 1)
-     {
diff --git a/community/v4l-utils/fix-compliance.patch b/community/v4l-utils/fix-compliance.patch
deleted file mode 100644
index 34b85eeb5597..000000000000
--- a/community/v4l-utils/fix-compliance.patch
+++ /dev/null
@@ -1,77 +0,0 @@
---- a/lib/libv4l1/v4l1compat.c
-+++ b/lib/libv4l1/v4l1compat.c
-@@ -62,7 +62,7 @@
- 	return fd;
- }
- 
--#ifdef linux
-+#ifdef __GLIBC__
- LIBV4L_PUBLIC int open64(const char *file, int oflag, ...)
- {
- 	int fd;
-@@ -94,7 +94,11 @@
- 	return v4l1_dup(fd);
- }
- 
-+#ifdef __GLIBC__
- LIBV4L_PUBLIC int ioctl(int fd, unsigned long int request, ...)
-+#else
-+LIBV4L_PUBLIC int ioctl(int fd, int request, ...)
-+#endif
- {
- 	void *arg;
- 	va_list ap;
-@@ -117,7 +121,7 @@
- 	return v4l1_mmap(start, length, prot, flags, fd, offset);
- }
- 
--#ifdef linux
-+#ifdef __GLIBC__
- LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd,
- 		__off64_t offset)
- {
---- a/lib/libv4l2/v4l2convert.c
-+++ b/lib/libv4l2/v4l2convert.c
-@@ -86,7 +86,7 @@
- 	return fd;
- }
- 
--#ifdef linux
-+#ifdef __GLIBC__
- LIBV4L_PUBLIC int open64(const char *file, int oflag, ...)
- {
- 	int fd;
-@@ -121,7 +121,11 @@
- 	return v4l2_dup(fd);
- }
- 
-+#ifdef __GLIBC__
- LIBV4L_PUBLIC int ioctl(int fd, unsigned long int request, ...)
-+#else
-+LIBV4L_PUBLIC int ioctl(int fd, int request, ...)
-+#endif
- {
- 	void *arg;
- 	va_list ap;
-@@ -144,7 +148,7 @@
- 	return v4l2_mmap(start, length, prot, flags, fd, offset);
- }
- 
--#ifdef linux
-+#ifdef __GLIBC__
- LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd,
- 		__off64_t offset)
- {
---- a/lib/libv4lconvert/libv4lsyscall-priv.h
-+++ b/lib/libv4lconvert/libv4lsyscall-priv.h
-@@ -41,7 +41,9 @@
- #include <linux/ioctl.h>
- /* On 32 bits archs we always use mmap2, on 64 bits archs there is no mmap2 */
- #ifdef __NR_mmap2
-+#ifndef SYS_mmap2
- #define	SYS_mmap2 __NR_mmap2
-+#endif
- #define	MMAP2_PAGE_SHIFT 12
- #else
- #define	SYS_mmap2 SYS_mmap
- 
diff --git a/community/v4l-utils/fix-libdvbv5.patch b/community/v4l-utils/fix-libdvbv5.patch
deleted file mode 100644
index 72e169adb4df..000000000000
--- a/community/v4l-utils/fix-libdvbv5.patch
+++ /dev/null
@@ -1,19 +0,0 @@
---- a/lib/libdvbv5/dvb-dev-local.c
-+++ b/lib/libdvbv5/dvb-dev-local.c
-@@ -44,6 +44,15 @@
- # define _(string) string
- #endif
- 
-+/* taken from glibc unistd.h */
-+#ifndef TEMP_FAILURE_RETRY
-+#define TEMP_FAILURE_RETRY(expression) \
-+    ({ long int __result;                                                     \
-+       do __result = (long int) (expression);                                 \
-+       while (__result == -1L && errno == EINTR);                             \
-+       __result; })
-+#endif
-+
- struct dvb_dev_local_priv {
- 	dvb_dev_change_t notify_dev_change;
- 
-
diff --git a/community/xfce4-battery-plugin/fix-includes.patch b/community/xfce4-battery-plugin/fix-includes.patch
deleted file mode 100644
index 207ac63bdee2..000000000000
--- a/community/xfce4-battery-plugin/fix-includes.patch
+++ /dev/null
@@ -1,19 +0,0 @@
---- a/panel-plugin/libacpi.c
-+++ b/panel-plugin/libacpi.c
-@@ -29,7 +29,6 @@
- #include <sys/types.h>
- #include <dirent.h>
- #include <glob.h>
--#include <unistd.h>
- 
- #ifdef __FreeBSD__
- #include <fcntl.h>
-@@ -55,6 +54,8 @@
- #include <errno.h>
- 
- #endif
-+
-+#include <unistd.h>
- 
- #include "libacpi.h"
- 
-- 
GitLab