input: define our own modifiers
[platform/upstream/kmscon.git] / tests / test_input.c
1 /*
2  * test_input - Test the input system - hotplug and keypresses
3  *
4  * Copyright (c) 2011 Ran Benita <ran234@gmail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 #include <errno.h>
27 #include <linux/input.h>
28 #include <locale.h>
29 #include <signal.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <wchar.h>
36
37 #include <X11/extensions/XKBcommon.h>
38 #include <X11/keysym.h>
39
40 #include "eloop.h"
41 #include "input.h"
42 #include "log.h"
43
44 static bool terminate;
45
46 static void sig_term(struct kmscon_signal *sig, int signum, void *data)
47 {
48         terminate = true;
49 }
50
51 /* Pressing Ctrl-\ should toggle the capturing. */
52 static void sig_quit(struct kmscon_signal *sig, int signum, void *data)
53 {
54         struct kmscon_input *input = data;
55
56         if (kmscon_input_is_asleep(input)) {
57                 kmscon_input_wake_up(input);
58                 log_info("Woke Up\n");
59         } else {
60                 kmscon_input_sleep(input);
61                 log_info("Went to sleep\n");
62         }
63 }
64
65 static void print_modifiers(unsigned int mods)
66 {
67         if (mods & KMSCON_SHIFT_MASK)
68                 printf("SHIFT ");
69         if (mods & KMSCON_LOCK_MASK)
70                 printf("LOCK ");
71         if (mods & KMSCON_CONTROL_MASK)
72                 printf("CONTROL ");
73         if (mods & KMSCON_MOD1_MASK)
74                 printf("MOD1 ");
75         if (mods & KMSCON_MOD2_MASK)
76                 printf("MOD2 ");
77         if (mods & KMSCON_MOD3_MASK)
78                 printf("MOD3 ");
79         if (mods & KMSCON_MOD4_MASK)
80                 printf("MOD4 ");
81         if (mods & KMSCON_MOD5_MASK)
82                 printf("MOD5 ");
83         printf("\n");
84 }
85
86 static void input_arrived(struct kmscon_input *input,
87                                 struct kmscon_input_event *ev, void *data)
88 {
89         int len;
90         char s[16];
91         char utf8[MB_CUR_MAX + 1];
92
93         if (ev->unicode == KMSCON_INPUT_INVALID) {
94                 xkb_keysym_to_string(ev->keysym, s, sizeof(s));
95                 printf("sym %s ", s);
96         } else {
97                 /*
98                  * Just a proof-of-concept hack. This works because glibc uses
99                  * UTF-32 (= UCS-4) as the internal wchar_t encoding.
100                  */
101                 len = wctomb(utf8, (wchar_t)ev->unicode);
102                 if (len <= 0) {
103                         log_info("Bad unicode char\n");
104                         return;
105                 } else {
106                         utf8[len] = '\0';
107                 }
108
109                 printf("utf8 %s ", utf8);
110         }
111         print_modifiers(ev->mods);
112 }
113
114 int main(int argc, char **argv)
115 {
116         int ret;
117         struct kmscon_eloop *loop;
118         struct kmscon_input *input;
119         struct kmscon_signal *sigint, *sigquit;
120
121         if (!setlocale(LC_ALL, "en_US.UTF-8")) {
122                 log_err("Cannot set locale: %m\n");
123                 ret = -EFAULT;
124                 goto err_out;
125         }
126
127         ret = kmscon_eloop_new(&loop);
128         if (ret) {
129                 log_err("Cannot create eloop\n");
130                 goto err_out;
131         }
132
133         ret = kmscon_input_new(&input);
134         if (ret) {
135                 log_err("Cannot create input\n");
136                 goto err_loop;
137         }
138
139         ret = kmscon_eloop_new_signal(loop, &sigint, SIGINT, sig_term, NULL);
140         if (ret) {
141                 log_err("Cannot add INT signal\n");
142                 goto err_input;
143         }
144
145         ret = kmscon_eloop_new_signal(loop, &sigquit, SIGQUIT, sig_quit, input);
146         if (ret) {
147                 log_err("Cannot add quit signal\n");
148                 goto err_sigint;
149         }
150
151         ret = kmscon_input_connect_eloop(input, loop, input_arrived, NULL);
152         if (ret) {
153                 log_err("Cannot connect input\n");
154                 goto err_sigquit;
155         }
156
157         kmscon_input_wake_up(input);
158
159         system("stty -echo");
160
161         while (!terminate) {
162                 ret = kmscon_eloop_dispatch(loop, -1);
163                 if (ret) {
164                         log_err("Dispatcher failed\n");
165                         break;
166                 }
167         }
168
169         system("stty echo");
170
171 err_sigquit:
172         kmscon_eloop_rm_signal(sigquit);
173 err_sigint:
174         kmscon_eloop_rm_signal(sigint);
175 err_input:
176         kmscon_input_unref(input);
177 err_loop:
178         kmscon_eloop_unref(loop);
179 err_out:
180         return abs(ret);
181 }