From f595754f91c916a57ac564fd5d48e53df5d8d3ba Mon Sep 17 00:00:00 2001 From: Johannes Marbach <n0-0ne+gitlab@mailbox.org> Date: Mon, 30 Nov 2020 11:12:57 +0100 Subject: [PATCH] Make keyboard more accessible (MR #105) 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 --- osk.conf | 9 ++++++++- src/config.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++-- src/config.h | 26 +++++++++++++++++++++--- src/keyboard.cpp | 44 +++++++++++++++++------------------------ src/keyboard.h | 19 ++---------------- src/main.cpp | 12 +----------- src/tooltip.cpp | 2 +- src/util.cpp | 14 +------------ 8 files changed, 103 insertions(+), 74 deletions(-) diff --git a/osk.conf b/osk.conf index e74f6cb..2551287 100644 --- a/osk.conf +++ b/osk.conf @@ -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 diff --git a/src/config.cpp b/src/config.cpp index 650677d..110210a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -25,6 +25,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) { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not parse color code %s", hex.c_str()); + exit(EXIT_FAILURE); + } + return result; +} + bool Config::Read(const std::string &path) { std::ifstream is(path, std::ifstream::binary); @@ -39,12 +49,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"); @@ -52,16 +64,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"]; diff --git a/src/config.h b/src/config.h index 9487d0d..b35ac7e 100644 --- a/src/config.h +++ b/src/config.h @@ -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; /** diff --git a/src/keyboard.cpp b/src/keyboard.cpp index 5dbd96c..2ff6249 100644 --- a/src/keyboard.cpp +++ b/src/keyboard.cpp @@ -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) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "TTF_OpenFont: %s", 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; } diff --git a/src/keyboard.h b/src/keyboard.h index 4e757cf..691b1b4 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -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 diff --git a/src/main.cpp b/src/main.cpp index 73673da..97c85b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -141,7 +141,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)) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Failed to initialize keyboard!"); atexit(SDL_Quit); @@ -175,17 +174,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) { - SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Could not parse color code %s", 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); diff --git a/src/tooltip.cpp b/src/tooltip.cpp index cfdd184..c1ae577 100644 --- a/src/tooltip.cpp +++ b/src/tooltip.cpp @@ -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); diff --git a/src/util.cpp b/src/util.cpp index df5fc7f..16bef65 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -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) { - SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Could not parse color code %s", config->wallpaper.c_str()); - exit(EXIT_FAILURE); - } - SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, r, g, b)); - } else { - // Implement image loading - SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Image loading not supported yet"); - exit(EXIT_FAILURE); - } + SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, config->wallpaper.r, config->wallpaper.g, config->wallpaper.b)); return surface; } -- GitLab