You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/01/28 12:59:58 UTC
[2/3] guacamole-server git commit: GUACAMOLE-352: Type using dead
keys when necessary and possible.
GUACAMOLE-352: Type using dead keys when necessary and possible.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/9a5b5574
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/9a5b5574
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/9a5b5574
Branch: refs/heads/master
Commit: 9a5b5574a833d95e1f2828bd028eddab4ecb2acb
Parents: 5d56985
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Jan 28 01:00:02 2018 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Sun Jan 28 01:32:58 2018 -0800
----------------------------------------------------------------------
src/protocols/rdp/Makefile.am | 2 +
src/protocols/rdp/decompose.c | 177 +++++++++++++++++++++++++++++++++++++
src/protocols/rdp/decompose.h | 50 +++++++++++
src/protocols/rdp/keyboard.c | 12 ++-
4 files changed, 237 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/9a5b5574/src/protocols/rdp/Makefile.am
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am
index 7de6df5..cffabb2 100644
--- a/src/protocols/rdp/Makefile.am
+++ b/src/protocols/rdp/Makefile.am
@@ -28,6 +28,7 @@ nodist_libguac_client_rdp_la_SOURCES = \
libguac_client_rdp_la_SOURCES = \
audio_input.c \
client.c \
+ decompose.c \
dvc.c \
error.c \
input.c \
@@ -98,6 +99,7 @@ noinst_HEADERS = \
guac_svc/svc_service.h \
audio_input.h \
client.h \
+ decompose.h \
dvc.h \
error.h \
input.h \
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/9a5b5574/src/protocols/rdp/decompose.c
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/decompose.c b/src/protocols/rdp/decompose.c
new file mode 100644
index 0000000..5f559d9
--- /dev/null
+++ b/src/protocols/rdp/decompose.c
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+#include "keyboard.h"
+
+/**
+ * The X11 keysym for the dead key which types a grave (`).
+ */
+#define DEAD_GRAVE 0xFE50
+
+/**
+ * The X11 keysym for the dead key which types an acute (´). Note that this is
+ * NOT equivalent to an apostrophe or single quote.
+ */
+#define DEAD_ACUTE 0xFE51
+
+/**
+ * The X11 keysym for the dead key which types a circumflex/caret (^).
+ */
+#define DEAD_CIRCUMFLEX 0xFE52
+
+/**
+ * The X11 keysym for the dead key which types a tilde (~).
+ */
+#define DEAD_TILDE 0xFE53
+
+/**
+ * The X11 keysym for the dead key which types a dieresis/umlaut (¨).
+ */
+#define DEAD_DIERESIS 0xFE57
+
+/**
+ * The X11 keysym for the dead key which types an abovering (˚). Note that this
+ * is NOT equivalent to the degree symbol.
+ */
+#define DEAD_ABOVERING 0xFE58
+
+/**
+ * The decomposed form of a key that can be typed using two keypresses: a dead
+ * key followed by a base key. For example, on a keyboard which lacks a single
+ * dedicated key for doing the same, "ó" would be typed using the dead acute
+ * key followed by the "o" key. The dead key and base key are pressed and
+ * released in sequence; they are not held down.
+ */
+typedef struct guac_rdp_decomposed_key {
+
+ /**
+ * The keysym of the dead key which must first be pressed and released to
+ * begin typing the desired character. The dead key defines the diacritic
+ * which will be applied to the character typed by the base key.
+ */
+ int dead_keysym;
+
+ /**
+ * The keysym of the base key which must be pressed and released to finish
+ * typing the desired character. The base key defines the normal form of
+ * the character (the form which lacks any diacritic) to which the
+ * diacritic defined by the previously-pressed dead key will be applied.
+ */
+ int base_keysym;
+
+} guac_rdp_decomposed_key;
+
+/**
+ * A lookup table of all known decomposed forms of various keysyms. Keysyms map
+ * directly to entries within this table. A keysym which has no entry within
+ * this table does not have a defined decomposed form (or at least does not
+ * have a decomposed form relevant to RDP).
+ */
+guac_rdp_decomposed_key guac_rdp_decomposed_keys[256] = {
+
+ /* ^ */ [0x005E] = { DEAD_CIRCUMFLEX, ' ' },
+ /* ` */ [0x0060] = { DEAD_GRAVE, ' ' },
+ /* ~ */ [0x007E] = { DEAD_TILDE, ' ' },
+ /* ¨ */ [0x00A8] = { DEAD_DIERESIS, ' ' },
+ /* ´ */ [0x00B4] = { DEAD_ACUTE, ' ' },
+ /* À */ [0x00C0] = { DEAD_GRAVE, 'A' },
+ /* Á */ [0x00C1] = { DEAD_ACUTE, 'A' },
+ /* Â */ [0x00C2] = { DEAD_CIRCUMFLEX, 'A' },
+ /* Ã */ [0x00C3] = { DEAD_TILDE, 'A' },
+ /* Ä */ [0x00C4] = { DEAD_DIERESIS, 'A' },
+ /* Å */ [0x00C5] = { DEAD_ABOVERING, 'A' },
+ /* È */ [0x00C8] = { DEAD_GRAVE, 'E' },
+ /* É */ [0x00C9] = { DEAD_ACUTE, 'E' },
+ /* Ê */ [0x00CA] = { DEAD_CIRCUMFLEX, 'E' },
+ /* Ë */ [0x00CB] = { DEAD_DIERESIS, 'E' },
+ /* Ì */ [0x00CC] = { DEAD_GRAVE, 'I' },
+ /* Í */ [0x00CD] = { DEAD_ACUTE, 'I' },
+ /* Î */ [0x00CE] = { DEAD_CIRCUMFLEX, 'I' },
+ /* Ï */ [0x00CF] = { DEAD_DIERESIS, 'I' },
+ /* Ñ */ [0x00D1] = { DEAD_TILDE, 'N' },
+ /* Ò */ [0x00D2] = { DEAD_GRAVE, 'O' },
+ /* Ó */ [0x00D3] = { DEAD_ACUTE, 'O' },
+ /* Ô */ [0x00D4] = { DEAD_CIRCUMFLEX, 'O' },
+ /* Õ */ [0x00D5] = { DEAD_TILDE, 'O' },
+ /* Ö */ [0x00D6] = { DEAD_DIERESIS, 'O' },
+ /* Ù */ [0x00D9] = { DEAD_GRAVE, 'U' },
+ /* Ú */ [0x00DA] = { DEAD_ACUTE, 'U' },
+ /* Û */ [0x00DB] = { DEAD_CIRCUMFLEX, 'U' },
+ /* Ü */ [0x00DC] = { DEAD_DIERESIS, 'U' },
+ /* Ý */ [0x00DD] = { DEAD_ACUTE, 'Y' },
+ /* à */ [0x00E0] = { DEAD_GRAVE, 'a' },
+ /* á */ [0x00E1] = { DEAD_ACUTE, 'a' },
+ /* â */ [0x00E2] = { DEAD_CIRCUMFLEX, 'a' },
+ /* ã */ [0x00E3] = { DEAD_TILDE, 'a' },
+ /* ä */ [0x00E4] = { DEAD_DIERESIS, 'a' },
+ /* å */ [0x00E5] = { DEAD_ABOVERING, 'a' },
+ /* è */ [0x00E8] = { DEAD_GRAVE, 'e' },
+ /* é */ [0x00E9] = { DEAD_ACUTE, 'e' },
+ /* ê */ [0x00EA] = { DEAD_CIRCUMFLEX, 'e' },
+ /* ë */ [0x00EB] = { DEAD_DIERESIS, 'e' },
+ /* ì */ [0x00EC] = { DEAD_GRAVE, 'i' },
+ /* í */ [0x00ED] = { DEAD_ACUTE, 'i' },
+ /* î */ [0x00EE] = { DEAD_CIRCUMFLEX, 'i' },
+ /* ï */ [0x00EF] = { DEAD_DIERESIS, 'i' },
+ /* ñ */ [0x00F1] = { DEAD_TILDE, 'n' },
+ /* ò */ [0x00F2] = { DEAD_GRAVE, 'o' },
+ /* ó */ [0x00F3] = { DEAD_ACUTE, 'o' },
+ /* ô */ [0x00F4] = { DEAD_CIRCUMFLEX, 'o' },
+ /* õ */ [0x00F5] = { DEAD_TILDE, 'o' },
+ /* ö */ [0x00F6] = { DEAD_DIERESIS, 'o' },
+ /* ù */ [0x00F9] = { DEAD_GRAVE, 'u' },
+ /* ú */ [0x00FA] = { DEAD_ACUTE, 'u' },
+ /* û */ [0x00FB] = { DEAD_CIRCUMFLEX, 'u' },
+ /* ü */ [0x00FC] = { DEAD_DIERESIS, 'u' },
+ /* ý */ [0x00FD] = { DEAD_ACUTE, 'y' },
+ /* ÿ */ [0x00FF] = { DEAD_DIERESIS, 'y' }
+
+};
+
+int guac_rdp_decompose_keysym(guac_rdp_keyboard* keyboard, int keysym) {
+
+ /* Verify keysym is within range of lookup table */
+ if (keysym < 0x00 || keysym > 0xFF)
+ return 1;
+
+ /* Verify keysym is actually defined within lookup table */
+ guac_rdp_decomposed_key* key = &guac_rdp_decomposed_keys[keysym];
+ if (!key->dead_keysym)
+ return 1;
+
+ /* Cannot type using decomposed keys if those keys are not defined within
+ * the current layout */
+ if (!guac_rdp_keyboard_is_defined(keyboard, key->dead_keysym)
+ || !guac_rdp_keyboard_is_defined(keyboard, key->base_keysym))
+ return 1;
+
+ /* Press dead key */
+ guac_rdp_keyboard_send_event(keyboard, key->dead_keysym, 1);
+ guac_rdp_keyboard_send_event(keyboard, key->dead_keysym, 0);
+
+ /* Press base key */
+ guac_rdp_keyboard_send_event(keyboard, key->base_keysym, 1);
+ guac_rdp_keyboard_send_event(keyboard, key->base_keysym, 0);
+
+ /* Decomposed key successfully typed */
+ return 0;
+
+}
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/9a5b5574/src/protocols/rdp/decompose.h
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/decompose.h b/src/protocols/rdp/decompose.h
new file mode 100644
index 0000000..a7ab146
--- /dev/null
+++ b/src/protocols/rdp/decompose.h
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_RDP_DECOMPOSE_H
+#define GUAC_RDP_DECOMPOSE_H
+
+#include "config.h"
+#include "keyboard.h"
+
+/**
+ * Attempts to type the given keysym by decomposing the associated character
+ * into the dead key and base key pair which would be used to type that
+ * character on a keyboard which lacks the necessary dedicated key. The key
+ * events for the dead key and base key are sent only if the keyboard layout of
+ * the given keyboard defines those keys.
+ *
+ * For example, the keysym for "ò" (0x00F2) would decompose into a dead grave
+ * (`) and the base key "o". May it rest in peace.
+ *
+ * @param keyboard
+ * The guac_rdp_keyboard associated with the current RDP session.
+ *
+ * @param keysym
+ * The keysym being pressed.
+ *
+ * @return
+ * Zero if the keysym was successfully decomposed and sent to the RDP
+ * server as a pair of key events (the dead key and base key), non-zero
+ * otherwise.
+ */
+int guac_rdp_decompose_keysym(guac_rdp_keyboard* keyboard, int keysym);
+
+#endif
+
http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/9a5b5574/src/protocols/rdp/keyboard.c
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/keyboard.c b/src/protocols/rdp/keyboard.c
index 2184e02..94329ec 100644
--- a/src/protocols/rdp/keyboard.c
+++ b/src/protocols/rdp/keyboard.c
@@ -20,6 +20,7 @@
#include "config.h"
#include "client.h"
+#include "decompose.h"
#include "keyboard.h"
#include "rdp.h"
#include "rdp_keymap.h"
@@ -309,12 +310,15 @@ int guac_rdp_keyboard_send_event(guac_rdp_keyboard* keyboard,
}
}
- /* Fall back to unicode events if undefined inside current keymap */
-
- /* Only send when key pressed - Unicode events do not have
- * DOWN/RELEASE flags */
+ /* Fall back to dead keys or Unicode events if otherwise undefined inside
+ * current keymap (note that we only handle "pressed" here, as neither
+ * Unicode events nor dead keys can have a pressed/released state) */
if (pressed) {
+ /* Attempt to type using dead keys */
+ if (!guac_rdp_decompose_keysym(keyboard, keysym))
+ return 0;
+
guac_client_log(client, GUAC_LOG_DEBUG,
"Sending keysym 0x%x as Unicode", keysym);