示例#1
0
/**
 * Sends the given character to the terminal at the given row and column,
 * rendering the character immediately. This bypasses the guac_terminal_display
 * mechanism and is intended for flushing of updates only.
 */
int __guac_terminal_set(guac_terminal_display* display, int row, int col, int codepoint) {

    int width;

    int bytes;
    char utf8[4];

    /* Use foreground color */
    const guac_terminal_color* color =
        &guac_terminal_palette[display->glyph_foreground];

    /* Use background color */
    const guac_terminal_color* background =
        &guac_terminal_palette[display->glyph_background];

    cairo_surface_t* surface;
    cairo_t* cairo;
    int surface_width, surface_height;
   
    PangoLayout* layout;
    int layout_width, layout_height;
    int ideal_layout_width, ideal_layout_height;

    /* Calculate width in columns */
    width = wcwidth(codepoint);
    if (width < 0)
        width = 1;

    /* Do nothing if glyph is empty */
    if (width == 0)
        return 0;

    /* Convert to UTF-8 */
    bytes = guac_terminal_encode_utf8(codepoint, utf8);

    surface_width = width * display->char_width;
    surface_height = display->char_height;

    ideal_layout_width = surface_width * PANGO_SCALE;
    ideal_layout_height = surface_height * PANGO_SCALE;

    /* Prepare surface */
    surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
                                         surface_width, surface_height);
    cairo = cairo_create(surface);

    /* Fill background */
    cairo_set_source_rgb(cairo,
            background->red   / 255.0,
            background->green / 255.0,
            background->blue  / 255.0);

    cairo_rectangle(cairo, 0, 0, surface_width, surface_height); 
    cairo_fill(cairo);

    /* Get layout */
    layout = pango_cairo_create_layout(cairo);
    pango_layout_set_font_description(layout, display->font_desc);
    pango_layout_set_text(layout, utf8, bytes);
    pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);

    pango_layout_get_size(layout, &layout_width, &layout_height);

    /* If layout bigger than available space, scale it back */
    if (layout_width > ideal_layout_width || layout_height > ideal_layout_height) {

        double scale = fmin(ideal_layout_width  / (double) layout_width,
                            ideal_layout_height / (double) layout_height);

        cairo_scale(cairo, scale, scale);

        /* Update layout to reflect scaled surface */
        pango_layout_set_width(layout, ideal_layout_width / scale);
        pango_layout_set_height(layout, ideal_layout_height / scale);
        pango_cairo_update_layout(cairo, layout);

    }

    /* Draw */
    cairo_set_source_rgb(cairo,
            color->red   / 255.0,
            color->green / 255.0,
            color->blue  / 255.0);

    cairo_move_to(cairo, 0.0, 0.0);
    pango_cairo_show_layout(cairo, layout);

    /* Draw */
    guac_common_surface_draw(display->display_surface,
        display->char_width * col,
        display->char_height * row,
        surface);

    /* Free all */
    g_object_unref(layout);
    cairo_destroy(cairo);
    cairo_surface_destroy(surface);

    return 0;

}
示例#2
0
int ssh_guac_client_key_handler(guac_client* client, int keysym, int pressed) {

    ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
    guac_terminal* term = client_data->term;

    /* Hide mouse cursor if not already hidden */
    if (client_data->current_cursor != client_data->blank_cursor) {
        pthread_mutex_lock(&(term->lock));

        client_data->current_cursor = client_data->blank_cursor;
        guac_ssh_set_cursor(client, client_data->blank_cursor);
        guac_socket_flush(client->socket);

        pthread_mutex_unlock(&(term->lock));
    }

    /* Track modifiers */
    if (keysym == 0xFFE3)
        client_data->mod_ctrl = pressed;
    else if (keysym == 0xFFE9)
        client_data->mod_alt = pressed;
    else if (keysym == 0xFFE1)
        client_data->mod_shift = pressed;
        
    /* If key pressed */
    else if (pressed) {

        /* Ctrl+Shift+V shortcut for paste */
        if (keysym == 'V' && client_data->mod_ctrl)
            return guac_terminal_send_data(term, client_data->clipboard->buffer, client_data->clipboard->length);

        /* Shift+PgUp / Shift+PgDown shortcuts for scrolling */
        if (client_data->mod_shift) {

            /* Page up */
            if (keysym == 0xFF55) {
                pthread_mutex_lock(&(term->lock));
                guac_terminal_scroll_display_up(term, term->term_height);
                pthread_mutex_unlock(&(term->lock));
                return 0;
            }

            /* Page down */
            if (keysym == 0xFF56) {
                pthread_mutex_lock(&(term->lock));
                guac_terminal_scroll_display_down(term, term->term_height);
                pthread_mutex_unlock(&(term->lock));
                return 0;
            }

        }

        /* Reset scroll */
        if (term->scroll_offset != 0) {
            pthread_mutex_lock(&(term->lock));
            guac_terminal_scroll_display_down(term, term->scroll_offset);
            pthread_mutex_unlock(&(term->lock));
        }

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

        /* Translate Ctrl+letter to control code */ 
        if (client_data->mod_ctrl) {

            char data;

            /* If valid control code, send it */
            if (keysym >= 'A' && keysym <= 'Z')
                data = (char) (keysym - 'A' + 1);
            else if (keysym >= 'a' && keysym <= 'z')
                data = (char) (keysym - 'a' + 1);

            /* Otherwise ignore */
            else
                return 0;

            return guac_terminal_send_data(term, &data, 1);

        }

        /* Translate Unicode to UTF-8 */
        else if ((keysym >= 0x00 && keysym <= 0xFF) || ((keysym & 0xFFFF0000) == 0x01000000)) {

            int length;
            char data[5];

            length = guac_terminal_encode_utf8(keysym & 0xFFFF, data);
            return guac_terminal_send_data(term, data, length);

        }

        /* Non-printable keys */
        else {

            if (keysym == 0xFF08) return guac_terminal_send_string(term, "\x7F"); /* Backspace */
            if (keysym == 0xFF09) return guac_terminal_send_string(term, "\x09"); /* Tab */
            if (keysym == 0xFF0D) return guac_terminal_send_string(term, "\x0D"); /* Enter */
            if (keysym == 0xFF1B) return guac_terminal_send_string(term, "\x1B"); /* Esc */

            if (keysym == 0xFF50) return guac_terminal_send_string(term, "\x1B[1~"); /* Home */

            /* Arrow keys w/ application cursor */
            if (term->application_cursor_keys) {
                if (keysym == 0xFF51) return guac_terminal_send_string(term, "\x1BOD"); /* Left */
                if (keysym == 0xFF52) return guac_terminal_send_string(term, "\x1BOA"); /* Up */
                if (keysym == 0xFF53) return guac_terminal_send_string(term, "\x1BOC"); /* Right */
                if (keysym == 0xFF54) return guac_terminal_send_string(term, "\x1BOB"); /* Down */
            }
            else {
                if (keysym == 0xFF51) return guac_terminal_send_string(term, "\x1B[D"); /* Left */
                if (keysym == 0xFF52) return guac_terminal_send_string(term, "\x1B[A"); /* Up */
                if (keysym == 0xFF53) return guac_terminal_send_string(term, "\x1B[C"); /* Right */
                if (keysym == 0xFF54) return guac_terminal_send_string(term, "\x1B[B"); /* Down */
            }

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

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

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

            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 */

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

            /* Ignore unknown keys */
        }

    }

    return 0;

}