GUACAMOLE-630: Merge allow font parameters of active terminal session to be changed.
This commit is contained in:
commit
381c5d1a76
@ -26,15 +26,44 @@
|
|||||||
#include <guacamole/socket.h>
|
#include <guacamole/socket.h>
|
||||||
#include <guacamole/user.h>
|
#include <guacamole/user.h>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All SSH connection settings which may be updated by unprivileged users
|
||||||
|
* through "argv" streams.
|
||||||
|
*/
|
||||||
|
typedef enum guac_ssh_argv_setting {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color scheme of the terminal.
|
||||||
|
*/
|
||||||
|
GUAC_SSH_ARGV_SETTING_COLOR_SCHEME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the font family used by the terminal.
|
||||||
|
*/
|
||||||
|
GUAC_SSH_ARGV_SETTING_FONT_NAME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the font used by the terminal, in points.
|
||||||
|
*/
|
||||||
|
GUAC_SSH_ARGV_SETTING_FONT_SIZE
|
||||||
|
|
||||||
|
} guac_ssh_argv_setting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value or current status of a connection parameter received over an
|
* The value or current status of a connection parameter received over an
|
||||||
* "argv" stream.
|
* "argv" stream.
|
||||||
*/
|
*/
|
||||||
typedef struct guac_ssh_argv {
|
typedef struct guac_ssh_argv {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The specific setting being updated.
|
||||||
|
*/
|
||||||
|
guac_ssh_argv_setting setting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer space for containing the received argument value.
|
* Buffer space for containing the received argument value.
|
||||||
*/
|
*/
|
||||||
@ -81,16 +110,51 @@ static int guac_ssh_argv_blob_handler(guac_user* user,
|
|||||||
static int guac_ssh_argv_end_handler(guac_user* user,
|
static int guac_ssh_argv_end_handler(guac_user* user,
|
||||||
guac_stream* stream) {
|
guac_stream* stream) {
|
||||||
|
|
||||||
|
int size;
|
||||||
|
|
||||||
guac_client* client = user->client;
|
guac_client* client = user->client;
|
||||||
guac_ssh_client* telnet_client = (guac_ssh_client*) client->data;
|
guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;
|
||||||
guac_terminal* terminal = telnet_client->term;
|
guac_terminal* terminal = ssh_client->term;
|
||||||
|
|
||||||
/* Append null terminator to value */
|
/* Append null terminator to value */
|
||||||
guac_ssh_argv* argv = (guac_ssh_argv*) stream->data;
|
guac_ssh_argv* argv = (guac_ssh_argv*) stream->data;
|
||||||
argv->buffer[argv->length] = '\0';
|
argv->buffer[argv->length] = '\0';
|
||||||
|
|
||||||
/* Update color scheme */
|
/* Apply changes to chosen setting */
|
||||||
guac_terminal_apply_color_scheme(terminal, argv->buffer);
|
switch (argv->setting) {
|
||||||
|
|
||||||
|
/* Update color scheme */
|
||||||
|
case GUAC_SSH_ARGV_SETTING_COLOR_SCHEME:
|
||||||
|
guac_terminal_apply_color_scheme(terminal, argv->buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Update font name */
|
||||||
|
case GUAC_SSH_ARGV_SETTING_FONT_NAME:
|
||||||
|
guac_terminal_apply_font(terminal, argv->buffer, -1, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Update font size */
|
||||||
|
case GUAC_SSH_ARGV_SETTING_FONT_SIZE:
|
||||||
|
|
||||||
|
/* Update only if font size is sane */
|
||||||
|
size = atoi(argv->buffer);
|
||||||
|
if (size > 0) {
|
||||||
|
guac_terminal_apply_font(terminal, NULL, size,
|
||||||
|
ssh_client->settings->resolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update SSH pty size if connected */
|
||||||
|
if (ssh_client->term_channel != NULL) {
|
||||||
|
pthread_mutex_lock(&(ssh_client->term_channel_lock));
|
||||||
|
libssh2_channel_request_pty_size(ssh_client->term_channel,
|
||||||
|
terminal->term_width, terminal->term_height);
|
||||||
|
pthread_mutex_unlock(&(ssh_client->term_channel_lock));
|
||||||
|
}
|
||||||
|
|
||||||
free(argv);
|
free(argv);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -99,28 +163,36 @@ static int guac_ssh_argv_end_handler(guac_user* user,
|
|||||||
int guac_ssh_argv_handler(guac_user* user, guac_stream* stream,
|
int guac_ssh_argv_handler(guac_user* user, guac_stream* stream,
|
||||||
char* mimetype, char* name) {
|
char* mimetype, char* name) {
|
||||||
|
|
||||||
/* Allow users to update the color scheme */
|
guac_ssh_argv_setting setting;
|
||||||
if (strcmp(name, "color-scheme") == 0) {
|
|
||||||
|
|
||||||
guac_ssh_argv* argv = malloc(sizeof(guac_ssh_argv));
|
/* Allow users to update the color scheme and font details */
|
||||||
argv->length = 0;
|
if (strcmp(name, "color-scheme") == 0)
|
||||||
|
setting = GUAC_SSH_ARGV_SETTING_COLOR_SCHEME;
|
||||||
/* Prepare stream to receive argument value */
|
else if (strcmp(name, "font-name") == 0)
|
||||||
stream->blob_handler = guac_ssh_argv_blob_handler;
|
setting = GUAC_SSH_ARGV_SETTING_FONT_NAME;
|
||||||
stream->end_handler = guac_ssh_argv_end_handler;
|
else if (strcmp(name, "font-size") == 0)
|
||||||
stream->data = argv;
|
setting = GUAC_SSH_ARGV_SETTING_FONT_SIZE;
|
||||||
|
|
||||||
/* Signal stream is ready */
|
|
||||||
guac_protocol_send_ack(user->socket, stream, "Ready for color "
|
|
||||||
"scheme.", GUAC_PROTOCOL_STATUS_SUCCESS);
|
|
||||||
guac_socket_flush(user->socket);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No other connection parameters may be updated */
|
/* No other connection parameters may be updated */
|
||||||
guac_protocol_send_ack(user->socket, stream, "Not allowed.",
|
else {
|
||||||
GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
|
guac_protocol_send_ack(user->socket, stream, "Not allowed.",
|
||||||
|
GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
|
||||||
|
guac_socket_flush(user->socket);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
guac_ssh_argv* argv = malloc(sizeof(guac_ssh_argv));
|
||||||
|
argv->setting = setting;
|
||||||
|
argv->length = 0;
|
||||||
|
|
||||||
|
/* Prepare stream to receive argument value */
|
||||||
|
stream->blob_handler = guac_ssh_argv_blob_handler;
|
||||||
|
stream->end_handler = guac_ssh_argv_end_handler;
|
||||||
|
stream->data = argv;
|
||||||
|
|
||||||
|
/* Signal stream is ready */
|
||||||
|
guac_protocol_send_ack(user->socket, stream, "Ready for updated "
|
||||||
|
"parameter.", GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||||
guac_socket_flush(user->socket);
|
guac_socket_flush(user->socket);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -29,12 +29,40 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All telnet connection settings which may be updated by unprivileged users
|
||||||
|
* through "argv" streams.
|
||||||
|
*/
|
||||||
|
typedef enum guac_telnet_argv_setting {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color scheme of the terminal.
|
||||||
|
*/
|
||||||
|
GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the font family used by the terminal.
|
||||||
|
*/
|
||||||
|
GUAC_TELNET_ARGV_SETTING_FONT_NAME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the font used by the terminal, in points.
|
||||||
|
*/
|
||||||
|
GUAC_TELNET_ARGV_SETTING_FONT_SIZE
|
||||||
|
|
||||||
|
} guac_telnet_argv_setting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value or current status of a connection parameter received over an
|
* The value or current status of a connection parameter received over an
|
||||||
* "argv" stream.
|
* "argv" stream.
|
||||||
*/
|
*/
|
||||||
typedef struct guac_telnet_argv {
|
typedef struct guac_telnet_argv {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The specific setting being updated.
|
||||||
|
*/
|
||||||
|
guac_telnet_argv_setting setting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer space for containing the received argument value.
|
* Buffer space for containing the received argument value.
|
||||||
*/
|
*/
|
||||||
@ -81,6 +109,8 @@ static int guac_telnet_argv_blob_handler(guac_user* user,
|
|||||||
static int guac_telnet_argv_end_handler(guac_user* user,
|
static int guac_telnet_argv_end_handler(guac_user* user,
|
||||||
guac_stream* stream) {
|
guac_stream* stream) {
|
||||||
|
|
||||||
|
int size;
|
||||||
|
|
||||||
guac_client* client = user->client;
|
guac_client* client = user->client;
|
||||||
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
|
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
|
||||||
guac_terminal* terminal = telnet_client->term;
|
guac_terminal* terminal = telnet_client->term;
|
||||||
@ -89,8 +119,38 @@ static int guac_telnet_argv_end_handler(guac_user* user,
|
|||||||
guac_telnet_argv* argv = (guac_telnet_argv*) stream->data;
|
guac_telnet_argv* argv = (guac_telnet_argv*) stream->data;
|
||||||
argv->buffer[argv->length] = '\0';
|
argv->buffer[argv->length] = '\0';
|
||||||
|
|
||||||
/* Update color scheme */
|
/* Apply changes to chosen setting */
|
||||||
guac_terminal_apply_color_scheme(terminal, argv->buffer);
|
switch (argv->setting) {
|
||||||
|
|
||||||
|
/* Update color scheme */
|
||||||
|
case GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME:
|
||||||
|
guac_terminal_apply_color_scheme(terminal, argv->buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Update font name */
|
||||||
|
case GUAC_TELNET_ARGV_SETTING_FONT_NAME:
|
||||||
|
guac_terminal_apply_font(terminal, argv->buffer, -1, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Update font size */
|
||||||
|
case GUAC_TELNET_ARGV_SETTING_FONT_SIZE:
|
||||||
|
|
||||||
|
/* Update only if font size is sane */
|
||||||
|
size = atoi(argv->buffer);
|
||||||
|
if (size > 0) {
|
||||||
|
guac_terminal_apply_font(terminal, NULL, size,
|
||||||
|
telnet_client->settings->resolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update terminal window size if connected */
|
||||||
|
if (telnet_client->telnet != NULL && telnet_client->naws_enabled)
|
||||||
|
guac_telnet_send_naws(telnet_client->telnet, terminal->term_width,
|
||||||
|
terminal->term_height);
|
||||||
|
|
||||||
free(argv);
|
free(argv);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -99,28 +159,36 @@ static int guac_telnet_argv_end_handler(guac_user* user,
|
|||||||
int guac_telnet_argv_handler(guac_user* user, guac_stream* stream,
|
int guac_telnet_argv_handler(guac_user* user, guac_stream* stream,
|
||||||
char* mimetype, char* name) {
|
char* mimetype, char* name) {
|
||||||
|
|
||||||
/* Allow users to update the color scheme */
|
guac_telnet_argv_setting setting;
|
||||||
if (strcmp(name, "color-scheme") == 0) {
|
|
||||||
|
|
||||||
guac_telnet_argv* argv = malloc(sizeof(guac_telnet_argv));
|
/* Allow users to update the color scheme and font details */
|
||||||
argv->length = 0;
|
if (strcmp(name, "color-scheme") == 0)
|
||||||
|
setting = GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME;
|
||||||
/* Prepare stream to receive argument value */
|
else if (strcmp(name, "font-name") == 0)
|
||||||
stream->blob_handler = guac_telnet_argv_blob_handler;
|
setting = GUAC_TELNET_ARGV_SETTING_FONT_NAME;
|
||||||
stream->end_handler = guac_telnet_argv_end_handler;
|
else if (strcmp(name, "font-size") == 0)
|
||||||
stream->data = argv;
|
setting = GUAC_TELNET_ARGV_SETTING_FONT_SIZE;
|
||||||
|
|
||||||
/* Signal stream is ready */
|
|
||||||
guac_protocol_send_ack(user->socket, stream, "Ready for color "
|
|
||||||
"scheme.", GUAC_PROTOCOL_STATUS_SUCCESS);
|
|
||||||
guac_socket_flush(user->socket);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No other connection parameters may be updated */
|
/* No other connection parameters may be updated */
|
||||||
guac_protocol_send_ack(user->socket, stream, "Not allowed.",
|
else {
|
||||||
GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
|
guac_protocol_send_ack(user->socket, stream, "Not allowed.",
|
||||||
|
GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
|
||||||
|
guac_socket_flush(user->socket);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
guac_telnet_argv* argv = malloc(sizeof(guac_telnet_argv));
|
||||||
|
argv->setting = setting;
|
||||||
|
argv->length = 0;
|
||||||
|
|
||||||
|
/* Prepare stream to receive argument value */
|
||||||
|
stream->blob_handler = guac_telnet_argv_blob_handler;
|
||||||
|
stream->end_handler = guac_telnet_argv_end_handler;
|
||||||
|
stream->data = argv;
|
||||||
|
|
||||||
|
/* Signal stream is ready */
|
||||||
|
guac_protocol_send_ack(user->socket, stream, "Ready for updated "
|
||||||
|
"parameter.", GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||||
guac_socket_flush(user->socket);
|
guac_socket_flush(user->socket);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -206,15 +206,15 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
|
|||||||
guac_terminal_color* foreground, guac_terminal_color* background,
|
guac_terminal_color* foreground, guac_terminal_color* background,
|
||||||
guac_terminal_color (*palette)[256]) {
|
guac_terminal_color (*palette)[256]) {
|
||||||
|
|
||||||
PangoFontMap* font_map;
|
|
||||||
PangoFont* font;
|
|
||||||
PangoFontMetrics* metrics;
|
|
||||||
PangoContext* context;
|
|
||||||
|
|
||||||
/* Allocate display */
|
/* Allocate display */
|
||||||
guac_terminal_display* display = malloc(sizeof(guac_terminal_display));
|
guac_terminal_display* display = malloc(sizeof(guac_terminal_display));
|
||||||
display->client = client;
|
display->client = client;
|
||||||
|
|
||||||
|
/* Initially no font loaded */
|
||||||
|
display->font_desc = NULL;
|
||||||
|
display->char_width = 0;
|
||||||
|
display->char_height = 0;
|
||||||
|
|
||||||
/* Create default surface */
|
/* Create default surface */
|
||||||
display->display_layer = guac_client_alloc_layer(client);
|
display->display_layer = guac_client_alloc_layer(client);
|
||||||
display->select_layer = guac_client_alloc_layer(client);
|
display->select_layer = guac_client_alloc_layer(client);
|
||||||
@ -225,42 +225,10 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
|
|||||||
guac_protocol_send_move(client->socket, display->select_layer,
|
guac_protocol_send_move(client->socket, display->select_layer,
|
||||||
display->display_layer, 0, 0, 0);
|
display->display_layer, 0, 0, 0);
|
||||||
|
|
||||||
/* Get font */
|
|
||||||
display->font_desc = pango_font_description_new();
|
|
||||||
pango_font_description_set_family(display->font_desc, font_name);
|
|
||||||
pango_font_description_set_weight(display->font_desc, PANGO_WEIGHT_NORMAL);
|
|
||||||
pango_font_description_set_size(display->font_desc,
|
|
||||||
font_size * PANGO_SCALE * dpi / 96);
|
|
||||||
|
|
||||||
font_map = pango_cairo_font_map_get_default();
|
|
||||||
context = pango_font_map_create_context(font_map);
|
|
||||||
|
|
||||||
font = pango_font_map_load_font(font_map, context, display->font_desc);
|
|
||||||
if (font == NULL) {
|
|
||||||
guac_client_abort(display->client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to get font \"%s\"", font_name);
|
|
||||||
free(display);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
metrics = pango_font_get_metrics(font, NULL);
|
|
||||||
if (metrics == NULL) {
|
|
||||||
guac_client_abort(display->client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
|
||||||
"Unable to get font metrics for font \"%s\"", font_name);
|
|
||||||
free(display);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
display->default_foreground = display->glyph_foreground = *foreground;
|
display->default_foreground = display->glyph_foreground = *foreground;
|
||||||
display->default_background = display->glyph_background = *background;
|
display->default_background = display->glyph_background = *background;
|
||||||
display->default_palette = palette;
|
display->default_palette = palette;
|
||||||
|
|
||||||
/* Calculate character dimensions */
|
|
||||||
display->char_width =
|
|
||||||
pango_font_metrics_get_approximate_digit_width(metrics) / PANGO_SCALE;
|
|
||||||
display->char_height =
|
|
||||||
(pango_font_metrics_get_descent(metrics)
|
|
||||||
+ pango_font_metrics_get_ascent(metrics)) / PANGO_SCALE;
|
|
||||||
|
|
||||||
/* Initially empty */
|
/* Initially empty */
|
||||||
display->width = 0;
|
display->width = 0;
|
||||||
display->height = 0;
|
display->height = 0;
|
||||||
@ -269,12 +237,23 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
|
|||||||
/* Initially nothing selected */
|
/* Initially nothing selected */
|
||||||
display->text_selected = false;
|
display->text_selected = false;
|
||||||
|
|
||||||
|
/* Attempt to load font */
|
||||||
|
if (guac_terminal_display_set_font(display, font_name, font_size, dpi)) {
|
||||||
|
guac_client_abort(display->client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Unable to set initial font \"%s\"", font_name);
|
||||||
|
free(display);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return display;
|
return display;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_terminal_display_free(guac_terminal_display* display) {
|
void guac_terminal_display_free(guac_terminal_display* display) {
|
||||||
|
|
||||||
|
/* Free font description */
|
||||||
|
pango_font_description_free(display->font_desc);
|
||||||
|
|
||||||
/* Free default palette. */
|
/* Free default palette. */
|
||||||
free(display->default_palette);
|
free(display->default_palette);
|
||||||
|
|
||||||
@ -966,4 +945,78 @@ void guac_terminal_display_clear_select(guac_terminal_display* display) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int guac_terminal_display_set_font(guac_terminal_display* display,
|
||||||
|
const char* font_name, int font_size, int dpi) {
|
||||||
|
|
||||||
|
PangoFontDescription* font_desc;
|
||||||
|
|
||||||
|
/* Build off existing font description if possible */
|
||||||
|
if (display->font_desc != NULL)
|
||||||
|
font_desc = pango_font_description_copy(display->font_desc);
|
||||||
|
|
||||||
|
/* Create new font description if there is nothing to copy */
|
||||||
|
else {
|
||||||
|
font_desc = pango_font_description_new();
|
||||||
|
pango_font_description_set_weight(font_desc, PANGO_WEIGHT_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Optionally update font name */
|
||||||
|
if (font_name != NULL)
|
||||||
|
pango_font_description_set_family(font_desc, font_name);
|
||||||
|
|
||||||
|
/* Optionally update size */
|
||||||
|
if (font_size != -1) {
|
||||||
|
pango_font_description_set_size(font_desc,
|
||||||
|
font_size * PANGO_SCALE * dpi / 96);
|
||||||
|
}
|
||||||
|
|
||||||
|
PangoFontMap* font_map = pango_cairo_font_map_get_default();
|
||||||
|
PangoContext* context = pango_font_map_create_context(font_map);
|
||||||
|
|
||||||
|
/* Load font from font map */
|
||||||
|
PangoFont* font = pango_font_map_load_font(font_map, context, font_desc);
|
||||||
|
if (font == NULL) {
|
||||||
|
guac_client_log(display->client, GUAC_LOG_INFO, "Unable to load "
|
||||||
|
"font \"%s\"", pango_font_description_get_family(font_desc));
|
||||||
|
pango_font_description_free(font_desc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get metrics from loaded font */
|
||||||
|
PangoFontMetrics* metrics = pango_font_get_metrics(font, NULL);
|
||||||
|
if (metrics == NULL) {
|
||||||
|
guac_client_log(display->client, GUAC_LOG_INFO, "Unable to get font "
|
||||||
|
"metrics for font \"%s\"",
|
||||||
|
pango_font_description_get_family(font_desc));
|
||||||
|
pango_font_description_free(font_desc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save effective size of current display */
|
||||||
|
int pixel_width = display->width * display->char_width;
|
||||||
|
int pixel_height = display->height * display->char_height;
|
||||||
|
|
||||||
|
/* Calculate character dimensions using metrics */
|
||||||
|
display->char_width =
|
||||||
|
pango_font_metrics_get_approximate_digit_width(metrics) / PANGO_SCALE;
|
||||||
|
display->char_height =
|
||||||
|
(pango_font_metrics_get_descent(metrics)
|
||||||
|
+ pango_font_metrics_get_ascent(metrics)) / PANGO_SCALE;
|
||||||
|
|
||||||
|
/* Atomically replace old font description */
|
||||||
|
PangoFontDescription* old_font_desc = display->font_desc;
|
||||||
|
display->font_desc = font_desc;
|
||||||
|
pango_font_description_free(old_font_desc);
|
||||||
|
|
||||||
|
/* Recalculate dimensions which will fit within current surface */
|
||||||
|
int new_width = pixel_width / display->char_width;
|
||||||
|
int new_height = pixel_height / display->char_height;
|
||||||
|
|
||||||
|
/* Resize display if dimensions have changed */
|
||||||
|
if (new_width != display->width || new_height != display->height)
|
||||||
|
guac_terminal_display_resize(display, new_width, new_height);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -360,6 +360,10 @@ guac_terminal* guac_terminal_create(guac_client* client,
|
|||||||
term->upload_path_handler = NULL;
|
term->upload_path_handler = NULL;
|
||||||
term->file_download_handler = NULL;
|
term->file_download_handler = NULL;
|
||||||
|
|
||||||
|
/* Set size of available screen area */
|
||||||
|
term->outer_width = width;
|
||||||
|
term->outer_height = height;
|
||||||
|
|
||||||
/* Init modified flag and conditional */
|
/* Init modified flag and conditional */
|
||||||
term->modified = 0;
|
term->modified = 0;
|
||||||
pthread_cond_init(&(term->modified_cond), NULL);
|
pthread_cond_init(&(term->modified_cond), NULL);
|
||||||
@ -1338,6 +1342,10 @@ int guac_terminal_resize(guac_terminal* terminal, int width, int height) {
|
|||||||
/* Acquire exclusive access to terminal */
|
/* Acquire exclusive access to terminal */
|
||||||
guac_terminal_lock(terminal);
|
guac_terminal_lock(terminal);
|
||||||
|
|
||||||
|
/* Set size of available screen area */
|
||||||
|
terminal->outer_width = width;
|
||||||
|
terminal->outer_height = height;
|
||||||
|
|
||||||
/* Calculate available display area */
|
/* Calculate available display area */
|
||||||
int available_width = width - GUAC_TERMINAL_SCROLLBAR_WIDTH;
|
int available_width = width - GUAC_TERMINAL_SCROLLBAR_WIDTH;
|
||||||
if (available_width < 0)
|
if (available_width < 0)
|
||||||
@ -1968,3 +1976,27 @@ void guac_terminal_apply_color_scheme(guac_terminal* terminal,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void guac_terminal_apply_font(guac_terminal* terminal, const char* font_name,
|
||||||
|
int font_size, int dpi) {
|
||||||
|
|
||||||
|
guac_client* client = terminal->client;
|
||||||
|
guac_terminal_display* display = terminal->display;
|
||||||
|
|
||||||
|
if (guac_terminal_display_set_font(display, font_name, font_size, dpi))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Resize terminal to fit available region, now that font metrics may be
|
||||||
|
* different */
|
||||||
|
guac_terminal_resize(terminal, terminal->outer_width,
|
||||||
|
terminal->outer_height);
|
||||||
|
|
||||||
|
/* Redraw terminal text and background */
|
||||||
|
guac_terminal_repaint_default_layer(terminal, client->socket);
|
||||||
|
__guac_terminal_redraw_rect(terminal, 0, 0,
|
||||||
|
terminal->term_height - 1,
|
||||||
|
terminal->term_width - 1);
|
||||||
|
|
||||||
|
guac_terminal_notify(terminal);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -334,5 +334,35 @@ void guac_terminal_display_select(guac_terminal_display* display,
|
|||||||
*/
|
*/
|
||||||
void guac_terminal_display_clear_select(guac_terminal_display* display);
|
void guac_terminal_display_clear_select(guac_terminal_display* display);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alters the font of the terminal display. The available display area and the
|
||||||
|
* regular grid of character cells will be resized as necessary to compensate
|
||||||
|
* for any changes in font metrics.
|
||||||
|
*
|
||||||
|
* If successful, the terminal itself MUST be manually resized to take into
|
||||||
|
* account the new character dimensions, and MUST be manually redrawn. Failing
|
||||||
|
* to do so will result in graphical artifacts.
|
||||||
|
*
|
||||||
|
* @param display
|
||||||
|
* The display whose font family and/or size are being changed.
|
||||||
|
*
|
||||||
|
* @param font_name
|
||||||
|
* The name of the new font family, or NULL if the font family should
|
||||||
|
* remain unchanged.
|
||||||
|
*
|
||||||
|
* @param font_size
|
||||||
|
* The new font size, in points, or -1 if the font size should remain
|
||||||
|
* unchanged.
|
||||||
|
*
|
||||||
|
* @param dpi
|
||||||
|
* The resolution of the display in DPI. If the font size will not be
|
||||||
|
* changed (the font size given is -1), this value is ignored.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the font was successfully changed, non-zero otherwise.
|
||||||
|
*/
|
||||||
|
int guac_terminal_display_set_font(guac_terminal_display* display,
|
||||||
|
const char* font_name, int font_size, int dpi);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -277,6 +277,20 @@ struct guac_terminal {
|
|||||||
*/
|
*/
|
||||||
int requested_scrollback;
|
int requested_scrollback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The width of the space available to all components of the terminal, in
|
||||||
|
* pixels. This may include space which will not actually be used for
|
||||||
|
* character rendering.
|
||||||
|
*/
|
||||||
|
int outer_width;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The height of the space available to all components of the terminal, in
|
||||||
|
* pixels. This may include space which will not actually be used for
|
||||||
|
* character rendering.
|
||||||
|
*/
|
||||||
|
int outer_height;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The width of the terminal, in pixels.
|
* The width of the terminal, in pixels.
|
||||||
*/
|
*/
|
||||||
@ -1086,5 +1100,29 @@ int guac_terminal_available_scroll(guac_terminal* term);
|
|||||||
void guac_terminal_apply_color_scheme(guac_terminal* terminal,
|
void guac_terminal_apply_color_scheme(guac_terminal* terminal,
|
||||||
const char* color_scheme);
|
const char* color_scheme);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alters the font of the terminal. The terminal will automatically be redrawn
|
||||||
|
* and resized as necessary. If the terminal size changes, the remote side of
|
||||||
|
* the terminal session must be manually informed of that change or graphical
|
||||||
|
* artifacts may result.
|
||||||
|
*
|
||||||
|
* @param terminal
|
||||||
|
* The terminal whose font family and/or size are being changed.
|
||||||
|
*
|
||||||
|
* @param font_name
|
||||||
|
* The name of the new font family, or NULL if the font family should
|
||||||
|
* remain unchanged.
|
||||||
|
*
|
||||||
|
* @param font_size
|
||||||
|
* The new font size, in points, or -1 if the font size should remain
|
||||||
|
* unchanged.
|
||||||
|
*
|
||||||
|
* @param dpi
|
||||||
|
* The resolution of the display in DPI. If the font size will not be
|
||||||
|
* changed (the font size given is -1), this value is ignored.
|
||||||
|
*/
|
||||||
|
void guac_terminal_apply_font(guac_terminal* terminal, const char* font_name,
|
||||||
|
int font_size, int dpi);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user