Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of libdom.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
  6.  */
  7.  
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #include "events/keyboard_event.h"
  12. #include "core/document.h"
  13.  
  14. #include "utils/utils.h"
  15.  
  16. static void _virtual_dom_keyboard_event_destroy(struct dom_event *evt);
  17.  
  18. static struct dom_event_private_vtable _event_vtable = {
  19.         _virtual_dom_keyboard_event_destroy
  20. };
  21.  
  22. /* Constructor */
  23. dom_exception _dom_keyboard_event_create(struct dom_document *doc,
  24.                 struct dom_keyboard_event **evt)
  25. {
  26.         *evt = malloc(sizeof(dom_keyboard_event));
  27.         if (*evt == NULL)
  28.                 return DOM_NO_MEM_ERR;
  29.        
  30.         ((struct dom_event *) *evt)->vtable = &_event_vtable;
  31.  
  32.         return _dom_keyboard_event_initialise(doc, *evt);
  33. }
  34.  
  35. /* Destructor */
  36. void _dom_keyboard_event_destroy(struct dom_keyboard_event *evt)
  37. {
  38.         _dom_keyboard_event_finalise(evt);
  39.  
  40.         free(evt);
  41. }
  42.  
  43. /* Initialise function */
  44. dom_exception _dom_keyboard_event_initialise(struct dom_document *doc,
  45.                 struct dom_keyboard_event *evt)
  46. {
  47.         evt->key_ident = NULL;
  48.         evt->modifier_state = 0;
  49.  
  50.         return _dom_ui_event_initialise(doc, &evt->base);
  51. }
  52.  
  53. /* Finalise function */
  54. void _dom_keyboard_event_finalise(struct dom_keyboard_event *evt)
  55. {
  56.         _dom_ui_event_finalise(&evt->base);
  57. }
  58.  
  59. /* The virtual destroy function */
  60. void _virtual_dom_keyboard_event_destroy(struct dom_event *evt)
  61. {
  62.         _dom_keyboard_event_destroy((dom_keyboard_event *) evt);
  63. }
  64.  
  65. /*----------------------------------------------------------------------*/
  66. /* The public API */
  67.  
  68. /**
  69.  * Get the key identifier
  70.  *
  71.  * \param evt  The Event object
  72.  * \param ident  The returned key identifier
  73.  * \return DOM_NO_ERR.
  74.  */
  75. dom_exception _dom_keyboard_event_get_key_identifier(dom_keyboard_event *evt,
  76.                 dom_string **ident)
  77. {
  78.         *ident = evt->key_ident;
  79.         dom_string_ref(*ident);
  80.  
  81.         return DOM_NO_ERR;
  82. }
  83.  
  84. /**
  85.  * Get the key location
  86.  *
  87.  * \param evt  The Event object
  88.  * \param loc  The returned key location
  89.  * \return DOM_NO_ERR.
  90.  */
  91. dom_exception _dom_keyboard_event_get_key_location(dom_keyboard_event *evt,
  92.                 dom_key_location *loc)
  93. {
  94.         *loc = evt->key_loc;
  95.  
  96.         return DOM_NO_ERR;
  97. }
  98.  
  99. /**
  100.  * Get the ctrl key state
  101.  *
  102.  * \param evt  The Event object
  103.  * \param key  Whether the Control key is pressed down
  104.  * \return DOM_NO_ERR.
  105.  */
  106. dom_exception _dom_keyboard_event_get_ctrl_key(dom_keyboard_event *evt,
  107.                 bool *key)
  108. {
  109.         *key = ((evt->modifier_state & DOM_MOD_CTRL) != 0);
  110.  
  111.         return DOM_NO_ERR;
  112. }
  113.  
  114. /**
  115.  * Get the shift key state
  116.  *
  117.  * \param evt  The Event object
  118.  * \param key  Whether the Shift key is pressed down
  119.  * \return DOM_NO_ERR.
  120.  */
  121. dom_exception _dom_keyboard_event_get_shift_key(dom_keyboard_event *evt,
  122.                 bool *key)
  123. {
  124.         *key = ((evt->modifier_state & DOM_MOD_SHIFT) != 0);
  125.  
  126.         return DOM_NO_ERR;
  127. }
  128.                
  129. /**
  130.  * Get the alt key state
  131.  *
  132.  * \param evt  The Event object
  133.  * \param key  Whether the Alt key is pressed down
  134.  * \return DOM_NO_ERR.
  135.  */
  136. dom_exception _dom_keyboard_event_get_alt_key(dom_keyboard_event *evt,
  137.                 bool *key)
  138. {
  139.         *key = ((evt->modifier_state & DOM_MOD_ALT) != 0);
  140.  
  141.         return DOM_NO_ERR;
  142. }
  143.  
  144. /**
  145.  * Get the meta key state
  146.  *
  147.  * \param evt  The Event object
  148.  * \param key  Whether the Meta key is pressed down
  149.  * \return DOM_NO_ERR.
  150.  */
  151. dom_exception _dom_keyboard_event_get_meta_key(dom_keyboard_event *evt,
  152.                 bool *key)
  153. {
  154.         *key = ((evt->modifier_state & DOM_MOD_META) != 0);
  155.  
  156.         return DOM_NO_ERR;
  157. }
  158.  
  159. /**
  160.  * Query the state of a modifier using a key identifier
  161.  *
  162.  * \param evt    The event object
  163.  * \param ml     The modifier identifier, such as "Alt", "Control", "Meta",
  164.  *               "AltGraph", "CapsLock", "NumLock", "Scroll", "Shift".
  165.  * \param state  Whether the modifier key is pressed
  166.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  167.  *
  168.  * @note: If an application wishes to distinguish between right and left
  169.  * modifiers, this information could be deduced using keyboard events and
  170.  * KeyboardEvent.keyLocation.
  171.  */
  172. dom_exception _dom_keyboard_event_get_modifier_state(dom_keyboard_event *evt,
  173.                 dom_string *m, bool *state)
  174. {
  175.         const char *data;
  176.         size_t len;
  177.  
  178.         if (m == NULL) {
  179.                 *state = false;
  180.                 return DOM_NO_ERR;
  181.         }
  182.  
  183.         data = dom_string_data(m);
  184.         len = dom_string_byte_length(m);
  185.  
  186.         if (len == SLEN("AltGraph") && strncmp(data, "AltGraph", len) == 0) {
  187.                 *state = ((evt->modifier_state & DOM_MOD_ALT_GRAPH) != 0);
  188.         } else if (len == SLEN("Alt") && strncmp(data, "Alt", len) == 0) {
  189.                 *state = ((evt->modifier_state & DOM_MOD_ALT) != 0);
  190.         } else if (len == SLEN("CapsLock") &&
  191.                         strncmp(data, "CapsLock", len) == 0) {
  192.                 *state = ((evt->modifier_state & DOM_MOD_CAPS_LOCK) != 0);
  193.         } else if (len == SLEN("Control") &&
  194.                         strncmp(data, "Control", len) == 0) {
  195.                 *state = ((evt->modifier_state & DOM_MOD_CTRL) != 0);
  196.         } else if (len == SLEN("Meta") && strncmp(data, "Meta", len) == 0) {
  197.                 *state = ((evt->modifier_state & DOM_MOD_META) != 0);
  198.         } else if (len == SLEN("NumLock") &&
  199.                         strncmp(data, "NumLock", len) == 0) {
  200.                 *state = ((evt->modifier_state & DOM_MOD_NUM_LOCK) != 0);
  201.         } else if (len == SLEN("Scroll") &&
  202.                         strncmp(data, "Scroll", len) == 0) {
  203.                 *state = ((evt->modifier_state & DOM_MOD_SCROLL) != 0);
  204.         } else if (len == SLEN("Shift") && strncmp(data, "Shift", len) == 0) {
  205.                 *state = ((evt->modifier_state & DOM_MOD_SHIFT) != 0);
  206.         }
  207.  
  208.         return DOM_NO_ERR;
  209. }
  210.  
  211. /**
  212.  * Initialise the keyboard event
  213.  *
  214.  * \param evt            The Event object
  215.  * \param type           The event's type
  216.  * \param bubble         Whether this is a bubbling event
  217.  * \param cancelable     Whether this is a cancelable event
  218.  * \param view           The AbstractView associated with this event
  219.  * \param key_indent     The key identifier of pressed key
  220.  * \param key_loc        The key location of the preesed key
  221.  * \param modifier_list  A string of modifier key identifiers, separated with
  222.  *                       space
  223.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  224.  */
  225. dom_exception _dom_keyboard_event_init(dom_keyboard_event *evt,
  226.                 dom_string *type, bool bubble, bool cancelable,
  227.                 struct dom_abstract_view *view, dom_string *key_ident,
  228.                 dom_key_location key_loc, dom_string *modifier_list)
  229. {
  230.         dom_exception err;
  231.  
  232.         evt->key_ident = key_ident;
  233.         dom_string_ref(evt->key_ident);
  234.         evt->key_loc = key_loc;
  235.  
  236.         err = _dom_parse_modifier_list(modifier_list, &evt->modifier_state);
  237.         if (err != DOM_NO_ERR)
  238.                 return err;
  239.  
  240.         return _dom_ui_event_init(&evt->base, type, bubble, cancelable,
  241.                         view, 0);
  242. }
  243.  
  244. /**
  245.  * Initialise the keyboard event with namespace
  246.  *
  247.  * \param evt            The Event object
  248.  * \param namespace      The namespace of this event
  249.  * \param type           The event's type
  250.  * \param bubble         Whether this is a bubbling event
  251.  * \param cancelable     Whether this is a cancelable event
  252.  * \param view           The AbstractView associated with this event
  253.  * \param key_indent     The key identifier of pressed key
  254.  * \param key_loc        The key location of the preesed key
  255.  * \param modifier_list  A string of modifier key identifiers, separated with
  256.  *                       space
  257.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  258.  */
  259. dom_exception _dom_keyboard_event_init_ns(dom_keyboard_event *evt,
  260.                 dom_string *namespace, dom_string *type,
  261.                 bool bubble, bool cancelable, struct dom_abstract_view *view,
  262.                 dom_string *key_ident, dom_key_location key_loc,
  263.                 dom_string *modifier_list)
  264. {
  265.         dom_exception err;
  266.  
  267.         evt->key_ident = key_ident;
  268.         dom_string_ref(evt->key_ident);
  269.         evt->key_loc = key_loc;
  270.  
  271.         err = _dom_parse_modifier_list(modifier_list, &evt->modifier_state);
  272.         if (err != DOM_NO_ERR)
  273.                 return err;
  274.  
  275.         return _dom_ui_event_init_ns(&evt->base, namespace, type, bubble,
  276.                         cancelable, view, 0);
  277. }
  278.  
  279.  
  280. /*-------------------------------------------------------------------------*/
  281.  
  282. /**
  283.  * Parse the modifier list string to corresponding bool variable state
  284.  *
  285.  * \param modifier_list   The modifier list string
  286.  * \param modifier_state  The returned state
  287.  * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
  288.  */
  289. dom_exception _dom_parse_modifier_list(dom_string *modifier_list,
  290.                 uint32_t *modifier_state)
  291. {
  292.         const char *data;
  293.         const char *m;
  294.         size_t len = 0;
  295.  
  296.         *modifier_state = 0;
  297.  
  298.         if (modifier_list == NULL)
  299.                 return DOM_NO_ERR;
  300.        
  301.         data = dom_string_data(modifier_list);
  302.         m = data;
  303.  
  304.         while (true) {
  305.                 /* If we reach a space or end of the string, we should parse
  306.                  * the new token. */
  307.                 if (*data == ' ' || *data == '\0') {
  308.                         if (len == SLEN("AltGraph") &&
  309.                                         strncmp(m, "AltGraph", len) == 0) {
  310.                                 *modifier_state = *modifier_state |
  311.                                                 DOM_MOD_ALT_GRAPH;
  312.                         } else if (len == SLEN("Alt") &&
  313.                                         strncmp(m, "Alt", len) == 0) {
  314.                                 *modifier_state = *modifier_state |
  315.                                                 DOM_MOD_ALT;
  316.                         } else if (len == SLEN("CapsLock") &&
  317.                                         strncmp(m, "CapsLock", len) == 0) {
  318.                                 *modifier_state = *modifier_state |
  319.                                                 DOM_MOD_CAPS_LOCK;
  320.                         } else if (len == SLEN("Control") &&
  321.                                         strncmp(m, "Control", len) == 0) {
  322.                                 *modifier_state = *modifier_state |
  323.                                                 DOM_MOD_CTRL;
  324.                         } else if (len == SLEN("Meta") &&
  325.                                         strncmp(m, "Meta", len) == 0) {
  326.                                 *modifier_state = *modifier_state |
  327.                                                 DOM_MOD_META;
  328.                         } else if (len == SLEN("NumLock") &&
  329.                                         strncmp(m, "NumLock", len) == 0) {
  330.                                 *modifier_state = *modifier_state |
  331.                                                 DOM_MOD_NUM_LOCK;
  332.                         } else if (len == SLEN("Scroll") &&
  333.                                         strncmp(m, "Scroll", len) == 0) {
  334.                                 *modifier_state = *modifier_state |
  335.                                                 DOM_MOD_SCROLL;
  336.                         } else if (len == SLEN("Shift") &&
  337.                                         strncmp(m, "Shift", len) == 0) {
  338.                                 *modifier_state = *modifier_state |
  339.                                                 DOM_MOD_SHIFT;
  340.                         }
  341.  
  342.                         while (*data == ' ') {
  343.                                 data++;
  344.                         }
  345.                         /* Finished parsing and break */
  346.                         if (*data == '\0')
  347.                                 break;
  348.  
  349.                         m = data;
  350.                         len = 0;
  351.                 }
  352.  
  353.                 data++;
  354.                 len++;
  355.         }
  356.  
  357.         return DOM_NO_ERR;
  358. }
  359.  
  360.