3 * @brief X C Bindings VLC keyboard event handling
5 /*****************************************************************************
6 * Copyright © 2009 Rémi Denis-Courmont
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.
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.
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 ****************************************************************************/
32 #include <xcb/xcb_keysyms.h>
33 #include <X11/keysym.h>
34 #include <X11/XF86keysym.h>
36 #include <vlc_common.h>
44 xcb_key_symbols_t *syms;
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.
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.
56 key_handler_t *CreateKeyHandler (vlc_object_t *obj, xcb_connection_t *conn)
58 key_handler_t *ctx = malloc (sizeof (*ctx));
63 ctx->syms = xcb_key_symbols_alloc (conn);
67 void DestroyKeyHandler (key_handler_t *ctx)
69 xcb_key_symbols_free (ctx->syms);
73 static int keysymcmp (const void *pa, const void *pb)
75 int a = *(const xcb_keysym_t *)pa;
76 int b = *(const xcb_keysym_t *)pb;
81 static uint_fast32_t ConvertKeySym (xcb_keysym_t sym)
88 /* This list MUST be in XK_* incremental order (see keysymdef.h),
89 * so that binary search works.
90 * Multiple X keys can match the same VLC key.
91 * X key symbols must be in the first column of the struct. */
92 { XK_BackSpace, KEY_BACKSPACE, },
94 { XK_Return, KEY_ENTER, },
95 { XK_Escape, KEY_ESC, },
96 { XK_Home, KEY_HOME, },
97 { XK_Left, KEY_LEFT, },
99 { XK_Right, KEY_RIGHT, },
100 { XK_Down, KEY_DOWN, },
101 { XK_Page_Up, KEY_PAGEUP, },
102 { XK_Page_Down, KEY_PAGEDOWN, },
103 { XK_End, KEY_END, },
104 { XK_Begin, KEY_HOME, },
105 { XK_Insert, KEY_INSERT, },
106 { XK_Menu, KEY_MENU },
108 /* Numeric pad keys */
109 { XK_KP_Space, ' ', },
110 { XK_KP_Tab, KEY_TAB, },
111 { XK_KP_Enter, KEY_ENTER, },
112 { XK_KP_F1, KEY_F1, },
113 { XK_KP_F2, KEY_F2, },
114 { XK_KP_F3, KEY_F3, },
115 { XK_KP_F4, KEY_F4, },
116 { XK_KP_Home, KEY_HOME, },
117 { XK_KP_Left, KEY_LEFT, },
118 { XK_KP_Up, KEY_UP, },
119 { XK_KP_Right, KEY_RIGHT, },
120 { XK_KP_Down, KEY_DOWN, },
121 { XK_KP_Page_Up, KEY_PAGEUP, },
122 { XK_KP_Page_Down, KEY_PAGEDOWN, },
123 { XK_KP_End, KEY_END, },
124 { XK_KP_Begin, KEY_HOME, }, /* KP middle (5 without numlock) */
125 { XK_KP_Insert, KEY_INSERT, },
126 { XK_KP_Delete, KEY_DELETE, },
127 { XK_KP_Equal, '=', },
128 { XK_KP_Multiply, '*', },
130 { XK_KP_Separator, ',', },
131 { XK_KP_Subtract, '-', },
132 { XK_KP_Decimal, ',', }, /* FIXME: I don't know that key */
133 { XK_KP_Divide, '/', },
154 { XK_F10, KEY_F10, },
155 { XK_F11, KEY_F11, },
156 { XK_F12, KEY_F12, },
157 { XK_Delete, KEY_DELETE, },
159 /* XFree86 extensions */
160 { XF86XK_AudioLowerVolume, KEY_VOLUME_DOWN, },
161 { XF86XK_AudioMute, KEY_VOLUME_MUTE, },
162 { XF86XK_AudioRaiseVolume, KEY_VOLUME_UP, },
163 { XF86XK_AudioPlay, KEY_MEDIA_PLAY_PAUSE, },
164 { XF86XK_AudioStop, KEY_MEDIA_STOP, },
165 { XF86XK_AudioPrev, KEY_MEDIA_PREV_TRACK, },
166 { XF86XK_AudioNext, KEY_MEDIA_NEXT_TRACK, },
167 { XF86XK_HomePage, KEY_BROWSER_HOME, },
168 { XF86XK_Search, KEY_BROWSER_SEARCH, },
169 { XF86XK_Back, KEY_BROWSER_BACK, },
170 { XF86XK_Forward, KEY_BROWSER_FORWARD, },
171 { XF86XK_Stop, KEY_BROWSER_STOP, },
172 { XF86XK_Refresh, KEY_BROWSER_REFRESH, },
173 { XF86XK_Favorites, KEY_BROWSER_FAVORITES, },
174 { XF86XK_AudioPause, KEY_MEDIA_PLAY_PAUSE, },
175 { XF86XK_Reload, KEY_BROWSER_REFRESH, },
178 /* X11 Latin-1 range */
181 /* X11 Unicode range */
182 if (sym >= 0x1000100 && sym <= 0x110ffff)
183 return sym - 0x1000000;
186 res = bsearch (&sym, tab, sizeof (tab) / sizeof (tab[0]), sizeof (tab[0]),
196 * Process an X11 event, convert into VLC hotkey event if applicable.
198 * @param ctx key handler created with CreateKeyHandler()
199 * @param ev XCB event to process
200 * @return 0 if the event was handled and free()'d, non-zero otherwise
202 int ProcessKeyEvent (key_handler_t *ctx, xcb_generic_event_t *ev)
206 switch (ev->response_type & 0x7f)
210 xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev;
211 xcb_keysym_t sym = xcb_key_press_lookup_keysym (ctx->syms, e, 0);
212 uint_fast32_t vk = ConvertKeySym (sym);
214 msg_Dbg (ctx->obj, "key: 0x%08"PRIxFAST32, vk);
217 if (e->state & XCB_MOD_MASK_SHIFT)
218 vk |= KEY_MODIFIER_SHIFT;
219 if (e->state & XCB_MOD_MASK_CONTROL)
220 vk |= KEY_MODIFIER_CTRL;
221 if (e->state & XCB_MOD_MASK_1)
222 vk |= KEY_MODIFIER_ALT;
223 if (e->state & XCB_MOD_MASK_4)
224 vk |= KEY_MODIFIER_COMMAND;
225 var_SetInteger (ctx->obj->p_libvlc, "key-pressed", vk);
229 case XCB_KEY_RELEASE:
232 case XCB_MAPPING_NOTIFY:
234 xcb_mapping_notify_event_t *e = (xcb_mapping_notify_event_t *)ev;
235 msg_Dbg (ctx->obj, "refreshing keyboard mapping");
236 xcb_refresh_keyboard_mapping (ctx->syms, e);