diff --git a/src/keyboard.cpp b/src/keyboard.cpp
index 1256e72b3c0646e343321fffd6fc91553772cdb7..e9e25f1f36604349e6db8aee9b87cc0b0cd0da37 100644
--- a/src/keyboard.cpp
+++ b/src/keyboard.cpp
@@ -21,11 +21,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "keyboard.h"
 #include "draw_helpers.h"
 
-Keyboard::Keyboard(int pos, int targetPos, int width, int height, Config *config)
+Keyboard::Keyboard(int pos, int targetPos, int width, int height, Uint32 format, Config *config)
 	: position(static_cast<float>(pos))
 	, targetPosition(static_cast<float>(targetPos))
 	, keyboardWidth(width)
 	, keyboardHeight(height)
+	, format(format)
 	, config(config)
 {
 	lastAnimTicks = SDL_GetTicks();
@@ -33,6 +34,15 @@ Keyboard::Keyboard(int pos, int targetPos, int width, int height, Config *config
 
 int Keyboard::init(SDL_Renderer *renderer)
 {
+	if (TTF_Init() == -1) {
+		fprintf(stderr, "ERROR: Unable to init TTF: %s\n", TTF_GetError());
+		return 1;
+	}
+	font = TTF_OpenFont(config->keyboardFont.c_str(), 24);
+	if (!font) {
+		fprintf(stderr, "ERROR: Unable to load font: %s\n", TTF_GetError());
+		return 1;
+	}
 	loadKeymap();
 	int keyLong = std::strtol(config->keyRadius.c_str(), nullptr, 10);
 	if (keyLong >= BEZIER_RESOLUTION || static_cast<double>(keyLong) > (keyboardHeight / 5.0) / 1.5) {
@@ -48,11 +58,21 @@ int Keyboard::init(SDL_Renderer *renderer)
 			fprintf(stderr, "ERROR: Unable to generate keyboard surface\n");
 			return 1;
 		}
-		layer.texture = SDL_CreateTextureFromSurface(renderer, layer.surface);
+		layer.texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STREAMING, layer.surface->w, layer.surface->h);
 		if (!layer.texture) {
 			fprintf(stderr, "ERROR: Unable to generate keyboard texture\n");
 			return 1;
 		}
+		SDL_Surface *formattedSurface = SDL_ConvertSurfaceFormat(layer.surface, format, 0);
+		if (!formattedSurface) {
+			fprintf(stderr, "ERROR: Unable to convert surface into window pixel format\n");
+			return 1;
+		}
+		void *pixels;
+		int pitch;
+		SDL_LockTexture(layer.texture, nullptr, &pixels, &pitch);
+		memcpy(pixels, formattedSurface->pixels, formattedSurface->pitch * formattedSurface->h);
+		SDL_UnlockTexture(layer.texture);
 	}
 	lastAnimTicks = SDL_GetTicks();
 	return 0;
@@ -147,45 +167,31 @@ bool Keyboard::isInSlideAnimation() const
 	return (fabs(getTargetPosition() - getPosition()) > 0.001);
 }
 
-void Keyboard::drawRow(SDL_Surface *surface, std::vector<touchArea> &keyVector, int x, int y, int width, int height,
+void Keyboard::drawAndStoreRow(SDL_Surface *surface, std::vector<touchArea> &keyVector, int x, int y, int width, int height,
 	const std::vector<std::string> &keys, int padding, TTF_Font *font) const
 {
-	auto keyBackground = SDL_MapRGB(surface->format, 15, 15, 15);
-	SDL_Color textColor = { 255, 255, 255, 0 };
-
-	auto background = SDL_MapRGB(surface->format, keyboardColor.r, keyboardColor.g, keyboardColor.b);
 	int i = 0;
 	for (const auto &keyCap : keys) {
-		SDL_Rect keyRect;
-		keyRect.x = x + (i * width) + padding;
-		keyRect.y = y + padding;
-		keyRect.w = width - (2 * padding);
-		keyRect.h = height - (2 * padding);
-		SDL_FillRect(surface, &keyRect, keyBackground);
-		if (keyRadius > 0) {
-			smooth_corners_surface(surface, background, &keyRect, keyRadius);
-		}
-		SDL_Surface *textSurface;
-		keyVector.push_back({ keyCap, x + (i * width), x + (i * width) + width, y, y + height });
-
-		textSurface = TTF_RenderUTF8_Blended(font, keyCap.c_str(), textColor);
-
-		SDL_Rect keyCapRect;
-		keyCapRect.x = keyRect.x + ((keyRect.w / 2) - (textSurface->w / 2));
-		keyCapRect.y = keyRect.y + ((keyRect.h / 2) - (textSurface->h / 2));
-		keyCapRect.w = keyRect.w;
-		keyCapRect.h = keyRect.h;
-		SDL_BlitSurface(textSurface, nullptr, surface, &keyCapRect);
-
+		const char *key = keyCap.c_str();
+		drawAndStoreKey(surface, keyVector, x + (i * width), y, width, height, key, key, padding, font);
 		i++;
 	}
 }
 
-void Keyboard::drawKey(SDL_Surface *surface, std::vector<touchArea> &keyVector, int x, int y, int width, int height,
-	char *cap, const char *key, int padding, TTF_Font *font) const
+void Keyboard::drawAndStoreKey(SDL_Surface *surface, std::vector<touchArea> &keyVector, int x, int y, int width, int height,
+	const char *cap, const char *key, int padding, TTF_Font *font) const
+{
+	drawKey(surface, x, y, width, height, cap, padding, font, false);
+	keyVector.push_back({ key, x, x + width, y, y + height });
+}
+
+void Keyboard::drawKey(SDL_Surface *surface, int x, int y, int width, int height,
+	const char *cap, int padding, TTF_Font *font, bool selected) const
 {
-	auto keyBackground = SDL_MapRGB(surface->format, 15, 15, 15);
-	SDL_Color textColor = { 255, 255, 255, 0 };
+	auto keyBackground = selected ? SDL_MapRGB(surface->format, 255, 255, 255) : SDL_MapRGB(surface->format, 15, 15, 15);
+	SDL_Color textColor = selected ? (SDL_Color) { 15, 15, 15, 0 } : (SDL_Color) { 255, 255, 255, 0 };
+
+	auto background = SDL_MapRGB(surface->format, keyboardColor.r, keyboardColor.g, keyboardColor.b);
 
 	SDL_Rect keyRect;
 	keyRect.x = x + padding;
@@ -193,10 +199,11 @@ void Keyboard::drawKey(SDL_Surface *surface, std::vector<touchArea> &keyVector,
 	keyRect.w = width - (2 * padding);
 	keyRect.h = height - (2 * padding);
 	SDL_FillRect(surface, &keyRect, keyBackground);
+	if (keyRadius > 0) {
+		smooth_corners_surface(surface, background, &keyRect, keyRadius);
+	}
 	SDL_Surface *textSurface;
 
-	keyVector.push_back({ key, x, x + width, y, y + height });
-
 	textSurface = TTF_RenderUTF8_Blended(font, cap, textColor);
 
 	SDL_Rect keyCapRect;
@@ -240,17 +247,6 @@ SDL_Surface *Keyboard::makeKeyboard(KeyboardLayer *layer) const
 	int rowCount = layer->rows.size();
 	int rowHeight = keyboardHeight / (rowCount + 1);
 
-	if (TTF_Init() == -1) {
-		printf("TTF_Init: %s\n", TTF_GetError());
-		return nullptr;
-	}
-
-	TTF_Font *font = TTF_OpenFont(config->keyboardFont.c_str(), 24);
-	if (!font) {
-		printf("TTF_OpenFont: %s\n", TTF_GetError());
-		return nullptr;
-	}
-
 	// Divide the bottom row in 20 columns and use that for calculations
 	int colw = keyboardWidth / 20;
 
@@ -264,7 +260,7 @@ SDL_Surface *Keyboard::makeKeyboard(KeyboardLayer *layer) const
 			x = keyboardWidth / 20;
 		if (i == 2) /* leave room for shift, "123" or "=\<" key */
 			x = keyboardWidth / 20 + colw * 2;
-		drawRow(surface, layer->keyVector, x, y, keyboardWidth / 10,
+		drawAndStoreRow(surface, layer->keyVector, x, y, keyboardWidth / 10,
 			rowHeight, layer->rows[i], keyboardWidth / 100, font);
 		y += rowHeight;
 		i++;
@@ -273,28 +269,28 @@ SDL_Surface *Keyboard::makeKeyboard(KeyboardLayer *layer) const
 	/* Bottom-left key, 123 or ABC key based on which layer we're on: */
 	if (layer->layerNum < 2) {
 		char nums[] = "123";
-		drawKey(surface, layer->keyVector, colw, y, colw * 3, rowHeight,
+		drawAndStoreKey(surface, layer->keyVector, colw, y, colw * 3, rowHeight,
 			nums, KEYCAP_NUMBERS, keyboardWidth / 100, font);
 	} else {
 		char abc[] = "abc";
-		drawKey(surface, layer->keyVector, colw, y, colw * 3, rowHeight,
+		drawAndStoreKey(surface, layer->keyVector, colw, y, colw * 3, rowHeight,
 			abc, KEYCAP_ABC, keyboardWidth / 100, font);
 	}
 	/* Shift-key that transforms into "123" or "=\<" depending on layer: */
 	if (layer->layerNum == 2) {
 		char symb[] = "=\\<";
-		drawKey(surface, layer->keyVector, 0, y - rowHeight,
+		drawAndStoreKey(surface, layer->keyVector, 0, y - rowHeight,
 			sidebuttonsWidth, rowHeight,
 			symb, KEYCAP_SYMBOLS, keyboardWidth / 100, font);
 	} else if (layer->layerNum == 3) {
 		char nums[] = "123";
-		drawKey(surface, layer->keyVector, 0, y - rowHeight,
+		drawAndStoreKey(surface, layer->keyVector, 0, y - rowHeight,
 			sidebuttonsWidth, rowHeight,
 			nums, KEYCAP_NUMBERS, keyboardWidth / 100, font);
 	} else {
 		char shift[64] = "";
 		memcpy(shift, KEYCAP_SHIFT, strlen(KEYCAP_SHIFT) + 1);
-		drawKey(surface, layer->keyVector, 0, y - rowHeight,
+		drawAndStoreKey(surface, layer->keyVector, 0, y - rowHeight,
 			sidebuttonsWidth, rowHeight,
 			shift, KEYCAP_SHIFT, keyboardWidth / 100, font);
 	}
@@ -303,21 +299,21 @@ SDL_Surface *Keyboard::makeKeyboard(KeyboardLayer *layer) const
 		char bcksp[64];
 		memcpy(bcksp, KEYCAP_BACKSPACE,
 			strlen(KEYCAP_BACKSPACE) + 1);
-		drawKey(surface, layer->keyVector, keyboardWidth / 20 + colw * 16,
+		drawAndStoreKey(surface, layer->keyVector, keyboardWidth / 20 + colw * 16,
 			y - rowHeight, sidebuttonsWidth, rowHeight,
 			bcksp, KEYCAP_BACKSPACE, keyboardWidth / 100, font);
 	}
 
 	char space[] = " ";
-	drawKey(surface, layer->keyVector, colw * 5, y, colw * 8, rowHeight,
+	drawAndStoreKey(surface, layer->keyVector, colw * 5, y, colw * 8, rowHeight,
 		space, KEYCAP_SPACE, keyboardWidth / 100, font);
 
 	char period[] = ".";
-	drawKey(surface, layer->keyVector, colw * 13, y, colw * 2, rowHeight,
+	drawAndStoreKey(surface, layer->keyVector, colw * 13, y, colw * 2, rowHeight,
 		period, KEYCAP_PERIOD, keyboardWidth / 100, font);
 
 	char enter[] = "OK";
-	drawKey(surface, layer->keyVector, colw * 15, y, colw * 5, rowHeight,
+	drawAndStoreKey(surface, layer->keyVector, colw * 15, y, colw * 5, rowHeight,
 		enter, KEYCAP_RETURN, keyboardWidth / 100, font);
 
 	return surface;
@@ -378,16 +374,39 @@ void Keyboard::loadKeymap()
 	keyboard.push_back(layer3);
 }
 
-std::string Keyboard::getCharForCoordinates(int x, int y)
+touchArea Keyboard::getKeyForCoordinates(int x, int y)
 {
 	for (const auto &layer : keyboard) {
 		if (layer.layerNum == activeLayer) {
 			for (const auto &it : layer.keyVector) {
 				if (x > it.x1 && x < it.x2 && y > it.y1 && y < it.y2) {
-					return it.keyChar;
+					return it;
 				}
 			}
 		}
 	}
-	return "";
+	return { "", 0, 0, 0, 0 };
+}
+
+void Keyboard::selectKey(touchArea area, bool selected)
+{
+	for (const auto &layer : keyboard) {
+		if (layer.layerNum != activeLayer) {
+			continue;
+		}
+
+		drawKey(layer.surface, area.x1, area.y1, area.x2 - area.x1, area.y2 - area.y1,
+			area.keyChar.c_str(), keyboardWidth / 100, font, selected);
+
+		SDL_Surface *formattedSurface = SDL_ConvertSurfaceFormat(layer.surface, format, 0);
+		if (!formattedSurface) {
+			fprintf(stderr, "ERROR: Unable to convert surface into window pixel format\n");
+		}
+
+		void *pixels;
+		int pitch;
+		SDL_LockTexture(layer.texture, nullptr, &pixels, &pitch);
+		memcpy(pixels, formattedSurface->pixels, formattedSurface->pitch * formattedSurface->h);
+		SDL_UnlockTexture(layer.texture);
+	}
 }
diff --git a/src/keyboard.h b/src/keyboard.h
index 4e757cf94d59c1a60793c9f61e5d0d932c05b537..7aeb0314365f6d2e011af7356f6478bb42b7f2c8 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -75,16 +75,23 @@ public:
 	  @param targetPos Final position (e.g. 1 for max height)
 	  @param width Width to draw keyboard
 	  @param height Height to draw keyboard
+	  @param format SDL_PixelFormatEnum value of the window
 	  @param config Pointer to Config
 	  */
-	Keyboard(int pos, int targetPos, int width, int height, Config *config);
+	Keyboard(int pos, int targetPos, int width, int height, Uint32 format, Config *config);
 	/**
 	  Get the character/key at the given coordinates
 	  @param x X-axis coordinate
 	  @param y Y-axis coordinate
-	  @return String with value of key at the given coordinates
+	  @return Touch area for the key at the given coordinates. When no key is found, keyChar will be an empty string.
 	  */
-	std::string getCharForCoordinates(int x, int y);
+	touchArea getKeyForCoordinates(int x, int y);
+	/**
+	  Select / unselect a specific key
+	  @param area Touch area of the key
+	  @param selected Whether to select or unselect the key
+	  */
+	void selectKey(touchArea area, bool selected);
 	/**
 	  Set keyboard color
 	  @param a Alpha value
@@ -150,10 +157,12 @@ private:
 	int keyboardHeight;
 	int activeLayer = 0;
 	std::vector<KeyboardLayer> keyboard;
+	Uint32 format;
 	Config *config;
+	TTF_Font *font = nullptr;
 
 	/**
-	  Draw keyboard row
+	  Draw and store keyboard row
 	  @param surface Surface to draw on
 	  @param keyList List of keys for keyboard layout
 	  @param x X-axis coord. for start of row
@@ -165,7 +174,7 @@ private:
 	  @param padding Spacing to reserve around the key
 	  @param font Font to use for key character
 	  */
-	void drawRow(SDL_Surface *surface, std::vector<touchArea> &keyVector, int x, int y,
+	void drawAndStoreRow(SDL_Surface *surface, std::vector<touchArea> &keyVector, int x, int y,
 		int width, int height, const std::vector<std::string> &keys, int padding,
 		TTF_Font *font) const;
 
@@ -176,9 +185,9 @@ private:
 	void updateAnimations();
 
 	/**
-	  Draw key for keyboard
+	  Draw and store key for keyboard
 	  @param surface Surface to draw on
-	  @param keyList List of keys for keyboard layout
+	  @param keyVector List of keys for keyboard layout
 	  @param x X-axis coord. for start of row
 	  @param y Y-axis coord. for start of row
 	  @param width Width of row
@@ -188,8 +197,24 @@ private:
 	  @param padding Spacing to reserve around the key
 	  @param font Font to use for key character
 	  */
-	void drawKey(SDL_Surface *surface, std::vector<touchArea> &keyVector, int x, int y,
-		int width, int height, char *cap, const char *key, int padding, TTF_Font *font) const;
+	void drawAndStoreKey(SDL_Surface *surface, std::vector<touchArea> &keyVector, int x, int y,
+		int width, int height, const char *cap, const char *key, int padding, TTF_Font *font) const;
+
+	/**
+	  Draw key for keyboard
+	  @param surface Surface to draw on
+	  @param x X-axis coord. for start of row
+	  @param y Y-axis coord. for start of row
+	  @param width Width of row
+	  @param height Height of row
+	  @param cap Key cap
+	  @param padding Spacing to reserve around the key
+	  @param font Font to use for key character
+		@param bool Whether the key is selected or not
+	  */
+	void drawKey(SDL_Surface *surface, int x, int y, int width, int height, const char *cap,
+		int padding, TTF_Font *font, bool selected) const;
+
 	/**
 	  Prepare new keyboard
 	  @param layer Keyboard layer to use
diff --git a/src/main.cpp b/src/main.cpp
index 12c1988ece8dc9c0c506f8090a2cd383e78d6c43..5fbf313d13a9097a12e49449a4976bbfaf1684ce 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -139,7 +139,7 @@ int main(int argc, char **args)
 	}
 
 	// Initialize virtual keyboard
-	Keyboard keyboard(0, 1, WIDTH, keyboardHeight, &config);
+	Keyboard keyboard(0, 1, WIDTH, keyboardHeight, SDL_GetWindowPixelFormat(display), &config);
 	keyboard.setKeyboardColor(0, 30, 30, 30);
 	if (keyboard.init(renderer)) {
 		fprintf(stderr, "ERROR: Failed to initialize keyboard!\n");
@@ -208,6 +208,7 @@ int main(int argc, char **args)
 
 	// The Main Loop.
 	bool done = false;
+	touchArea selectedKey = { "", 0, 0, 0, 0 };
 	while (luksDev.isLocked() && !done) {
 		if (SDL_WaitEvent(&event)) {
 			int cur_ticks = SDL_GetTicks();
@@ -247,6 +248,22 @@ int main(int argc, char **args)
 				SDL_PushEvent(&renderEvent);
 				break; // SDL_KEYDOWN
 				// handle touchscreen
+			case SDL_FINGERDOWN: {
+				// x and y values are normalized!
+				auto xTouch = static_cast<unsigned>(event.tfinger.x * WIDTH);
+				auto yTouch = static_cast<unsigned>(event.tfinger.y * HEIGHT);
+				if (opts.verbose) {
+					printf("xTouch: %u\tyTouch: %u\n", xTouch, yTouch);
+				}
+				auto offsetYTouch = yTouch - static_cast<int>(HEIGHT - (keyboard.getHeight() * keyboard.getPosition()));
+				auto key = keyboard.getKeyForCoordinates(xTouch, offsetYTouch);
+				if (key.keyChar.length() > 0) {
+					keyboard.selectKey(key, true);
+					selectedKey = key;
+				}
+				SDL_PushEvent(&renderEvent);
+				break; // SDL_FINGERDOWN
+			}
 			case SDL_FINGERUP: {
 				showPasswordError = false;
 				// x and y values are normalized!
@@ -256,7 +273,11 @@ int main(int argc, char **args)
 					printf("xTouch: %u\tyTouch: %u\n", xTouch, yTouch);
 				}
 				auto offsetYTouch = yTouch - static_cast<int>(HEIGHT - (keyboard.getHeight() * keyboard.getPosition()));
-				tapped = keyboard.getCharForCoordinates(xTouch, offsetYTouch);
+				auto key = keyboard.getKeyForCoordinates(xTouch, offsetYTouch);
+				if (selectedKey.keyChar.length() > 0) {
+					keyboard.selectKey(selectedKey, false);
+				}
+				tapped = key.keyChar;
 				if (!luksDev.unlockRunning()) {
 					done = handleVirtualKeyPress(tapped, keyboard, luksDev, passphrase, opts.keyscript);
 				}
@@ -264,6 +285,21 @@ int main(int argc, char **args)
 				break; // SDL_FINGERUP
 			}
 				// handle the mouse
+			case SDL_MOUSEBUTTONDOWN: {
+				auto xMouse = event.button.x;
+				auto yMouse = event.button.y;
+				if (opts.verbose) {
+					printf("xMouse: %u\tyMouse: %u\n", xMouse, yMouse);
+				}
+				auto offsetYMouse = yMouse - static_cast<int>(HEIGHT - (keyboard.getHeight() * keyboard.getPosition()));
+				auto key = keyboard.getKeyForCoordinates(xMouse, offsetYMouse);
+				if (key.keyChar.length() > 0) {
+					keyboard.selectKey(key, true);
+					selectedKey = key;
+				}
+				SDL_PushEvent(&renderEvent);
+				break; // SDL_MOUSEBUTTONDOWN
+			}
 			case SDL_MOUSEBUTTONUP: {
 				showPasswordError = false;
 				auto xMouse = event.button.x;
@@ -272,7 +308,11 @@ int main(int argc, char **args)
 					printf("xMouse: %u\tyMouse: %u\n", xMouse, yMouse);
 				}
 				auto offsetYMouse = yMouse - static_cast<int>(HEIGHT - (keyboard.getHeight() * keyboard.getPosition()));
-				tapped = keyboard.getCharForCoordinates(xMouse, offsetYMouse);
+				auto key = keyboard.getKeyForCoordinates(xMouse, offsetYMouse);
+				if (selectedKey.keyChar.length() > 0) {
+					keyboard.selectKey(selectedKey, false);
+				}
+				tapped = key.keyChar;
 				if (!luksDev.unlockRunning()) {
 					done = handleVirtualKeyPress(tapped, keyboard, luksDev, passphrase, opts.keyscript);
 				}