/* * Matchbox Keyboard - A lightweight software keyboard. * * Authored By Matthew Allum * Tomas Frydrych * * Copyright (c) 2005-2012 Intel Corp * Copyright (c) 2012 Vernier Software & Technology * * SPDX-License-Identifier: LGPL-2.1 * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "matchbox-keyboard.h" #ifdef WANT_CAIRO #include "matchbox-keyboard-popup.h" #endif #define FONT_FAMILY_LEN 100 #define MB_KB_CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) Display *mb_xdpy = NULL; int mb_xscreen = 0; Window mb_xroot = None; static void mb_kbd_usage (char *progname) { fprintf(stderr, "Usage:\n %s [Options ] [ Layout Variant ]\n", progname); fprintf(stderr, "\nOptions are;\n" " -xid,--xid Print window ID to stdout ( for embedding )\n" " -d,--daemon Run in 'daemon' mode (for remote control)\n" " -o,--orientation \n" " Use to limit visibility with screen orientation \n" " --fontfamily \n" " Colon (:) delimited list of font family descriptor to use (ie. dejavu:sans)\n" " --fontptsize \n" " Base font point size to use\n" " --fontvariant \n" " Colon (:) delimited list of Font variants to apply (ie. bold:mono:italic)\n" " --rowspacing \n" " Pixel padding between keys in a row. 0 - 50" " --colspacing \n" " Pixel padding between keys in a column. 0 - 50" " --lang \n" " Force given locale when choosing layout."); fprintf(stderr, "\nmatchbox-keyboard %s \nCopyright (C) 2007 OpenedHand Ltd.\n", VERSION); exit(-1); } #if WANT_GTK_WIDGET MBKeyboard* mb_kbd_new (int argc, char **argv, Bool widget, GdkWindow *parent, int x, int y, int width, int height) #else MBKeyboard* mb_kbd_new (int argc, char **argv, Bool widget, Window parent, int x, int y, int width, int height) #endif { MBKeyboard *kb = NULL; char *variant = NULL; char *lang = NULL; Bool want_embedding = widget; Bool want_daemon = False; int i; MBKeyboardDisplayOrientation orientation = MBKeyboardDisplayAny; int param_offset = widget ? 0 : 1; kb = util_malloc0(sizeof(MBKeyboard)); kb->key_border = 1; kb->key_pad = 0; kb->key_margin = 0; kb->col_spacing = 0; kb->row_spacing = 0; kb->font_family = strdup("sans"); kb->font_pt_size = 8; kb->font_variant = strdup("bold"); kb->parent = parent; kb->is_widget = widget; if (width > 0) kb->req_width = width; if (height > 0) kb->req_height = height; for (i = param_offset; i < argc; i++) { DBG ("argv[%d] = %s", i, argv[i]); if (!strcmp ("-width", argv[i]) || !strcmp ("--width", argv[i])) { if (++i>=argc) { if (!widget) mb_kbd_usage (argv[0]); } else kb->req_width = strtol (argv[i], NULL, 0); continue; } if (!strcmp ("-height", argv[i]) || !strcmp ("--height", argv[i])) { if (++i>=argc) { if (!widget) mb_kbd_usage (argv[0]); } else kb->req_height = strtol (argv[i], NULL, 0); continue; } if (!strcmp ("-xid", argv[i]) || !strcmp ("--xid", argv[i])) { want_embedding = True; continue; } if (!strcmp ("-d", argv[i]) || !strcmp ("--daemon", argv[i])) { want_daemon = True; continue; } if (!strcmp ("--fontfamily", argv[i])) { if (++i>=argc) { if (widget) return NULL; else mb_kbd_usage (argv[0]); } else { char family[FONT_FAMILY_LEN]; char *cp = strdup (argv[i]); const char *delimiter = ":"; char *token = strtok (cp, delimiter); memset (family, 0, FONT_FAMILY_LEN); while (NULL != token) { strncat (family, token, (FONT_FAMILY_LEN - strlen (family))); token = strtok (NULL, delimiter); if (NULL != token) strncat (family, " ", (FONT_FAMILY_LEN - strlen (family))); } kb->font_family = strndup(family, 100); free (cp); } continue; } if (!strcmp ("--fontptsize", argv[i])) { if (++i>=argc) { if (widget) return NULL; else mb_kbd_usage (argv[0]); } kb->font_pt_size = strtol(argv[i], NULL, 0); continue; } if (!strcmp ("--fontvariant", argv[i])) { if (++i>=argc) { if (widget) return NULL; else mb_kbd_usage (argv[0]); } kb->font_variant = strdup(argv[i]); continue; } if (!strcmp ("--rowspacing", argv[i])) { int spacing = kb->row_spacing; if (++i>=argc) { if (widget) return NULL; else mb_kbd_usage (argv[0]); } else { spacing = strtol(argv[i], NULL, 0); spacing = MB_KB_CLAMP (spacing, 0, 50); } kb->row_spacing = spacing; continue; } if (!strcmp ("--colspacing", argv[i])) { int spacing = kb->col_spacing; if (++i>=argc) { if (widget) return NULL; else mb_kbd_usage (argv[0]); } else { spacing = strtol(argv[i], NULL, 0); spacing = MB_KB_CLAMP (spacing, 0, 50); } kb->col_spacing = spacing; continue; } if (!strcmp ("-o", argv[i]) || !strcmp ("--orientation", argv[i])) { if (++i>=argc) { if (widget) return NULL; else mb_kbd_usage (argv[0]); } if (!strcmp(argv[i], "portrait")) { orientation = MBKeyboardDisplayPortrait; } else if (!strcmp(argv[i], "landscape")) { orientation = MBKeyboardDisplayLandscape; } else if (widget) { return NULL; } else { mb_kbd_usage (argv[0]); } continue; } if (!strcmp ("--lang", argv[i])) { char *p; if (++i>=argc) { if (widget) return NULL; else mb_kbd_usage (argv[0]); } lang = argv[i]; /* remove any encoding part */ if ((p = strchr (lang, '.'))) *p = 0; continue; } if (i == (argc-1) && argv[i][0] != '-') variant = argv[i]; else if (widget) return NULL; else mb_kbd_usage(argv[0]); } if (variant == NULL) variant = getenv("MB_KBD_VARIANT"); if (!mb_kbd_ui_init(kb)) return NULL; if (!mb_kbd_config_load(kb, variant, lang)) return NULL; kb->selected_layout = (MBKeyboardLayout *)util_list_get_nth_data(kb->layouts, 0); if (want_embedding && !widget) mb_kbd_ui_set_embeded (kb->ui, True); mb_kbd_ui_set_widget (kb->ui, widget); if (want_daemon && !widget) { mb_kbd_ui_set_daemon (kb->ui, True); if (orientation != MBKeyboardDisplayAny) mb_kbd_ui_limit_orientation (kb->ui, orientation); } return kb; } void mb_kbd_destroy (MBKeyboard *kb) { if (kb->font_family) free (kb->font_family); if (kb->font_variant) free (kb->font_variant); if (kb->config_file) free (kb->config_file); if (kb->layouts) { List *l; l = kb->layouts; while (l) { List *n = l->next; MBKeyboardLayout *c = l->data; n = l->next; mb_kbd_layout_destroy (c); free (l); l = n; } } #ifdef WANT_CAIRO if (kb->popup) mb_kbd_popup_destroy (kb->popup); #endif mb_kbd_ui_destroy (kb->ui); free (kb); } int mb_kbd_row_spacing(MBKeyboard *kb) { return kb->row_spacing; } int mb_kbd_col_spacing(MBKeyboard *kb) { return kb->col_spacing; } int mb_kbd_keys_border(MBKeyboard *kb) { return kb->key_border; } int mb_kbd_keys_pad(MBKeyboard *kb) { return kb->key_pad; } int mb_kbd_keys_margin(MBKeyboard *kb) { return kb->key_margin; } void mb_kbd_add_state(MBKeyboard *kbd, MBKeyboardStateType state) { kbd->keys_state |= state; } void mb_kbd_toggle_state(MBKeyboard *kbd, MBKeyboardStateType state) { kbd->keys_state ^= state; } boolean mb_kbd_has_state(MBKeyboard *kbd, MBKeyboardStateType state) { return (kbd->keys_state & state); } boolean mb_kbd_has_any_state(MBKeyboard *kbd) { return (kbd->keys_state > 0); } void mb_kbd_remove_state(MBKeyboard *kbd, MBKeyboardStateType state) { kbd->keys_state &= ~(state); } MBKeyboardKeyStateType mb_kbd_keys_current_state(MBKeyboard *kbd) { if (mb_kbd_has_state(kbd, MBKeyboardStateShifted)) return MBKeyboardKeyStateShifted; if (mb_kbd_has_state(kbd, MBKeyboardStateMod1)) return MBKeyboardKeyStateMod1; if (mb_kbd_has_state(kbd, MBKeyboardStateMod2)) return MBKeyboardKeyStateMod2; if (mb_kbd_has_state(kbd, MBKeyboardStateMod3)) return MBKeyboardKeyStateMod3; return MBKeyboardKeyStateNormal; } void mb_kbd_redraw(MBKeyboard *kb) { mb_kbd_ui_redraw(kb->ui); } void mb_kbd_redraw_key(MBKeyboard *kb, MBKeyboardKey *key) { mb_kbd_ui_redraw_key(kb->ui, key); mb_kbd_ui_swap_buffers(kb->ui); } MBKeyboardKey* mb_kbd_locate_key(MBKeyboard *kb, int x, int y) { MBKeyboardLayout *layout; List *row_item, *key_item; layout = mb_kbd_get_selected_layout(kb); row_item = mb_kbd_layout_rows(layout); while (row_item != NULL) { MBKeyboardRow *row = row_item->data; if (x >= mb_kbd_row_x(row) && x <= mb_kbd_row_x(row) + mb_kbd_row_width(row) && y >= mb_kbd_row_y(row) && y <= mb_kbd_row_y(row) + mb_kbd_row_height(row) ) { mb_kbd_row_for_each_key(row, key_item) { MBKeyboardKey *key = key_item->data; if (!mb_kbd_is_extended(kb) && mb_kbd_key_get_extended(key)) continue; if (!mb_kbd_key_is_blank(key) && x >= mb_kbd_key_abs_x(key) && x <= mb_kbd_key_abs_x(key) + mb_kbd_key_width(key)) return key; } return NULL; } row_item = util_list_next(row_item); } return NULL; } void mb_kbd_add_layout(MBKeyboard *kb, MBKeyboardLayout *layout) { kb->layouts = util_list_append(kb->layouts, (pointer)layout); } MBKeyboardLayout* mb_kbd_get_selected_layout(MBKeyboard *kb) { return kb->selected_layout; } void mb_kbd_set_held_key(MBKeyboard *kb, MBKeyboardKey *key) { kb->held_key = key; } MBKeyboardKey * mb_kbd_get_held_key(MBKeyboard *kb) { return kb->held_key; } void mb_kbd_set_extended(MBKeyboard *kb, boolean extend) { kb->extended = extend; } boolean mb_kbd_is_extended(MBKeyboard *kb) { return kb->extended; } void mb_kbd_show_popup (MBKeyboard *kb, MBKeyboardKey *key, int x_root, int y_root) { #ifdef WANT_CAIRO mb_kbd_popup_show (kb->popup, key, x_root, y_root); #endif } void mb_kbd_hide_popup (MBKeyboard *kb) { #ifdef WANT_CAIRO mb_kbd_popup_hide (kb->popup); #endif } void mb_kbd_load_popup_font (MBKeyboard *kb) { #ifdef WANT_CAIRO if (kb->popup) mb_kbd_popup_load_font (kb->popup); #endif } void mb_kbd_resize_popup (MBKeyboard *kb) { #ifdef WANT_CAIRO if (kb->popup) mb_kbd_popup_resize (kb->popup); #endif }