2 * FreeRDP: A Remote Desktop Protocol Client
3 * X11 Keyboard Handling
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
24 #include <X11/Xutil.h>
25 #include <X11/keysym.h>
27 #include "xf_keyboard.h"
29 void xf_kbd_init(xfInfo* xfi)
31 memset(xfi->pressed_keys, 0, 256 * sizeof(boolean));
32 xfi->keyboard_layout_id = xfi->instance->settings->kbd_layout;
33 xfi->keyboard_layout_id = freerdp_kbd_init(xfi->display, xfi->keyboard_layout_id);
34 xfi->instance->settings->kbd_layout = xfi->keyboard_layout_id;
37 void xf_kbd_set_keypress(xfInfo* xfi, uint8 keycode, KeySym keysym)
40 xfi->pressed_keys[keycode] = keysym;
45 void xf_kbd_unset_keypress(xfInfo* xfi, uint8 keycode)
48 xfi->pressed_keys[keycode] = NoSymbol;
53 boolean xf_kbd_key_pressed(xfInfo* xfi, KeySym keysym)
55 KeyCode keycode = XKeysymToKeycode(xfi->display, keysym);
56 return (xfi->pressed_keys[keycode] == keysym);
59 void xf_kbd_send_key(xfInfo* xfi, boolean down, uint8 keycode)
66 input = xfi->instance->input;
67 scancode = freerdp_kbd_get_scancode_by_keycode(keycode, &extended);
73 else if ((scancode == 0x46) && extended &&
74 !xf_kbd_key_pressed(xfi, XK_Control_L) && !xf_kbd_key_pressed(xfi, XK_Control_R))
76 /* Pause without Ctrl has to be sent as Ctrl + NumLock. */
79 input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x1D); /* Ctrl down */
80 input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x45); /* NumLock down */
81 input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x1D); /* Ctrl up */
82 input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x45); /* NumLock up */
87 flags = (extended) ? KBD_FLAGS_EXTENDED : 0;
88 flags |= (down) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE;
90 input->KeyboardEvent(input, flags, scancode);
92 if ((scancode == 0x3A) && (down == false)) /* caps lock was released */
95 syncFlags = xf_kbd_get_toggle_keys_state(xfi);
96 input->SynchronizeEvent(input, syncFlags);
101 int xf_kbd_read_keyboard_state(xfInfo* xfi)
107 if (xfi->remote_app != true)
109 XQueryPointer(xfi->display, xfi->window->handle,
110 &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
116 boolean xf_kbd_get_key_state(xfInfo* xfi, int state, int keysym)
119 int modifierpos, key, keysymMask = 0;
120 KeyCode keycode = XKeysymToKeycode(xfi->display, keysym);
122 if (keycode == NoSymbol)
125 for (modifierpos = 0; modifierpos < 8; modifierpos++)
127 offset = xfi->modifier_map->max_keypermod * modifierpos;
128 for (key = 0; key < xfi->modifier_map->max_keypermod; key++)
130 if (xfi->modifier_map->modifiermap[offset + key] == keycode)
132 keysymMask |= 1 << modifierpos;
137 return (state & keysymMask) ? true : false;
140 int xf_kbd_get_toggle_keys_state(xfInfo* xfi)
143 int toggle_keys_state = 0;
145 state = xf_kbd_read_keyboard_state(xfi);
146 if (xf_kbd_get_key_state(xfi, state, XK_Scroll_Lock))
147 toggle_keys_state |= KBD_SYNC_SCROLL_LOCK;
148 if (xf_kbd_get_key_state(xfi, state, XK_Num_Lock))
149 toggle_keys_state |= KBD_SYNC_NUM_LOCK;
150 if (xf_kbd_get_key_state(xfi, state, XK_Caps_Lock))
151 toggle_keys_state |= KBD_SYNC_CAPS_LOCK;
152 if (xf_kbd_get_key_state(xfi, state, XK_Kana_Lock))
153 toggle_keys_state |= KBD_SYNC_KANA_LOCK;
155 return toggle_keys_state;
158 void xf_kbd_focus_in(xfInfo* xfi)
163 input = xfi->instance->input;
165 /* on focus in send a tab up like mstsc.exe */
166 input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x0F);
168 /* synchronize toggle keys */
169 syncFlags = xf_kbd_get_toggle_keys_state(xfi);
170 input->SynchronizeEvent(input, syncFlags);
173 boolean xf_kbd_handle_special_keys(xfInfo* xfi, KeySym keysym)
175 if (keysym == XK_Return)
177 if ((xf_kbd_key_pressed(xfi, XK_Alt_L) || xf_kbd_key_pressed(xfi, XK_Alt_R))
178 && (xf_kbd_key_pressed(xfi, XK_Control_L) || xf_kbd_key_pressed(xfi, XK_Control_R)))
180 /* Ctrl-Alt-Enter: toggle full screen */
181 xf_toggle_fullscreen(xfi);