Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GUACAMOLE-1943: Add ctrl+arrows/ctrl+backspace shortcuts #505

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 159 additions & 38 deletions src/terminal/terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1435,13 +1435,13 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed
}

/* Track modifiers */
if (keysym == 0xFFE3 || keysym == 0xFFE4)
if (keysym == GUAC_TERMINAL_KEY_CTRL_L || keysym == GUAC_TERMINAL_KEY_CTRL_R)
term->mod_ctrl = pressed;
else if (keysym == 0xFFE7 || keysym == 0xFFE8)
else if (keysym == GUAC_TERMINAL_KEY_META_L || keysym == GUAC_TERMINAL_KEY_META_R)
term->mod_meta = pressed;
else if (keysym == 0xFFE9 || keysym == 0xFFEA)
else if (keysym == GUAC_TERMINAL_KEY_ALT_L || keysym == GUAC_TERMINAL_KEY_ALT_R)
term->mod_alt = pressed;
else if (keysym == 0xFFE1 || keysym == 0xFFE2)
else if (keysym == GUAC_TERMINAL_KEY_SHIFT_L || keysym == GUAC_TERMINAL_KEY_SHIFT_R)
term->mod_shift = pressed;

/* If key pressed */
Expand All @@ -1460,21 +1460,45 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed
if ((keysym == 'C' && term->mod_ctrl) || (keysym == 'c' && term->mod_meta))
return 0;

/* Shift+PgUp / Shift+PgDown shortcuts for scrolling */
/* Shortcuts for scrolling history with shift */
if (term->mod_shift) {

/* Home */
if (keysym == GUAC_TERMINAL_KEY_HOME || keysym == GUAC_TERMINAL_KEY_KP_HOME) {
guac_terminal_scroll_display_up(term, term->max_scrollback);
return 0;
}

/* End */
if (keysym == GUAC_TERMINAL_KEY_END || keysym == GUAC_TERMINAL_KEY_KP_END) {
guac_terminal_scroll_display_down(term, term->max_scrollback);
return 0;
}

/* Page up */
if (keysym == 0xFF55) {
if (keysym == GUAC_TERMINAL_KEY_PAGEUP || keysym == GUAC_TERMINAL_KEY_KP_PAGEUP) {
guac_terminal_scroll_display_up(term, term->term_height);
return 0;
}

/* Page down */
if (keysym == 0xFF56) {
if (keysym == GUAC_TERMINAL_KEY_PAGEDOWN || keysym == GUAC_TERMINAL_KEY_KP_PAGEDOWN) {
guac_terminal_scroll_display_down(term, term->term_height);
return 0;
}

/* Up */
if (keysym == GUAC_TERMINAL_KEY_UP || keysym == GUAC_TERMINAL_KEY_KP_UP) {
guac_terminal_scroll_display_up(term, 1);
return 0;
}

/* Down */
if (keysym == GUAC_TERMINAL_KEY_DOWN || keysym == GUAC_TERMINAL_KEY_KP_DOWN) {
guac_terminal_scroll_display_down(term, 1);
return 0;
}

}

/* Reset scroll */
Expand All @@ -1483,7 +1507,7 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed

/* If alt being held, also send escape character */
if (term->mod_alt)
guac_terminal_send_string(term, "\x1B");
guac_terminal_send_string(term, GUAC_TERMINAL_ASCII_ESCAPE);

/* Translate Ctrl+letter to control code */
if (term->mod_ctrl) {
Expand All @@ -1510,6 +1534,22 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed
else if (keysym >= '3' && keysym <= '7')
data = (char) (keysym - '3' + 0x1B);

/* CTRL+Left: return to previous word */
else if (keysym == GUAC_TERMINAL_KEY_LEFT || keysym == GUAC_TERMINAL_KEY_KP_LEFT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_PREV_WORD);

/* CTRL+Right: go to next word */
else if (keysym == GUAC_TERMINAL_KEY_RIGHT || keysym == GUAC_TERMINAL_KEY_KP_RIGHT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_NEXT_WORD);

/* CTRL+Backspace: remove word (map to CTRL+w) */
else if (keysym == GUAC_TERMINAL_KEY_BACKSPACE)
data = (char) 23;

/* CTRL+Supr: remove word to right */
else if (keysym == GUAC_TERMINAL_KEY_DELETE || keysym == GUAC_TERMINAL_KEY_KP_DELETE)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_DELETE_WORD);

/* Otherwise ignore */
else
return 0;
Expand Down Expand Up @@ -1539,51 +1579,132 @@ static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed
else {

/* Backspace can vary based on configuration of terminal by client. */
if (keysym == 0xFF08) {
if (keysym == GUAC_TERMINAL_KEY_BACKSPACE) {
char backspace_str[] = { term->backspace, '\0' };
return guac_terminal_send_string(term, backspace_str);
}
if (keysym == 0xFF09 || keysym == 0xFF89) return guac_terminal_send_string(term, "\x09"); /* Tab */
if (keysym == 0xFF0D || keysym == 0xFF8D) return guac_terminal_send_string(term, "\x0D"); /* Enter */
if (keysym == 0xFF1B) return guac_terminal_send_string(term, "\x1B"); /* Esc */

if (keysym == 0xFF50 || keysym == 0xFF95) return guac_terminal_send_string(term, "\x1B[1~"); /* Home */
/* Tab */
if (keysym == GUAC_TERMINAL_KEY_TAB || keysym == GUAC_TERMINAL_KEY_KP_TAB)
return guac_terminal_send_string(term, GUAC_TERMINAL_ASCII_TAB);

/* Enter */
if (keysym == GUAC_TERMINAL_KEY_ENTER || keysym == GUAC_TERMINAL_KEY_KP_ENTER)
return guac_terminal_send_string(term, GUAC_TERMINAL_ASCII_CR);

/* Esc */
if (keysym == GUAC_TERMINAL_KEY_ESCAPE)
return guac_terminal_send_string(term, GUAC_TERMINAL_ASCII_ESCAPE);

/* Home */
if (keysym == GUAC_TERMINAL_KEY_HOME || keysym == GUAC_TERMINAL_KEY_KP_HOME)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_HOME);

/* Arrow keys w/ application cursor */
if (term->application_cursor_keys) {
if (keysym == 0xFF51 || keysym == 0xFF96) return guac_terminal_send_string(term, "\x1BOD"); /* Left */
if (keysym == 0xFF52 || keysym == 0xFF97) return guac_terminal_send_string(term, "\x1BOA"); /* Up */
if (keysym == 0xFF53 || keysym == 0xFF98) return guac_terminal_send_string(term, "\x1BOC"); /* Right */
if (keysym == 0xFF54 || keysym == 0xFF99) return guac_terminal_send_string(term, "\x1BOB"); /* Down */

/* Left */
if (keysym == GUAC_TERMINAL_KEY_LEFT || keysym == GUAC_TERMINAL_KEY_KP_LEFT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_LEFT);

/* Up */
if (keysym == GUAC_TERMINAL_KEY_UP || keysym == GUAC_TERMINAL_KEY_KP_UP)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_UP);

/* Right */
if (keysym == GUAC_TERMINAL_KEY_RIGHT || keysym == GUAC_TERMINAL_KEY_KP_RIGHT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_RIGHT);

/* Down */
if (keysym == GUAC_TERMINAL_KEY_DOWN || keysym == GUAC_TERMINAL_KEY_KP_DOWN)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_APP_CURSOR_DOWN);
}
else {
if (keysym == 0xFF51 || keysym == 0xFF96) return guac_terminal_send_string(term, "\x1B[D"); /* Left */
if (keysym == 0xFF52 || keysym == 0xFF97) return guac_terminal_send_string(term, "\x1B[A"); /* Up */
if (keysym == 0xFF53 || keysym == 0xFF98) return guac_terminal_send_string(term, "\x1B[C"); /* Right */
if (keysym == 0xFF54 || keysym == 0xFF99) return guac_terminal_send_string(term, "\x1B[B"); /* Down */

/* Left */
if (keysym == GUAC_TERMINAL_KEY_LEFT || keysym == GUAC_TERMINAL_KEY_KP_LEFT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_CURSOR_LEFT);

/* Up */
if (keysym == GUAC_TERMINAL_KEY_UP || keysym == GUAC_TERMINAL_KEY_KP_UP)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_CURSOR_UP);

/* Right */
if (keysym == GUAC_TERMINAL_KEY_RIGHT || keysym == GUAC_TERMINAL_KEY_KP_RIGHT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_CURSOR_RIGHT);

/* Down */
if (keysym == GUAC_TERMINAL_KEY_DOWN || keysym == GUAC_TERMINAL_KEY_KP_DOWN)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_CURSOR_DOWN);
}

if (keysym == 0xFF55 || keysym == 0xFF9A) return guac_terminal_send_string(term, "\x1B[5~"); /* Page up */
if (keysym == 0xFF56 || keysym == 0xFF9B) return guac_terminal_send_string(term, "\x1B[6~"); /* Page down */
if (keysym == 0xFF57 || keysym == 0xFF9C) return guac_terminal_send_string(term, "\x1B[4~"); /* End */
/* Page up */
if (keysym == GUAC_TERMINAL_KEY_PAGEUP || keysym == GUAC_TERMINAL_KEY_KP_PAGEUP)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_PAGEUP);

/* Page down */
if (keysym == GUAC_TERMINAL_KEY_PAGEDOWN || keysym == GUAC_TERMINAL_KEY_KP_PAGEDOWN)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_PAGEDOWN);

/* End */
if (keysym == GUAC_TERMINAL_KEY_END || keysym == GUAC_TERMINAL_KEY_KP_END)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_END);

/* Insert */
if (keysym == GUAC_TERMINAL_KEY_INSERT || keysym == GUAC_TERMINAL_KEY_KP_INSERT)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_INSERT);

/* F1 */
if (keysym == GUAC_TERMINAL_KEY_F1 || keysym == GUAC_TERMINAL_KEY_KP_F1)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F1);

/* F2 */
if (keysym == GUAC_TERMINAL_KEY_F2 || keysym == GUAC_TERMINAL_KEY_KP_F2)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F2);

/* F3 */
if (keysym == GUAC_TERMINAL_KEY_F3 || keysym == GUAC_TERMINAL_KEY_KP_F3)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F3);

/* F4 */
if (keysym == GUAC_TERMINAL_KEY_F4 || keysym == GUAC_TERMINAL_KEY_KP_F4)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F4);

/* F5 */
if (keysym == GUAC_TERMINAL_KEY_F5)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F5);

/* F6 */
if (keysym == GUAC_TERMINAL_KEY_F6)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F6);

/* F7 */
if (keysym == GUAC_TERMINAL_KEY_F7)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F7);

/* F8 */
if (keysym == GUAC_TERMINAL_KEY_F8)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F8);

/* F9 */
if (keysym == GUAC_TERMINAL_KEY_F9)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F9);

if (keysym == 0xFF63 || keysym == 0xFF9E) return guac_terminal_send_string(term, "\x1B[2~"); /* Insert */
/* F10 */
if (keysym == GUAC_TERMINAL_KEY_F10)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F10);

if (keysym == 0xFFBE || keysym == 0xFF91) return guac_terminal_send_string(term, "\x1B[[A"); /* F1 */
if (keysym == 0xFFBF || keysym == 0xFF92) return guac_terminal_send_string(term, "\x1B[[B"); /* F2 */
if (keysym == 0xFFC0 || keysym == 0xFF93) return guac_terminal_send_string(term, "\x1B[[C"); /* F3 */
if (keysym == 0xFFC1 || keysym == 0xFF94) return guac_terminal_send_string(term, "\x1B[[D"); /* F4 */
if (keysym == 0xFFC2) return guac_terminal_send_string(term, "\x1B[[E"); /* F5 */
/* F11 */
if (keysym == GUAC_TERMINAL_KEY_F11)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F11);

if (keysym == 0xFFC3) return guac_terminal_send_string(term, "\x1B[17~"); /* F6 */
if (keysym == 0xFFC4) return guac_terminal_send_string(term, "\x1B[18~"); /* F7 */
if (keysym == 0xFFC5) return guac_terminal_send_string(term, "\x1B[19~"); /* F8 */
if (keysym == 0xFFC6) return guac_terminal_send_string(term, "\x1B[20~"); /* F9 */
if (keysym == 0xFFC7) return guac_terminal_send_string(term, "\x1B[21~"); /* F10 */
if (keysym == 0xFFC8) return guac_terminal_send_string(term, "\x1B[22~"); /* F11 */
if (keysym == 0xFFC9) return guac_terminal_send_string(term, "\x1B[23~"); /* F12 */
/* F12 */
if (keysym == GUAC_TERMINAL_KEY_F12)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_F12);

if (keysym == 0xFFFF || keysym == 0xFF9F) return guac_terminal_send_string(term, "\x1B[3~"); /* Delete */
/* Delete */
if (keysym == GUAC_TERMINAL_KEY_DELETE || keysym == GUAC_TERMINAL_KEY_KP_DELETE)
return guac_terminal_send_string(term, GUAC_TERMINAL_ESC_SEQ_DELETE);

/* Ignore unknown keys */
guac_client_log(term->client, GUAC_LOG_DEBUG,
Expand Down
Loading
Loading