Add font control variables to xrdp.ini

This commit adds the variables fv1_select and default_dpi to
xrdp.ini. These variables allow for a different font to be
loaded, depending on the DPI of the login screen.
This commit is contained in:
matt335672 2022-08-11 14:42:53 +01:00
parent d0c8e28d27
commit a417ab0542
7 changed files with 263 additions and 18 deletions

View File

@ -125,12 +125,12 @@ separator as the password supplied by the user and treats it as autologon. If no
defaults to \fBfalse\fP. defaults to \fBfalse\fP.
.TP .TP
\domain_user_separator\fP=\separator\fP \fBdomain_user_separator\fP=\fBseparator\fP
If specified the domain name supplied by the client is appended to the username separated If specified the domain name supplied by the client is appended to the username separated
by \fBseparator\fP. by \fBseparator\fP.
.TP .TP
\enable_token_login\fP=\fI[true|false]\fP \fBenable_token_login\fP=\fI[true|false]\fP
If set to \fB1\fP, \fBtrue\fP or \fByes\fP, \fBxrdp\fP requires clients to include username and If set to \fB1\fP, \fBtrue\fP or \fByes\fP, \fBxrdp\fP requires clients to include username and
password initial connection phase. In other words, xrdp doesn't allow clients to show login password initial connection phase. In other words, xrdp doesn't allow clients to show login
screen if set to true. If not specified, defaults to \fBfalse\fP. screen if set to true. If not specified, defaults to \fBfalse\fP.
@ -212,6 +212,18 @@ These options override the colors used internally by \fBxrdp\fP(8) to draw the l
Colors are defined using a hexadecimal (hex) notation for the combination of Red, Green, and Blue color values (RGB). Colors are defined using a hexadecimal (hex) notation for the combination of Red, Green, and Blue color values (RGB).
The lowest value that can be given to one of the light sources is 0 (hex 00). The lowest value that can be given to one of the light sources is 0 (hex 00).
The highest value is 255 (hex FF). The highest value is 255 (hex FF).
.TP
\fBfv1_select\fP=\fI130:sans-18.fv1,0:sans-10.fv1\fP
Selects a default fv1 font.
This parameter is a comma-separated list of DPI:name pairs. The list
is scanned from left-to-right. The font used is the first font whose DPI
value is less-than-or-equal to the vertical DPI of the monitor used for
the login screen.
.TP
\fBdefault_dpi\fP=\fI96\fP
Default DPI used for a monitor if the client does not send physical
size information.
.SH "LOGGING" .SH "LOGGING"
The following parameters can be used in the \fB[Logging]\fR section: The following parameters can be used in the \fB[Logging]\fR section:

View File

@ -343,7 +343,7 @@ xrdp_painter_line(struct xrdp_painter *self,
/* xrdp_font.c */ /* xrdp_font.c */
struct xrdp_font * struct xrdp_font *
xrdp_font_create(struct xrdp_wm *wm); xrdp_font_create(struct xrdp_wm *wm, unsigned int dpi);
void void
xrdp_font_delete(struct xrdp_font *self); xrdp_font_delete(struct xrdp_font *self);
int int
@ -387,6 +387,14 @@ int
get_keymaps(int keylayout, struct xrdp_keymap *keymap); get_keymaps(int keylayout, struct xrdp_keymap *keymap);
/* xrdp_login_wnd.c */ /* xrdp_login_wnd.c */
/**
* Gets the DPI of the login (primary) monitor
*
* @param self xrdp_wm instance
* @return DPI of primary monitor, or 0 if unavailable.
*/
unsigned int
xrdp_login_wnd_get_monitor_dpi(struct xrdp_wm *self);
int int
xrdp_login_wnd_create(struct xrdp_wm *self); xrdp_login_wnd_create(struct xrdp_wm *self);
int int
@ -394,7 +402,6 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp);
void void
xrdp_login_wnd_scale_config_values(struct xrdp_wm *self); xrdp_login_wnd_scale_config_values(struct xrdp_wm *self);
/* xrdp_bitmap_compress.c */ /* xrdp_bitmap_compress.c */
int int
xrdp_bitmap_compress(char *in_data, int width, int height, xrdp_bitmap_compress(char *in_data, int width, int height,

View File

@ -106,6 +106,17 @@ grey=dedede
#green=00ff00 #green=00ff00
#background=626c72 #background=626c72
;
; Select a default fv1 font
;
; This parameter is a comma-separated list of DPI:name pairs.
; The list is scanned from left-to-right. The font used is the first
; font whose DPI value is less-than-or-equal to the vertical DPI of
; the monitor used for the login screen.
#fv1_select=130:sans-18.fv1,0:sans-10.fv1
; Default DPI used for a monitor when that information is unknown
#default_dpi=96
; ;
; configure login screen ; configure login screen
; ;
@ -118,6 +129,10 @@ ls_top_window_bg_color=009cb5
; width and height of login screen ; width and height of login screen
; ;
; When the sans-10.fv1 font is selected, these values are in pixels.
; For other fonts, these values (and other size values) will be scaled
; appropriately to preserve the proportions of the login screen.
;
; The default height allows for about 5 fields to be comfortably displayed ; The default height allows for about 5 fields to be comfortably displayed
; above the buttons at the bottom. To display more fields, make <ls_height> ; above the buttons at the bottom. To display more fields, make <ls_height>
; larger, and also increase <ls_btn_ok_y_pos> and <ls_btn_cancel_y_pos> ; larger, and also increase <ls_btn_ok_y_pos> and <ls_btn_cancel_y_pos>
@ -147,15 +162,15 @@ ls_bg_color=dedede
; For transform values, see 'ls_background_transform'. The logo width and ; For transform values, see 'ls_background_transform'. The logo width and
; logo height are ignored for a transform of 'none'. ; logo height are ignored for a transform of 'none'.
ls_logo_filename= ls_logo_filename=
#ls_logo_transform=none ls_logo_transform=scale
#ls_logo_width=240 ls_logo_width=240
#ls_logo_height=140 ls_logo_height=140
ls_logo_x_pos=55 ls_logo_x_pos=55
ls_logo_y_pos=50 ls_logo_y_pos=50
; for positioning labels such as username, password etc ; for positioning labels such as username, password etc
ls_label_x_pos=30 ls_label_x_pos=30
ls_label_width=65 ls_label_width=68
; for positioning text and combo boxes next to above labels ; for positioning text and combo boxes next to above labels
ls_input_x_pos=110 ls_input_x_pos=110

View File

@ -24,8 +24,11 @@
#include <config_ac.h> #include <config_ac.h>
#endif #endif
#include <ctype.h>
#include "xrdp.h" #include "xrdp.h"
#include "log.h" #include "log.h"
#include "string_calls.h"
#if 0 /* not used */ #if 0 /* not used */
static char w_char[] = static char w_char[] =
@ -49,9 +52,93 @@ static char w_char[] =
}; };
#endif #endif
/*****************************************************************************/
/**
* Parses the fv1_select configuration value to get the font to use,
* based on the DPI of the primary monitor
*
* @param globals Configuration globals
* @param dpi DPI of primary monitor. If not known, a suitable
* default should be passed in here.
* @param[out] font_name Name of font to use
* @param[in] font_name_len Length of font name buffer
*/
static void
get_font_name_from_dpi(const struct xrdp_cfg_globals *globals,
unsigned int dpi,
char *font_name, int font_name_len)
{
int bad_selector = 0;
font_name[0] = '\0';
const char *fv1_select = globals->fv1_select;
if (fv1_select == NULL || fv1_select[0] == '\0')
{
fv1_select = DEFAULT_FV1_SELECT;
}
const char *p = fv1_select;
while (p != NULL)
{
/* DPI value must be next in string */
if (!isdigit(*p))
{
bad_selector = 1;
break;
}
unsigned int field_dpi = g_atoi(p);
if (field_dpi <= dpi)
{
/* Use this font */
p = g_strchr(p, ':');
if (p == NULL)
{
bad_selector = 1;
}
else
{
++p;
const char *q = g_strchr(p, ',');
if (q == NULL)
{
q = p + g_strlen(p);
}
if (q - p > (font_name_len - 1))
{
q = p + font_name_len - 1;
}
g_memcpy(font_name, p, q - p);
font_name[q - p] = '\0';
}
break;
}
else
{
p = g_strchr(p, ',');
if (p != NULL)
{
++p;
}
}
}
if (bad_selector)
{
LOG(LOG_LEVEL_WARNING, "Unable to parse fv1_select configuration");
}
if (font_name[0] == '\0')
{
LOG(LOG_LEVEL_WARNING, "Loading default font " DEFAULT_FONT_NAME);
g_snprintf(font_name, font_name_len, DEFAULT_FONT_NAME);
}
}
/*****************************************************************************/ /*****************************************************************************/
struct xrdp_font * struct xrdp_font *
xrdp_font_create(struct xrdp_wm *wm) xrdp_font_create(struct xrdp_wm *wm, unsigned int dpi)
{ {
struct xrdp_font *self; struct xrdp_font *self;
struct stream *s; struct stream *s;
@ -62,17 +149,52 @@ xrdp_font_create(struct xrdp_wm *wm)
int datasize; int datasize;
int file_size; int file_size;
struct xrdp_font_char *f; struct xrdp_font_char *f;
const char *file_path;
char file_path_buff[256];
int min_descender; int min_descender;
char file_path[256]; char font_name[256];
const struct xrdp_cfg_globals *globals = &wm->xrdp_config->cfg_globals;
LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_font_create"); LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_font_create");
g_snprintf(file_path, 255, "%s/%s", XRDP_SHARE_PATH, DEFAULT_FONT_NAME);
if (dpi == 0)
{
LOG(LOG_LEVEL_WARNING, "No DPI value is available to find login font");
dpi = globals->default_dpi;
LOG(LOG_LEVEL_WARNING, "Using the default_dpi of %u", dpi);
}
get_font_name_from_dpi(globals, dpi, font_name, sizeof(font_name));
if (font_name[0] == '/')
{
/* User specified absolute path */
file_path = font_name;
}
else
{
g_snprintf(file_path_buff, sizeof(file_path_buff),
XRDP_SHARE_PATH "/%s",
font_name);
file_path = file_path_buff;
}
if (!g_file_exist(file_path)) if (!g_file_exist(file_path))
{ {
LOG(LOG_LEVEL_ERROR, "xrdp_font_create: error font file [%s] does not exist", /* Try to fall back to the default */
file_path); const char *default_file_path = XRDP_SHARE_PATH "/" DEFAULT_FONT_NAME;
return 0; if (g_file_exist(default_file_path))
{
LOG(LOG_LEVEL_WARNING,
"xrdp_font_create: font file [%s] does not exist - using [%s]",
file_path, default_file_path);
file_path = default_file_path;
}
else
{
LOG(LOG_LEVEL_ERROR,
"xrdp_font_create: Can't load either [%s] or [%s]",
file_path, default_file_path);
return 0;
}
} }
file_size = g_file_get_size(file_path); file_size = g_file_get_size(file_path);
@ -150,7 +272,6 @@ xrdp_font_create(struct xrdp_wm *wm)
{ {
LOG(LOG_LEVEL_ERROR, "error in xrdp_font_create"); LOG(LOG_LEVEL_ERROR, "error in xrdp_font_create");
} }
index++; index++;
} }
@ -161,7 +282,6 @@ xrdp_font_create(struct xrdp_wm *wm)
self->body_height = -self->font_items[32].baseline + 1; self->body_height = -self->font_items[32].baseline + 1;
} }
} }
} }
free_stream(s); free_stream(s);

View File

@ -668,6 +668,81 @@ xrdp_wm_login_fill_in_combo(struct xrdp_wm *self, struct xrdp_bitmap *b)
return 0; return 0;
} }
/******************************************************************************/
unsigned int
xrdp_login_wnd_get_monitor_dpi(struct xrdp_wm *self)
{
unsigned int result = 0;
const struct display_size_description *display_sizes =
&self->client_info->display_sizes;
unsigned int height_pixels = 0;
unsigned int height_mm = 0;
unsigned int i;
/* Look at the monitor data first */
for (i = 0; i < display_sizes->monitorCount; ++i)
{
const struct monitor_info *mi = &display_sizes->minfo_wm[i];
{
if (mi->is_primary)
{
height_pixels = mi->bottom - mi->top + 1;
height_mm = mi->physical_height;
break;
}
}
}
/* No primary monitor, or values not defined - use the desktop size */
if (height_mm == 0)
{
height_pixels = display_sizes->session_height;
height_mm = self->client_info->session_physical_height;
if (height_mm == 0)
{
LOG(LOG_LEVEL_WARNING,
"No information is available to determine login screen DPI");
}
else if (height_pixels < 768)
{
/* A bug was encountered with mstsc.exe version
10.0.19041.1682 where the full physical monitor size was
sent in TS_UD_CS_CORE when the desktop size was set to
less than the screen size.
To generate the bug, make a connection with a full-screen
single window, cancel the login, and reconnect at
(e.g.) 800x600.
We can't detect that exact situation here, but if the
session height is so small as to likely be in a window
(rather than full screen), we should ignore the physical
size */
LOG(LOG_LEVEL_WARNING,
"Ignoring unlikely physical session size %u "
"for height of %u pixels", height_mm, height_pixels);
height_mm = 0;
}
}
if (height_mm != 0)
{
/*
* DPI = height_pixels / (height_mm / 25.4)
* = (height_pixels * 25.4) / height_mm
* = (height_pixels * 127) / (height_mm * 5)
*/
result = (height_pixels * 127 ) / (height_mm * 5);
LOG(LOG_LEVEL_INFO,
"Login screen monitor height is %u pixels over %u mm (%u DPI)",
height_pixels,
height_mm,
result);
}
return result;
}
/******************************************************************************/ /******************************************************************************/
int int
xrdp_login_wnd_create(struct xrdp_wm *self) xrdp_login_wnd_create(struct xrdp_wm *self)
@ -989,6 +1064,7 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
/* set default values in case we can't get them from xrdp.ini file */ /* set default values in case we can't get them from xrdp.ini file */
globals->ini_version = 1; globals->ini_version = 1;
globals->default_dpi = 96;
globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi("009cb5")); globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi("009cb5"));
globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi("dedede")); globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi("dedede"));
@ -1217,6 +1293,16 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
} }
/* login screen values */ /* login screen values */
else if (g_strcmp(n, "default_dpi") == 0)
{
globals->default_dpi = g_atoi(v);
}
else if (g_strcmp(n, "fv1_select") == 0)
{
g_strncpy(globals->fv1_select, v, sizeof(globals->fv1_select) - 1);
}
else if (g_strncmp(n, "ls_top_window_bg_color", 64) == 0) else if (g_strncmp(n, "ls_top_window_bg_color", 64) == 0)
{ {
globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v)); globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v));

View File

@ -606,6 +606,7 @@ struct xrdp_bitmap
#define NUM_FONTS 0x4e00 #define NUM_FONTS 0x4e00
#define DEFAULT_FONT_NAME "sans-10.fv1" #define DEFAULT_FONT_NAME "sans-10.fv1"
#define DEFAULT_FONT_PIXEL_SIZE 16 #define DEFAULT_FONT_PIXEL_SIZE 16
#define DEFAULT_FV1_SELECT "130:sans-18.fv1,0:" DEFAULT_FONT_NAME
#define DEFAULT_BUTTON_MARGIN_H 12 #define DEFAULT_BUTTON_MARGIN_H 12
#define DEFAULT_BUTTON_MARGIN_W 12 #define DEFAULT_BUTTON_MARGIN_W 12
@ -726,6 +727,8 @@ struct xrdp_cfg_globals
int background; int background;
/* login screen */ /* login screen */
unsigned int default_dpi; /* Default DPI to use if nothing from client */
char fv1_select[256]; /* Selection string for fv1 font */
int ls_top_window_bg_color; /* top level window background color */ int ls_top_window_bg_color; /* top level window background color */
int ls_bg_color; /* background color */ int ls_bg_color; /* background color */
char ls_background_image[256]; /* background image file name */ char ls_background_image[256]; /* background image file name */

View File

@ -569,6 +569,7 @@ xrdp_wm_init(struct xrdp_wm *self)
char default_section_name[256]; char default_section_name[256];
char section_name[256]; char section_name[256];
char autorun_name[256]; char autorun_name[256];
int dpi;
LOG(LOG_LEVEL_DEBUG, "in xrdp_wm_init: "); LOG(LOG_LEVEL_DEBUG, "in xrdp_wm_init: ");
@ -576,7 +577,8 @@ xrdp_wm_init(struct xrdp_wm *self)
self->screen->bpp); self->screen->bpp);
/* Load the font */ /* Load the font */
self->default_font = xrdp_font_create(self); dpi = xrdp_login_wnd_get_monitor_dpi(self);
self->default_font = xrdp_font_create(self, dpi);
/* Scale the login screen values */ /* Scale the login screen values */
xrdp_login_wnd_scale_config_values(self); xrdp_login_wnd_scale_config_values(self);