Skip to content
Snippets Groups Projects
Commit a10d8566 authored by Johannes Marbach's avatar Johannes Marbach
Browse files

Make keyboard more accessible

This makes the following things configurable via the config:

* keyboard background
* keyboard font size
* keycap text color
* keycap background (letters, return, other)
* text input background

Color selections were tweaked from the previous defaults to offer
more contrast, taking inspiration from common color patterns on
iOS and Android keyboards.

Hex string parsing was moved into the config class since it is
now required in a lot more places.

Closes: #96
parent 885288bc
No related branches found
No related tags found
No related merge requests found
......@@ -3,11 +3,18 @@
wallpaper = #000000
keyboard-background = #333333;
keyboard-background = #0E0E12
keyboard-map = us
keyboard-font = /usr/share/fonts/ttf-dejavu/DejaVuSans.ttf
keyboard-font-size = 24
key-foreground = #FFFFFF
key-background-letter = #5A606A
key-background-return = #003C00
key-background-other = #32363E
key-radius = 0
inputbox-background = #32363E
inputbox-radius = 0
animations = true
......@@ -24,6 +24,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <sstream>
#include <string>
argb parseHexString(const std::string &hex)
{
argb result = { 255, 0, 0, 0 };
if (sscanf(hex.c_str(), "#%02hhx%02hhx%02hhx", &result.r, &result.g, &result.b) != 3) {
fprintf(stderr, "Could not parse color code %s\n", hex.c_str());
exit(EXIT_FAILURE);
}
return result;
}
bool Config::Read(const std::string &path)
{
std::ifstream is(path, std::ifstream::binary);
......@@ -38,12 +48,14 @@ bool Config::Read(const std::string &path)
auto it = Config::options.find("wallpaper");
if (it != Config::options.end()) {
Config::wallpaper = Config::options["wallpaper"];
std::string hex = Config::options["wallpaper"];
Config::wallpaper = parseHexString(hex);
}
it = Config::options.find("keyboard-background");
if (it != Config::options.end()) {
Config::keyboardBackground = Config::options["keyboard-background"];
std::string hex = Config::options["keyboard-background"];
Config::keyboardBackground = parseHexString(hex);
}
it = Config::options.find("keyboard-font");
......@@ -51,16 +63,51 @@ bool Config::Read(const std::string &path)
Config::keyboardFont = Config::options["keyboard-font"];
}
it = Config::options.find("keyboard-font-size");
if (it != Config::options.end()) {
Config::keyboardFontSize = std::stoi(Config::options["keyboard-font-size"]);
}
it = Config::options.find("keyboard-map");
if (it != Config::options.end()) {
Config::keyboardMap = Config::options["keyboard-map"];
}
it = Config::options.find("key-foreground");
if (it != Config::options.end()) {
std::string hex = Config::options["key-foreground"];
Config::keyForeground = parseHexString(hex);
}
it = Config::options.find("key-background-letter");
if (it != Config::options.end()) {
std::string hex = Config::options["key-background-letter"];
Config::keyBackgroundLetter = parseHexString(hex);
}
it = Config::options.find("key-background-return");
if (it != Config::options.end()) {
std::string hex = Config::options["key-background-return"];
Config::keyBackgroundReturn = parseHexString(hex);
}
it = Config::options.find("key-background-other");
if (it != Config::options.end()) {
std::string hex = Config::options["key-background-other"];
Config::keyBackgroundOther = parseHexString(hex);
}
it = Config::options.find("key-radius");
if (it != Config::options.end()) {
Config::keyRadius = Config::options["key-radius"];
}
it = Config::options.find("inputbox-background");
if (it != Config::options.end()) {
std::string hex = Config::options["inputbox-background"];
Config::inputBoxBackground = parseHexString(hex);
}
it = Config::options.find("inputbox-radius");
if (it != Config::options.end()) {
Config::inputBoxRadius = Config::options["inputbox-radius"];
......
......@@ -22,14 +22,34 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <map>
#include <string>
struct argb {
unsigned char a;
unsigned char r;
unsigned char g;
unsigned char b;
};
/**
Convert color hex string into ARGB
@hex 6-character hex string with leading #
@return ARGB structure to write the extracted values into
*/
argb parseHexString(const std::string &hex);
class Config {
public:
std::string keyboardBackground = "#333333";
std::string wallpaper = "#FF9900";
argb wallpaper = parseHexString("#000000");
argb keyboardBackground = parseHexString("#0E0E12");
std::string keyboardFont = "DejaVu";
int keyboardFontSize = 24;
std::string keyboardMap = "us";
std::string inputBoxRadius = "0";
argb keyForeground = parseHexString("#FFFFFF");
argb keyBackgroundLetter = parseHexString("#5A606A");
argb keyBackgroundReturn = parseHexString("#003C00");
argb keyBackgroundOther = parseHexString("#32363E");
std::string keyRadius = "0";
argb inputBoxBackground = parseHexString("#32363E");
std::string inputBoxRadius = "0";
bool animations = true;
/**
......
......@@ -68,14 +68,6 @@ void Keyboard::setTargetPosition(float p)
targetPosition = p;
}
void Keyboard::setKeyboardColor(uint8_t a, uint8_t r, uint8_t g, uint8_t b)
{
keyboardColor.a = a;
keyboardColor.r = r;
keyboardColor.g = g;
keyboardColor.b = b;
}
void Keyboard::updateAnimations()
{
const int animStep = 20; // 20ms -> 50 FPS
......@@ -133,7 +125,7 @@ void Keyboard::draw(SDL_Renderer *renderer, int screenHeight)
srcRect.w = keyboardWidth;
srcRect.h = keyboardRect.h;
SDL_SetRenderDrawColor(renderer, keyboardColor.r, keyboardColor.g, keyboardColor.b, keyboardColor.a);
SDL_SetRenderDrawColor(renderer, config->keyboardBackground.r, config->keyboardBackground.g, config->keyboardBackground.b, config->keyboardBackground.a);
for (const auto &layer : keyboard) {
if (layer.layerNum == activeLayer) {
......@@ -150,10 +142,10 @@ bool Keyboard::isInSlideAnimation() const
void Keyboard::drawRow(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 keyBackground = SDL_MapRGB(surface->format, config->keyBackgroundLetter.r, config->keyBackgroundLetter.g, config->keyBackgroundLetter.b);
SDL_Color textColor = { config->keyForeground.r, config->keyForeground.g, config->keyForeground.b, config->keyForeground.a };
auto background = SDL_MapRGB(surface->format, keyboardColor.r, keyboardColor.g, keyboardColor.b);
auto background = SDL_MapRGB(surface->format, config->keyboardBackground.r, config->keyboardBackground.g, config->keyboardBackground.b);
int i = 0;
for (const auto &keyCap : keys) {
SDL_Rect keyRect;
......@@ -182,10 +174,10 @@ void Keyboard::drawRow(SDL_Surface *surface, std::vector<touchArea> &keyVector,
}
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
char *cap, const char *key, int padding, TTF_Font *font, argb background) const
{
auto keyBackground = SDL_MapRGB(surface->format, 15, 15, 15);
SDL_Color textColor = { 255, 255, 255, 0 };
auto keyBackground = SDL_MapRGB(surface->format, background.r, background.g, background.b);
SDL_Color textColor = { config->keyForeground.r, config->keyForeground.g, config->keyForeground.b, config->keyForeground.a };
SDL_Rect keyRect;
keyRect.x = x + padding;
......@@ -235,7 +227,7 @@ SDL_Surface *Keyboard::makeKeyboard(KeyboardLayer *layer) const
}
SDL_FillRect(surface, nullptr,
SDL_MapRGB(surface->format, keyboardColor.r, keyboardColor.g, keyboardColor.b));
SDL_MapRGB(surface->format, config->keyboardBackground.r, config->keyboardBackground.g, config->keyboardBackground.b));
int rowCount = layer->rows.size();
int rowHeight = keyboardHeight / (rowCount + 1);
......@@ -245,7 +237,7 @@ SDL_Surface *Keyboard::makeKeyboard(KeyboardLayer *layer) const
return nullptr;
}
TTF_Font *font = TTF_OpenFont(config->keyboardFont.c_str(), 24);
TTF_Font *font = TTF_OpenFont(config->keyboardFont.c_str(), config->keyboardFontSize);
if (!font) {
printf("TTF_OpenFont: %s\n", TTF_GetError());
return nullptr;
......@@ -274,29 +266,29 @@ SDL_Surface *Keyboard::makeKeyboard(KeyboardLayer *layer) const
if (layer->layerNum < 2) {
char nums[] = "123";
drawKey(surface, layer->keyVector, colw, y, colw * 3, rowHeight,
nums, KEYCAP_NUMBERS, keyboardWidth / 100, font);
nums, KEYCAP_NUMBERS, keyboardWidth / 100, font, config->keyBackgroundOther);
} else {
char abc[] = "abc";
drawKey(surface, layer->keyVector, colw, y, colw * 3, rowHeight,
abc, KEYCAP_ABC, keyboardWidth / 100, font);
abc, KEYCAP_ABC, keyboardWidth / 100, font, config->keyBackgroundOther);
}
/* Shift-key that transforms into "123" or "=\<" depending on layer: */
if (layer->layerNum == 2) {
char symb[] = "=\\<";
drawKey(surface, layer->keyVector, 0, y - rowHeight,
sidebuttonsWidth, rowHeight,
symb, KEYCAP_SYMBOLS, keyboardWidth / 100, font);
symb, KEYCAP_SYMBOLS, keyboardWidth / 100, font, config->keyBackgroundOther);
} else if (layer->layerNum == 3) {
char nums[] = "123";
drawKey(surface, layer->keyVector, 0, y - rowHeight,
sidebuttonsWidth, rowHeight,
nums, KEYCAP_NUMBERS, keyboardWidth / 100, font);
nums, KEYCAP_NUMBERS, keyboardWidth / 100, font, config->keyBackgroundOther);
} else {
char shift[64] = "";
memcpy(shift, KEYCAP_SHIFT, strlen(KEYCAP_SHIFT) + 1);
drawKey(surface, layer->keyVector, 0, y - rowHeight,
sidebuttonsWidth, rowHeight,
shift, KEYCAP_SHIFT, keyboardWidth / 100, font);
shift, KEYCAP_SHIFT, keyboardWidth / 100, font, config->keyBackgroundOther);
}
/* Backspace key that is larger-sized (hence also drawn separately) */
{
......@@ -305,20 +297,20 @@ SDL_Surface *Keyboard::makeKeyboard(KeyboardLayer *layer) const
strlen(KEYCAP_BACKSPACE) + 1);
drawKey(surface, layer->keyVector, keyboardWidth / 20 + colw * 16,
y - rowHeight, sidebuttonsWidth, rowHeight,
bcksp, KEYCAP_BACKSPACE, keyboardWidth / 100, font);
bcksp, KEYCAP_BACKSPACE, keyboardWidth / 100, font, config->keyBackgroundOther);
}
char space[] = " ";
drawKey(surface, layer->keyVector, colw * 5, y, colw * 8, rowHeight,
space, KEYCAP_SPACE, keyboardWidth / 100, font);
space, KEYCAP_SPACE, keyboardWidth / 100, font, config->keyBackgroundLetter);
char period[] = ".";
drawKey(surface, layer->keyVector, colw * 13, y, colw * 2, rowHeight,
period, KEYCAP_PERIOD, keyboardWidth / 100, font);
period, KEYCAP_PERIOD, keyboardWidth / 100, font, config->keyBackgroundOther);
char enter[] = "OK";
drawKey(surface, layer->keyVector, colw * 15, y, colw * 5, rowHeight,
enter, KEYCAP_RETURN, keyboardWidth / 100, font);
enter, KEYCAP_RETURN, keyboardWidth / 100, font, config->keyBackgroundReturn);
return surface;
}
......
......@@ -51,13 +51,6 @@ struct rgb {
unsigned char b;
};
struct argb {
unsigned char a;
unsigned char r;
unsigned char g;
unsigned char b;
};
struct KeyboardLayer {
SDL_Surface *surface = nullptr;
SDL_Texture *texture = nullptr;
......@@ -85,14 +78,6 @@ public:
@return String with value of key at the given coordinates
*/
std::string getCharForCoordinates(int x, int y);
/**
Set keyboard color
@param a Alpha value
@param r Red value
@param g Green value
@param b Blue value
*/
void setKeyboardColor(uint8_t a, uint8_t r, uint8_t g, uint8_t b);
/**
Get position of keyboard
@return Position as a value between 0 and 1 (0% and 100%)
......@@ -141,7 +126,6 @@ public:
bool isInSlideAnimation() const;
private:
argb keyboardColor = { 0, 0, 0, 0 };
int keyRadius = 0;
float position;
float targetPosition;
......@@ -187,9 +171,10 @@ private:
@param key Key text
@param padding Spacing to reserve around the key
@param font Font to use for key character
@param background Background color for the keycap
*/
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;
int width, int height, char *cap, const char *key, int padding, TTF_Font *font, argb background) const;
/**
Prepare new keyboard
@param layer Keyboard layer to use
......
......@@ -140,7 +140,6 @@ int main(int argc, char **args)
// Initialize virtual keyboard
Keyboard keyboard(0, 1, WIDTH, keyboardHeight, &config);
keyboard.setKeyboardColor(0, 30, 30, 30);
if (keyboard.init(renderer)) {
fprintf(stderr, "ERROR: Failed to initialize keyboard!\n");
atexit(SDL_Quit);
......@@ -170,17 +169,8 @@ int main(int argc, char **args)
inputHeight / 1.5, inputBoxRadius);
inputBoxRadius = 0;
}
argb wallpaperColor {};
wallpaperColor.a = 255;
if (sscanf(config.wallpaper.c_str(), "#%02hhx%02hhx%02hhx", &wallpaperColor.r, &wallpaperColor.g,
&wallpaperColor.b)
!= 3) {
fprintf(stderr, "Could not parse color code %s\n", config.wallpaper.c_str());
//to avoid akward colors just remove the radius
inputBoxRadius = 0;
}
argb inputBoxColor = argb { 255, 30, 30, 30 };
argb inputBoxColor = config.inputBoxBackground;
SDL_Surface *inputBox = make_input_box(static_cast<int>(WIDTH * 0.9), inputHeight, &inputBoxColor, inputBoxRadius);
SDL_Texture *inputBoxTexture = SDL_CreateTextureFromSurface(renderer, inputBox);
......
......@@ -51,7 +51,7 @@ int Tooltip::init(SDL_Renderer *renderer, const std::string &text)
}
SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, 30, 30, 30));
TTF_Font *font = TTF_OpenFont(config->keyboardFont.c_str(), 24);
TTF_Font *font = TTF_OpenFont(config->keyboardFont.c_str(), config->keyboardFontSize);
SDL_Surface *textSurface;
SDL_Color textColor = { 255, 255, 255, 0 };
textSurface = TTF_RenderText_Blended(font, text.c_str(), textColor);
......
......@@ -98,19 +98,7 @@ SDL_Surface *make_wallpaper(Config *config, int width, int height)
#endif
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, rmask, gmask, bmask, amask);
if (config->wallpaper[0] == '#') {
unsigned char r, g, b;
if (sscanf(config->wallpaper.c_str(), "#%02hhx%02hhx%02hhx", &r, &g, &b) != 3) {
fprintf(stderr, "Could not parse color code %s\n", config->wallpaper.c_str());
exit(EXIT_FAILURE);
}
SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, r, g, b));
} else {
// Implement image loading
fprintf(stderr, "Image loading not supported yet\n");
exit(EXIT_FAILURE);
}
SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, config->wallpaper.r, config->wallpaper.g, config->wallpaper.b));
return surface;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment