Add support for FreeRDP 3.x

With this, Weston can build against either FreeRDP 3.x or 2.x depending
on what has been detected by meson (3.x takes priority).

The main source of changes is the settings are now opaque and require the
use of accessors. That was pretty mechanical and seems to work on 2.x as
well.

There are a few changes around constants getting a WINPR_ prefix, the UTF
conversion functions we used are obsolete, so use the proper "new" ones,
and other fairly minor things.

The key & cert management changed rather completely, libfreerdp won't load
files for us, we have to use the helpers to do so, and I *think* the RDP RSA
key and SSL key use the same setting location. Seems to work with SSL at
least.

There was also a minor glitch with keyboard input, KBD_FLAGS_DOWN is basically
never set. It appears to be an upstream FreeRDP change in 3.x, it was being
set incorrectly (always on any key down) while it should only be set on
repeats. However the fastpath input code has no way to set it from what I
can tell, so it's just loss. We instead ignore it.

Note that the screen size is odd (and different between freerdp client and
remmina), it also won't adjust dynamically when the window is resized. I
don't think this relates to my port though, I observe the same behaviour
with the packaged FreeRDP 2 based Weston, but I can try to look into it
later

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
Benjamin Herrenschmidt 2024-08-02 15:45:33 +10:00
parent e7ed5d201a
commit 89f3a8a71e
6 changed files with 271 additions and 129 deletions

View File

@ -43,7 +43,7 @@
variables:
FDO_UPSTREAM_REPO: wayland/weston
FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH"
FDO_DISTRIBUTION_TAG: '2024-08-05-00-rm-plugins'
FDO_DISTRIBUTION_TAG: '2024-08-14-00-freerdp3.x'
include:
@ -89,6 +89,7 @@ stages:
variables:
BUILD_OS: debian
LLVM_VERSION: 11
FREERDP_VERSION: 2
FDO_DISTRIBUTION_VERSION: bullseye
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
@ -96,6 +97,8 @@ stages:
variables:
BUILD_OS: debian
LLVM_VERSION: 15
FREERDP_VERSION: 3
USE_BOOKWORM_BACKPORTS: y
# If you upgrade from bookworm, see the use_tls=0 notes in tests/meson.build.
FDO_DISTRIBUTION_VERSION: bookworm
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
@ -142,6 +145,10 @@ check-commit:
- .os-debian
variables:
BUILD_ARCH: "armv7"
# Armv7 doesn't have freerdp3 in bookworm-backports so we don't build FreeRDP
MESON_DIST_OPTIONS: "-Dbackend-rdp=false"
# Inhibit installation of freerdp-dev
FREERDP_VERSION: 0
.debian-lts-aarch64:
extends:
@ -276,7 +283,7 @@ aarch64-debian-container_prep:
- .default-rules
script:
- cd "$BUILDDIR"
- meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ..
- meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
- ninja install
- test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
@ -304,7 +311,7 @@ aarch64-debian-container_prep:
- .default-rules
script:
- cd "$BUILDDIR"
- meson --prefix="$PREFIX" --wrap-mode=nofallback ${MESON_OPTIONS} ..
- meson --prefix="$PREFIX" --wrap-mode=nofallback ${MESON_OPTIONS} ${MESON_DIST_OPTIONS} ..
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
- ninja install
- ninja clean

View File

@ -31,6 +31,9 @@ MESA_RUNTIME_PKGS="
libllvm${LLVM_VERSION}
"
if [ x"$USE_BOOKWORM_BACKPORTS" = "xy" ] ; then
echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list
fi
apt-get update
apt-get -y --no-install-recommends install \
autoconf \
@ -40,7 +43,6 @@ apt-get -y --no-install-recommends install \
curl \
doxygen \
graphviz \
freerdp2-dev \
gcovr \
git \
hwdata \
@ -123,6 +125,9 @@ apt-get -y --no-install-recommends install \
$MESA_RUNTIME_PKGS \
$LINUX_DEV_PKGS \
if [ "$FREERDP_VERSION" -ne 0 ] ; then
apt-get -y --no-install-recommends install freerdp${FREERDP_VERSION}-dev
fi
# Actually build our dependencies ...
./.gitlab-ci/build-deps.sh

View File

@ -1,46 +1,64 @@
if not get_option('backend-rdp')
subdir_done()
subdir_done()
endif
config_h.set('BUILD_RDP_COMPOSITOR', '1')
dep_frdp = dependency('freerdp2', version: '>= 2.3.0', required: false)
if not dep_frdp.found()
error('RDP-backend requires freerdp >= 2.3.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
dep_frdp3 = dependency('freerdp3', version: '>= 3.0.0', required: false)
dep_frdp2 = dependency('freerdp2', version: '>= 2.3.0', required: false)
dep_frdp_server = dependency('freerdp-server2', version: '>= 2.3.0', required: false)
if not dep_frdp_server.found()
error('RDP-backend requires freerdp-server2 >= 2.3.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
if dep_frdp3.found()
config_h.set('USE_FREERDP_VERSION', '3')
dep_frdp = dep_frdp3
dep_frdp_server = dependency('freerdp-server3', version: '>= 3.0.0', required: false)
if not dep_frdp_server.found()
error('RDP-backend v3 requires freerdp-server3 >= 3.0.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
dep_wpr = dependency('winpr2', version: '>= 2.3.0', required: false)
if not dep_wpr.found()
error('RDP-backend requires winpr >= 2.3.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
dep_wpr = dependency('winpr3', version: '>= 3.0.0', required: false)
if not dep_wpr.found()
error('RDP-backend v3 requires winpr >= 3.0.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
message('Using FreeRDP 3.x for RDP backend')
elif dep_frdp2.found()
config_h.set('USE_FREERDP_VERSION', '2')
dep_frdp = dep_frdp2
dep_frdp_server = dependency('freerdp-server2', version: '>= 2.3.0', required: false)
if not dep_frdp_server.found()
error('RDP-backend v2 requires freerdp-server2 >= 2.3.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
dep_wpr = dependency('winpr2', version: '>= 2.3.0', required: false)
if not dep_wpr.found()
error('RDP-backend requires v2 winpr >= 2.3.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
message('Using FreeRDP 2.x for RDP backend')
else
error('RDP-backend requires freerdp3 >= 3.0.0 or freerdp2 >= 2.3.0 which was not found. Or, you can use \'-Dbackend-rdp=false\'.')
endif
deps_rdp = [
dep_libweston_private,
dep_frdp,
dep_frdp_server,
dep_wpr,
dep_libdrm_headers,
dep_libweston_private,
dep_frdp,
dep_frdp_server,
dep_wpr,
dep_libdrm_headers,
]
srcs_rdp = [
'rdp.c',
'rdpclip.c',
'rdpdisp.c',
'rdpdisp.c',
'rdputil.c',
]
plugin_rdp = shared_library(
'rdp-backend',
srcs_rdp,
include_directories: common_inc,
dependencies: deps_rdp,
name_prefix: '',
install: true,
install_dir: dir_module_libweston
'rdp-backend',
srcs_rdp,
include_directories: common_inc,
dependencies: deps_rdp,
name_prefix: '',
install: true,
install_dir: dir_module_libweston
)
env_modmap += 'rdp-backend.so=@0@;'.format(plugin_rdp.full_path())
install_headers(backend_rdp_h, subdir: dir_include_libweston_install)

View File

@ -100,7 +100,7 @@ rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_p
cmd.destRight = damage->extents.x2;
cmd.destBottom = damage->extents.y2;
cmd.bmp.bpp = 32;
cmd.bmp.codecID = peer->context->settings->RemoteFxCodecId;
cmd.bmp.codecID = freerdp_settings_get_uint32(peer->context->settings, FreeRDP_RemoteFxCodecId);
cmd.bmp.width = width;
cmd.bmp.height = height;
@ -161,7 +161,7 @@ rdp_peer_refresh_nsc(pixman_region32_t *damage, pixman_image_t *image, freerdp_p
cmd.destRight = damage->extents.x2;
cmd.destBottom = damage->extents.y2;
cmd.bmp.bpp = 32;
cmd.bmp.codecID = peer->context->settings->NSCodecId;
cmd.bmp.codecID = freerdp_settings_get_uint32(peer->context->settings, FreeRDP_NSCodecId);
cmd.bmp.width = width;
cmd.bmp.height = height;
@ -220,7 +220,8 @@ rdp_peer_refresh_raw(pixman_region32_t *region, pixman_image_t *image, freerdp_p
cmd.destRight = rect->x2;
cmd.bmp.width = (rect->x2 - rect->x1);
heightIncrement = peer->context->settings->MultifragMaxRequestSize / (16 + cmd.bmp.width * 4);
heightIncrement = freerdp_settings_get_uint32(peer->context->settings,
FreeRDP_MultifragMaxRequestSize) / (16 + cmd.bmp.width * 4);
remainingHeight = rect->y2 - rect->y1;
top = rect->y1;
@ -259,9 +260,9 @@ rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer)
struct rdp_output *output = rdp_get_first_output(context->rdpBackend);
rdpSettings *settings = peer->context->settings;
if (settings->RemoteFxCodec)
if (freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec))
rdp_peer_refresh_rfx(region, output->shadow_surface, peer);
else if (settings->NSCodec)
else if (freerdp_settings_get_bool(settings, FreeRDP_NSCodec))
rdp_peer_refresh_nsc(region, output->shadow_surface, peer);
else
rdp_peer_refresh_raw(region, output->shadow_surface, peer);
@ -398,17 +399,17 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
*/
wl_list_for_each(rdpPeer, &b->peers, link) {
settings = rdpPeer->peer->context->settings;
if (settings->DesktopWidth == (uint32_t)mode->width &&
settings->DesktopHeight == (uint32_t)mode->height)
if (freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) == (uint32_t)mode->width &&
freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight) == (uint32_t)mode->height)
continue;
if (!settings->DesktopResize) {
if (!freerdp_settings_get_bool(settings, FreeRDP_DesktopResize)) {
/* too bad this peer does not support desktop resize */
weston_log("desktop resize is not allowed\n");
rdpPeer->peer->Close(rdpPeer->peer);
} else {
settings->DesktopWidth = mode->width;
settings->DesktopHeight = mode->height;
freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, mode->width);
freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, mode->height);
rdpPeer->peer->context->update->DesktopResize(rdpPeer->peer->context);
}
}
@ -758,9 +759,16 @@ rdp_peer_context_new(freerdp_peer* client, RdpPeerContext* context)
if (!context->rfx_context)
return FALSE;
#if USE_FREERDP_VERSION >= 3
rfx_context_set_mode(context->rfx_context, RLGR3);
rfx_context_reset(context->rfx_context,
freerdp_settings_get_uint32(client->context->settings, FreeRDP_DesktopWidth),
freerdp_settings_get_uint32(client->context->settings, FreeRDP_DesktopHeight));
#else
context->rfx_context->mode = RLGR3;
context->rfx_context->width = client->context->settings->DesktopWidth;
context->rfx_context->height = client->context->settings->DesktopHeight;
#endif
rfx_context_set_pixel_format(context->rfx_context, DEFAULT_PIXEL_FORMAT);
context->nsc_context = nsc_context_new();
@ -1015,7 +1023,7 @@ convert_rdp_keyboard_to_xkb_rule_names(UINT32 KeyboardType,
xkbRuleNames->variant = "kr104"; /* kr(ralt_hangul)/kr(rctrl_hanja) */
else if (KeyboardSubType == 6) /* PC/AT 103 Enhanced Korean Keyboard */
xkbRuleNames->variant = "kr106"; /* kr(hw_keys) */
} else if (KeyboardType != KBD_TYPE_JAPANESE && ((KeyboardLayout & 0xFFFF) == 0x411)) {
} else if (KeyboardType != WINPR_KBD_TYPE_JAPANESE && ((KeyboardLayout & 0xFFFF) == 0x411)) {
/* when Japanese keyboard layout is used without a Japanese 106/109
* keyboard (keyboard type 7), use the "us" layout, since the "jp"
* layout in xkb expects the Japanese 106/109 keyboard layout.
@ -1061,6 +1069,8 @@ xf_peer_activate(freerdp_peer* client)
char seat_name[50];
POINTER_SYSTEM_UPDATE pointer_system;
int width, height;
const char *cl_hostname;
BOOL audio_playback, audio_capture;
peerCtx = (RdpPeerContext *)client->context;
b = peerCtx->rdpBackend;
@ -1068,31 +1078,32 @@ xf_peer_activate(freerdp_peer* client)
output = rdp_get_first_output(b);
settings = client->context->settings;
if (!settings->SurfaceCommandsEnabled) {
if (!freerdp_settings_get_bool(settings, FreeRDP_SurfaceCommandsEnabled)) {
weston_log("client doesn't support required SurfaceCommands\n");
return FALSE;
}
if (b->force_no_compression && settings->CompressionEnabled) {
if (b->force_no_compression && freerdp_settings_get_bool(settings, FreeRDP_CompressionEnabled)) {
rdp_debug(b, "Forcing compression off\n");
settings->CompressionEnabled = FALSE;
freerdp_settings_set_bool(settings, FreeRDP_CompressionEnabled, FALSE);
}
settings->AudioPlayback = b->audio_out_setup && b->audio_out_teardown;
settings->AudioCapture = b->audio_in_setup && b->audio_in_teardown;
audio_playback = b->audio_out_setup && b->audio_out_teardown;
freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, audio_playback);
audio_capture = b->audio_in_setup && b->audio_in_teardown;
freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, audio_capture);
if (settings->RedirectClipboard ||
settings->AudioPlayback ||
settings->AudioCapture) {
if (freerdp_settings_get_bool(settings, FreeRDP_RedirectClipboard) ||
audio_playback || audio_capture) {
if (!peerCtx->vcm) {
weston_log("Virtual channel is required for clipboard, audio playback/capture\n");
goto error_exit;
}
/* Audio setup will return NULL on failure, and we'll proceed without audio */
if (settings->AudioPlayback)
if (audio_playback)
peerCtx->audio_out_private = b->audio_out_setup(b->compositor, peerCtx->vcm);
if (settings->AudioCapture)
if (audio_capture)
peerCtx->audio_in_private = b->audio_in_setup(b->compositor, peerCtx->vcm);
}
@ -1103,15 +1114,15 @@ xf_peer_activate(freerdp_peer* client)
if (!b->resizeable) {
struct weston_mode *mode = output->base.current_mode;
if (mode->width != (int)settings->DesktopWidth ||
mode->height != (int)settings->DesktopHeight) {
if (!settings->DesktopResize) {
if (mode->width != (int)freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) ||
mode->height != (int)freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)) {
if (!freerdp_settings_get_bool(settings, FreeRDP_DesktopResize)) {
/* peer does not support desktop resize */
weston_log("client doesn't support resizing, closing connection\n");
return FALSE;
} else {
settings->DesktopWidth = mode->width;
settings->DesktopHeight = mode->height;
freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, mode->width);
freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, mode->height);
client->context->update->DesktopResize(client->context);
}
}
@ -1130,12 +1141,14 @@ xf_peer_activate(freerdp_peer* client)
/* when here it's the first reactivation, we need to setup a little more */
rdp_debug(b, "kbd_layout:0x%x kbd_type:0x%x kbd_subType:0x%x kbd_functionKeys:0x%x\n",
settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType,
settings->KeyboardFunctionKey);
freerdp_settings_get_uint32(settings, FreeRDP_KeyboardLayout),
freerdp_settings_get_uint32(settings, FreeRDP_KeyboardType),
freerdp_settings_get_uint32(settings, FreeRDP_KeyboardSubType),
freerdp_settings_get_uint32(settings, FreeRDP_KeyboardFunctionKey));
convert_rdp_keyboard_to_xkb_rule_names(settings->KeyboardType,
settings->KeyboardSubType,
settings->KeyboardLayout,
convert_rdp_keyboard_to_xkb_rule_names(freerdp_settings_get_uint32(settings, FreeRDP_KeyboardType),
freerdp_settings_get_uint32(settings, FreeRDP_KeyboardSubType),
freerdp_settings_get_uint32(settings, FreeRDP_KeyboardLayout),
&xkbRuleNames);
keymap = NULL;
@ -1144,10 +1157,12 @@ xf_peer_activate(freerdp_peer* client)
&xkbRuleNames, 0);
}
if (settings->ClientHostname)
snprintf(seat_name, sizeof(seat_name), "RDP %s", settings->ClientHostname);
cl_hostname = freerdp_settings_get_string(settings, FreeRDP_ClientHostname);
if (cl_hostname)
snprintf(seat_name, sizeof(seat_name), "RDP %s", cl_hostname);
else
snprintf(seat_name, sizeof(seat_name), "RDP peer @%s", settings->ClientAddress);
snprintf(seat_name, sizeof(seat_name), "RDP peer @%s",
freerdp_settings_get_string(settings, FreeRDP_ClientAddress));
peersItem->seat = zalloc(sizeof(*peersItem->seat));
if (!peersItem->seat) {
@ -1162,7 +1177,7 @@ xf_peer_activate(freerdp_peer* client)
weston_seat_init_pointer(peersItem->seat);
/* Initialize RDP clipboard after seat is initialized */
if (settings->RedirectClipboard)
if (freerdp_settings_get_bool(settings, FreeRDP_RedirectClipboard))
if (rdp_clipboard_init(client) != 0)
goto error_exit;
@ -1181,10 +1196,10 @@ error_exit:
rdp_clipboard_destroy(peerCtx);
if (settings->AudioPlayback && peerCtx->audio_out_private)
if (audio_playback && peerCtx->audio_out_private)
b->audio_out_teardown(peerCtx->audio_out_private);
if (settings->AudioCapture && peerCtx->audio_in_private)
if (audio_capture && peerCtx->audio_in_private)
b->audio_in_teardown(peerCtx->audio_in_private);
return FALSE;
@ -1502,7 +1517,7 @@ xf_input_synchronize_event(rdpInput *input, UINT32 flags)
static BOOL
xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
xf_input_keyboard_event(rdpInput *input, UINT16 flags, XF_KEV_CODE_TYPE code)
{
uint32_t scan_code, vk_code, full_code;
enum wl_keyboard_key_state keyState;
@ -1512,15 +1527,23 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
int notify = 0;
struct timespec time;
if (!(peerContext->item.flags & RDP_PEER_ACTIVATED))
return TRUE;
rdp_debug_verbose(peerContext->rdpBackend, "RDP backend: %s flags:0x%x, code:0x%x\n",
__func__, flags, code);
if (flags & KBD_FLAGS_DOWN) {
keyState = WL_KEYBOARD_KEY_STATE_PRESSED;
notify = 1;
} else if (flags & KBD_FLAGS_RELEASE) {
if (!(peerContext->item.flags & RDP_PEER_ACTIVATED)) {
rdp_debug_verbose(peerContext->rdpBackend, " -> NOT ACTIVATED\n");
return TRUE;
}
/* Note: With FreeRDP 3.x, we seem to have KBD_FLAGS_RELEASE set when
* releasing a key and *NO* flag set when pressing...
*/
else if (flags & KBD_FLAGS_RELEASE) {
keyState = WL_KEYBOARD_KEY_STATE_RELEASED;
notify = 1;
} else if ((USE_FREERDP_VERSION >= 3) || flags & KBD_FLAGS_DOWN) {
keyState = WL_KEYBOARD_KEY_STATE_PRESSED;
notify = 1;
}
if (notify) {
@ -1531,8 +1554,8 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
/* Korean keyboard support:
* WinPR's GetVirtualKeyCodeFromVirtualScanCode() can't handle hangul/hanja keys
* hanja and hangeul keys are only present on Korean 103 keyboard (Type 8:SubType 6) */
if (client->context->settings->KeyboardType == 8 &&
client->context->settings->KeyboardSubType == 6 &&
if (freerdp_settings_get_uint32(client->context->settings, FreeRDP_KeyboardType) == 8 &&
freerdp_settings_get_uint32(client->context->settings, FreeRDP_KeyboardSubType) == 6 &&
((full_code == (KBD_FLAGS_EXTENDED | ATKBD_RET_HANJA)) ||
(full_code == (KBD_FLAGS_EXTENDED | ATKBD_RET_HANGEUL)))) {
if (full_code == (KBD_FLAGS_EXTENDED | ATKBD_RET_HANJA))
@ -1552,7 +1575,10 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
}
send_release_key = true;
} else {
vk_code = GetVirtualKeyCodeFromVirtualScanCode(full_code, client->context->settings->KeyboardType);
vk_code = GetVirtualKeyCodeFromVirtualScanCode(full_code,
freerdp_settings_get_uint32(client->context->settings,
FreeRDP_KeyboardType));
rdp_debug_verbose(peerContext->rdpBackend, " -> vk_code=0x%x\n", vk_code);
}
/* Korean keyboard support */
/* WinPR's GetKeycodeFromVirtualKeyCode() expects no extended bit for VK_HANGUL and VK_HANJA */
@ -1560,7 +1586,7 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
if (flags & KBD_FLAGS_EXTENDED)
vk_code |= KBDEXT;
scan_code = GetKeycodeFromVirtualKeyCode(vk_code, KEYCODE_TYPE_EVDEV);
scan_code = GetKeycodeFromVirtualKeyCode(vk_code, WINPR_KEYCODE_TYPE_XKB);
/*weston_log("code=%x ext=%d vk_code=%x scan_code=%x\n", code, (flags & KBD_FLAGS_EXTENDED) ? 1 : 0,
vk_code, scan_code);*/
@ -1617,14 +1643,21 @@ xf_peer_adjust_monitor_layout(freerdp_peer *client)
unsigned int i;
rdp_debug(b, "%s:\n", __func__);
rdp_debug(b, " DesktopWidth:%d, DesktopHeight:%d\n", settings->DesktopWidth, settings->DesktopHeight);
rdp_debug(b, " UseMultimon:%d\n", settings->UseMultimon);
rdp_debug(b, " ForceMultimon:%d\n", settings->ForceMultimon);
rdp_debug(b, " MonitorCount:%d\n", settings->MonitorCount);
rdp_debug(b, " HasMonitorAttributes:%d\n", settings->HasMonitorAttributes);
rdp_debug(b, " HiDefRemoteApp:%d\n", settings->HiDefRemoteApp);
rdp_debug(b, " DesktopWidth:%d, DesktopHeight:%d\n",
freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight));
rdp_debug(b, " UseMultimon:%d\n",
freerdp_settings_get_bool(settings, FreeRDP_UseMultimon));
rdp_debug(b, " ForceMultimon:%d\n",
freerdp_settings_get_bool(settings, FreeRDP_ForceMultimon));
rdp_debug(b, " MonitorCount:%d\n",
freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount));
rdp_debug(b, " HasMonitorAttributes:%d\n",
freerdp_settings_get_bool(settings, FreeRDP_HasMonitorAttributes));
rdp_debug(b, " HiDefRemoteApp:%d\n",
freerdp_settings_get_bool(settings, FreeRDP_HiDefRemoteApp));
if (settings->MonitorCount > 1) {
if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) > 1) {
weston_log("multiple monitor is not supported");
fallback = true;
}
@ -1632,18 +1665,19 @@ xf_peer_adjust_monitor_layout(freerdp_peer *client)
if (!b->resizeable)
fallback = true;
if (settings->MonitorCount > RDP_MAX_MONITOR) {
if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) > RDP_MAX_MONITOR) {
weston_log("Client reports more monitors then expected:(%d)\n",
settings->MonitorCount);
freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount));
return FALSE;
}
if ((settings->MonitorCount > 0 && settings->MonitorDefArray) && !fallback) {
rdpMonitor *rdp_monitor = settings->MonitorDefArray;
monitor_count = settings->MonitorCount;
if ((freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) > 0 &&
freerdp_settings_get_pointer(settings, FreeRDP_MonitorDefArray)) && !fallback) {
const rdpMonitor *rdp_monitor = freerdp_settings_get_pointer(settings, FreeRDP_MonitorDefArray);
monitor_count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
monitors = xmalloc(sizeof(*monitors) * monitor_count);
for (i = 0; i < monitor_count; i++) {
monitors[i] = rdp_monitor[i];
if (!settings->HasMonitorAttributes) {
if (!freerdp_settings_get_bool(settings, FreeRDP_HasMonitorAttributes)) {
monitors[i].attributes.physicalWidth = 0;
monitors[i].attributes.physicalHeight = 0;
monitors[i].attributes.orientation = ORIENTATION_LANDSCAPE;
@ -1657,14 +1691,19 @@ xf_peer_adjust_monitor_layout(freerdp_peer *client)
/* when no monitor array provided, generate from desktop settings */
monitors[0].x = 0;
monitors[0].y = 0;
monitors[0].width = settings->DesktopWidth;
monitors[0].height = settings->DesktopHeight;
monitors[0].width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
monitors[0].height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
monitors[0].is_primary = 1;
monitors[0].attributes.physicalWidth = settings->DesktopPhysicalWidth;
monitors[0].attributes.physicalHeight = settings->DesktopPhysicalHeight;
monitors[0].attributes.orientation = settings->DesktopOrientation;
monitors[0].attributes.desktopScaleFactor = settings->DesktopScaleFactor;
monitors[0].attributes.deviceScaleFactor = settings->DeviceScaleFactor;
monitors[0].attributes.physicalWidth =
freerdp_settings_get_uint32(settings, FreeRDP_DesktopPhysicalWidth);
monitors[0].attributes.physicalHeight =
freerdp_settings_get_uint32(settings, FreeRDP_DesktopPhysicalHeight);
monitors[0].attributes.orientation =
freerdp_settings_get_uint16(settings, FreeRDP_DesktopOrientation);
monitors[0].attributes.desktopScaleFactor =
freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor);
monitors[0].attributes.deviceScaleFactor =
freerdp_settings_get_uint32(settings, FreeRDP_DeviceScaleFactor);
monitors[0].orig_screen = 0;
if (!b->resizeable) {
@ -1703,7 +1742,30 @@ rdp_peer_init(freerdp_peer *client, struct rdp_backend *b)
peerCtx->rdpBackend = b;
settings = client->context->settings;
#if USE_FREERDP_VERSION >= 3
/* configure security settings */
if (b->rdp_key) {
rdpPrivateKey* key = freerdp_key_new_from_file(b->rdp_key);
if (!key)
goto error_initialize;
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerRsaKey, key, 1))
goto error_initialize;
}
if (b->tls_enabled) {
rdpCertificate* cert = freerdp_certificate_new_from_file(b->server_cert);
if (!cert)
goto error_initialize;
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerCertificate, cert, 1))
goto error_initialize;
rdpPrivateKey* key = freerdp_key_new_from_file(b->server_key);
if (!key)
goto error_initialize;
if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerRsaKey, key, 1))
goto error_initialize;
} else {
freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, FALSE);
}
#else
if (b->rdp_key)
settings->RdpKeyFile = strdup(b->rdp_key);
if (b->tls_enabled) {
@ -1712,31 +1774,32 @@ rdp_peer_init(freerdp_peer *client, struct rdp_backend *b)
} else {
settings->TlsSecurity = FALSE;
}
settings->NlaSecurity = FALSE;
#endif
freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE);
if (!client->Initialize(client)) {
weston_log("peer initialization failed\n");
goto error_initialize;
}
settings->OsMajorType = OSMAJORTYPE_UNIX;
settings->OsMinorType = OSMINORTYPE_PSEUDO_XSERVER;
settings->ColorDepth = 32;
settings->RefreshRect = TRUE;
settings->RemoteFxCodec = b->remotefx_codec;
settings->NSCodec = TRUE;
settings->FrameMarkerCommandEnabled = TRUE;
settings->SurfaceFrameMarkerEnabled = TRUE;
settings->RedirectClipboard = TRUE;
settings->HasExtendedMouseEvent = TRUE;
settings->HasHorizontalWheel = TRUE;
freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX);
freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_PSEUDO_XSERVER);
freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32);
freerdp_settings_set_bool(settings, FreeRDP_RefreshRect, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, b->remotefx_codec);
freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_FrameMarkerCommandEnabled, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_SurfaceFrameMarkerEnabled, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_HasExtendedMouseEvent, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_HasHorizontalWheel, TRUE);
client->Capabilities = xf_peer_capabilities;
client->PostConnect = xf_peer_post_connect;
client->Activate = xf_peer_activate;
if (b->resizeable) {
settings->SupportMonitorLayoutPdu = TRUE;
freerdp_settings_set_bool(settings, FreeRDP_SupportMonitorLayoutPdu, TRUE);
client->AdjustMonitorsLayout = xf_peer_adjust_monitor_layout;
}
@ -1793,6 +1856,7 @@ error_dispatch_initialize:
peerCtx->vcm = NULL;
}
error_initialize:
client->Close(client);
return -1;

View File

@ -27,6 +27,14 @@
#ifndef RDP_H
#define RDP_H
/* Workaround an issue with clang and freerdp 3 headers. Another
* option would be to build with --std=c11 but weston itself isn't
* quite ready for that
*/
#if USE_FREERDP_VERSION >= 3 && defined(__clang__)
#pragma clang diagnostic ignored "-Wtypedef-redefinition"
#endif
#include <freerdp/version.h>
#include <freerdp/freerdp.h>
@ -44,6 +52,8 @@
#include <libweston/backend-rdp.h>
#include <libweston/weston-log.h>
#include <winpr/string.h>
#include "backend.h"
#include "shared/helpers.h"
@ -68,6 +78,17 @@
#define ATKBD_RET_HANJA 0xf1
#define ATKBD_RET_HANGEUL 0xf2
/* freerdp2 vs 3 compat */
#if USE_FREERDP_VERSION >= 3
#define FORM_DATA_RESP_COMM(r, f) (r).common.f
#define XF_KEV_CODE_TYPE UINT8
#else
#define FORM_DATA_RESP_COMM(r, f) (r).f
#define WINPR_KBD_TYPE_JAPANESE KBD_TYPE_JAPANESE
#define WINPR_KEYCODE_TYPE_XKB KEYCODE_TYPE_EVDEV
#define XF_KEV_CODE_TYPE UINT16
#endif
struct rdp_backend {
struct weston_backend base;
struct weston_compositor *compositor;

View File

@ -37,6 +37,8 @@
#include "rdp.h"
#include <winpr/string.h>
#include "libweston-internal.h"
/* From MSDN, RegisterClipboardFormat API.
@ -194,10 +196,14 @@ clipboard_process_text_utf8(struct rdp_clipboard_data_source *source, bool is_se
source->data_contents.size++;
/* obtain size in UNICODE */
#if USE_FREERDP_VERSION >= 3
data_size = ConvertUtf8NToWChar(data, source->data_contents.size, NULL, 0);
#else
data_size = MultiByteToWideChar(CP_UTF8, 0,
data,
source->data_contents.size,
NULL, 0);
#endif
if (data_size < 1)
goto error_return;
@ -206,11 +212,18 @@ clipboard_process_text_utf8(struct rdp_clipboard_data_source *source, bool is_se
goto error_return;
/* convert to UNICODE */
#if USE_FREERDP_VERSION >= 3
data_size_in_char = ConvertUtf8NToWChar(data,
source->data_contents.size,
data_contents.data,
data_size);
#else
data_size_in_char = MultiByteToWideChar(CP_UTF8, 0,
data,
source->data_contents.size,
data_contents.data,
data_size);
#endif
assert(data_contents.size == (data_size_in_char * 2));
} else {
/* Windows to Linux (UNICODE to utf-8) */
@ -226,11 +239,17 @@ clipboard_process_text_utf8(struct rdp_clipboard_data_source *source, bool is_se
goto error_return;
/* obtain size in utf-8 */
#if USE_FREERDP_VERSION >= 3
data_size = ConvertWCharNToUtf8(source->data_contents.data,
data_size_in_char,
NULL, 0);
#else
data_size = WideCharToMultiByte(CP_UTF8, 0,
source->data_contents.data,
data_size_in_char,
NULL, 0,
NULL, NULL);
#endif
if (data_size < 1)
goto error_return;
@ -238,12 +257,19 @@ clipboard_process_text_utf8(struct rdp_clipboard_data_source *source, bool is_se
goto error_return;
/* convert to utf-8 */
#if USE_FREERDP_VERSION >= 3
data_size = ConvertWCharNToUtf8(source->data_contents.data,
data_size_in_char,
data_contents.data,
data_size);
#else
data_size = WideCharToMultiByte(CP_UTF8, 0,
source->data_contents.data,
data_size_in_char,
data_contents.data,
data_size,
NULL, NULL);
#endif
assert(data_contents.size == data_size);
}
@ -721,9 +747,9 @@ clipboard_client_send_format_data_response(RdpPeerContext *ctx, struct rdp_clipb
clipboard_supported_formats[source->format_index].mime_type,
source->processed_data_size);
formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE;
formatDataResponse.msgFlags = CB_RESPONSE_OK;
formatDataResponse.dataLen = source->processed_data_size;
FORM_DATA_RESP_COMM(formatDataResponse, msgType) = CB_FORMAT_DATA_RESPONSE;
FORM_DATA_RESP_COMM(formatDataResponse, msgFlags) = CB_RESPONSE_OK;
FORM_DATA_RESP_COMM(formatDataResponse, dataLen) = source->processed_data_size;
formatDataResponse.requestedFormatData = source->processed_data_start;
ctx->clipboard_server_context->ServerFormatDataResponse(ctx->clipboard_server_context, &formatDataResponse);
/* if here failed to send response, what can we do ? */
@ -745,9 +771,9 @@ clipboard_client_send_format_data_response_fail(RdpPeerContext *ctx, struct rdp_
source->data_response_fail_count++;
}
formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE;
formatDataResponse.msgFlags = CB_RESPONSE_FAIL;
formatDataResponse.dataLen = 0;
FORM_DATA_RESP_COMM(formatDataResponse, msgType) = CB_FORMAT_DATA_RESPONSE;
FORM_DATA_RESP_COMM(formatDataResponse, msgFlags) = CB_RESPONSE_FAIL;
FORM_DATA_RESP_COMM(formatDataResponse, dataLen) = 0;
formatDataResponse.requestedFormatData = NULL;
ctx->clipboard_server_context->ServerFormatDataResponse(ctx->clipboard_server_context, &formatDataResponse);
/* if here failed to send response, what can we do ? */
@ -1098,8 +1124,8 @@ clipboard_data_source_send(struct weston_data_source *base,
/* update requesting format property */
source->format_index = index;
/* request clipboard data from client */
formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
formatDataRequest.dataLen = 4;
FORM_DATA_RESP_COMM(formatDataRequest, msgType) = CB_FORMAT_DATA_REQUEST;
FORM_DATA_RESP_COMM(formatDataRequest, dataLen) = 4;
formatDataRequest.requestedFormatId = source->client_format_id_table[index];
source->state = RDP_CLIPBOARD_SOURCE_REQUEST_DATA;
rdp_debug_clipboard(b, "RDP %s (%p:%s) request data \"%s\" index:%d formatId:%d %s\n",
@ -1389,7 +1415,7 @@ clipboard_set_selection(struct wl_listener *listener, void *data)
if (num_supported_format) {
/* let client knows formats are available in server clipboard */
formatList.msgType = CB_FORMAT_LIST;
FORM_DATA_RESP_COMM(formatList, msgType) = CB_FORMAT_LIST;
formatList.numFormats = num_supported_format;
formatList.formats = &format[0];
ctx->clipboard_server_context->ServerFormatList(ctx->clipboard_server_context, &formatList);
@ -1527,9 +1553,9 @@ clipboard_client_format_list(CliprdrServerContext *context, const CLIPRDR_FORMAT
rdp_dispatch_task_to_display_loop(ctx, clipboard_data_source_publish, &source->task_base);
fail:
formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE;
formatListResponse.msgFlags = source ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
formatListResponse.dataLen = 0;
FORM_DATA_RESP_COMM(formatListResponse, msgType) = CB_FORMAT_LIST_RESPONSE;
FORM_DATA_RESP_COMM(formatListResponse, msgFlags) = source ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
FORM_DATA_RESP_COMM(formatListResponse, dataLen) = 0;
if (ctx->clipboard_server_context->ServerFormatListResponse(ctx->clipboard_server_context, &formatListResponse) != 0) {
source->state = RDP_CLIPBOARD_SOURCE_FAILED;
weston_log("Client: %s (%p:%s) ServerFormatListResponse failed\n",
@ -1555,8 +1581,8 @@ clipboard_client_format_data_response(CliprdrServerContext *context, const CLIPR
rdp_debug_clipboard(b, "Client: %s (%p:%s) flags:%d dataLen:%d\n",
__func__, source,
clipboard_data_source_state_to_string(source),
formatDataResponse->msgFlags,
formatDataResponse->dataLen);
FORM_DATA_RESP_COMM(*formatDataResponse, msgFlags),
FORM_DATA_RESP_COMM(*formatDataResponse, dataLen));
assert_not_compositor_thread(b);
@ -1574,13 +1600,13 @@ clipboard_client_format_data_response(CliprdrServerContext *context, const CLIPR
return -1;
}
if (formatDataResponse->msgFlags == CB_RESPONSE_OK) {
if (FORM_DATA_RESP_COMM(*formatDataResponse, msgFlags) == CB_RESPONSE_OK) {
/* Recieved data from client, cache to data source */
if (wl_array_add(&source->data_contents, formatDataResponse->dataLen+1)) {
if (wl_array_add(&source->data_contents, FORM_DATA_RESP_COMM(*formatDataResponse, dataLen)+1)) {
memcpy(source->data_contents.data,
formatDataResponse->requestedFormatData,
formatDataResponse->dataLen);
source->data_contents.size = formatDataResponse->dataLen;
FORM_DATA_RESP_COMM(*formatDataResponse, dataLen));
source->data_contents.size = FORM_DATA_RESP_COMM(*formatDataResponse, dataLen);
/* regardless data type, make sure it ends with NULL */
((char *)source->data_contents.data)[source->data_contents.size] = '\0';
/* data is ready, waiting to be written to destination */
@ -1621,7 +1647,8 @@ clipboard_client_format_list_response(CliprdrServerContext *context,
RdpPeerContext *ctx = (RdpPeerContext *)client->context;
struct rdp_backend *b = ctx->rdpBackend;
rdp_debug_clipboard(b, "Client: %s msgFlags:0x%x\n", __func__, formatListResponse->msgFlags);
rdp_debug_clipboard(b, "Client: %s msgFlags:0x%x\n", __func__,
FORM_DATA_RESP_COMM(*formatListResponse, msgFlags));
assert_not_compositor_thread(b);
return 0;
}