]> git.sesse.net Git - vlc/blob - modules/video_output/xcb/keys.c
Use var_Inherit* instead of var_CreateGet*.
[vlc] / modules / video_output / xcb / keys.c
1 /**
2  * @file keys.c
3  * @brief X C Bindings VLC keyboard event handling
4  */
5 /*****************************************************************************
6  * Copyright © 2009 Rémi Denis-Courmont
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1
11  * of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  ****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <inttypes.h>
29 #include <assert.h>
30
31 #include <xcb/xcb.h>
32 #include <vlc_common.h>
33 #include "xcb_vlc.h"
34
35 #ifdef HAVE_XCB_KEYSYMS
36 #include <xcb/xcb_keysyms.h>
37 #include <X11/keysym.h>
38 #include <X11/XF86keysym.h>
39 #include <vlc_keys.h>
40
41 struct key_handler_t
42 {
43     vlc_object_t      *obj;
44     xcb_key_symbols_t *syms;
45 };
46
47 /**
48  * Create an X11 key event handler for a VLC window.
49  * The caller shall arrange receiving applicable X11 events, and pass them to
50  * ProcessKeyEvent() later.
51  *
52  * @param obj VLC object owning an X window
53  * @param conn XCB connection to the X server (to fetch key mappings)
54  * @return NULL on error, or a key handling context.
55  */
56 key_handler_t *CreateKeyHandler (vlc_object_t *obj, xcb_connection_t *conn)
57 {
58     key_handler_t *ctx = malloc (sizeof (*ctx));
59     if (!ctx)
60         return NULL;
61
62     ctx->obj = obj;
63     ctx->syms = xcb_key_symbols_alloc (conn);
64     return ctx;
65 }
66
67 void DestroyKeyHandler (key_handler_t *ctx)
68 {
69     xcb_key_symbols_free (ctx->syms);
70     free (ctx);
71 }
72
73 static int keysymcmp (const void *pa, const void *pb)
74 {
75     int a = *(const xcb_keysym_t *)pa;
76     int b = *(const xcb_keysym_t *)pb;
77
78     return a - b;
79 }
80
81 static uint_fast32_t ConvertKeySym (xcb_keysym_t sym)
82 {
83     static const struct
84     {
85         xcb_keysym_t x11;
86         uint32_t vlc;
87     } *res, tab[] = {
88 #include "xcb_keysym.h"
89     }, old[] = {
90 #include "keysym.h"
91     };
92
93     /* X11 Latin-1 range */
94     if (sym <= 0xff)
95         return sym;
96     /* X11 Unicode range */
97     if (sym >= 0x1000100 && sym <= 0x110ffff)
98         return sym - 0x1000000;
99
100     /* Special keys */
101     res = bsearch (&sym, tab, sizeof (tab) / sizeof (tab[0]), sizeof (tab[0]),
102                    keysymcmp);
103     if (res != NULL)
104         return res->vlc;
105     /* Legacy X11 symbols outside the Unicode range */
106     res = bsearch (&sym, old, sizeof (old) / sizeof (old[0]), sizeof (old[0]),
107                    keysymcmp);
108     if (res != NULL)
109         return res->vlc;
110
111     return KEY_UNSET;
112 }
113
114
115 /**
116  * Process an X11 event, convert into VLC hotkey event if applicable.
117  *
118  * @param ctx key handler created with CreateKeyHandler()
119  * @param ev XCB event to process
120  * @return 0 if the event was handled and free()'d, non-zero otherwise
121  */
122 int ProcessKeyEvent (key_handler_t *ctx, xcb_generic_event_t *ev)
123 {
124     assert (ctx);
125
126     switch (ev->response_type & 0x7f)
127     {
128         case XCB_KEY_PRESS:
129         {
130             xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev;
131             xcb_keysym_t sym = xcb_key_press_lookup_keysym (ctx->syms, e, 0);
132             uint_fast32_t vk = ConvertKeySym (sym);
133
134             msg_Dbg (ctx->obj, "key: 0x%08"PRIxFAST32, vk);
135             if (vk == KEY_UNSET)
136                 break;
137             if (e->state & XCB_MOD_MASK_SHIFT)
138                 vk |= KEY_MODIFIER_SHIFT;
139             if (e->state & XCB_MOD_MASK_CONTROL)
140                 vk |= KEY_MODIFIER_CTRL;
141             if (e->state & XCB_MOD_MASK_1)
142                 vk |= KEY_MODIFIER_ALT;
143             if (e->state & XCB_MOD_MASK_4)
144                 vk |= KEY_MODIFIER_META;
145             var_SetInteger (ctx->obj->p_libvlc, "key-pressed", vk);
146             break;
147         }
148
149         case XCB_KEY_RELEASE:
150             break;
151
152         case XCB_MAPPING_NOTIFY:
153         {
154             xcb_mapping_notify_event_t *e = (xcb_mapping_notify_event_t *)ev;
155             msg_Dbg (ctx->obj, "refreshing keyboard mapping");
156             xcb_refresh_keyboard_mapping (ctx->syms, e);
157             break;
158         }
159
160         default:
161             return -1;
162     }
163
164     free (ev);
165     return 0;
166 }
167
168 #else /* HAVE_XCB_KEYSYMS */
169
170 key_handler_t *CreateKeyHandler (vlc_object_t *obj, xcb_connection_t *conn)
171 {
172     msg_Err (obj, "X11 key press support not compiled-in");
173     (void) conn;
174     return NULL;
175 }
176
177 void DestroyKeyHandler (key_handler_t *ctx)
178 {
179     (void) ctx;
180     abort ();
181 }
182
183 int ProcessKeyEvent (key_handler_t *ctx, xcb_generic_event_t *ev)
184 {
185     (void) ctx;
186     (void) ev;
187     abort ();
188 }
189
190 #endif /* HAVE_XCB_KEYSYMS */