From 0fd705c6c731fd28098ece5f7714e2aa0d7e42fb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 16 Aug 2013 16:46:47 -0400 Subject: [PATCH] channels/cliprdr: start server-side implementation --- channels/cliprdr/CMakeLists.txt | 3 + channels/cliprdr/ChannelOptions.cmake | 2 +- channels/cliprdr/server/CMakeLists.txt | 35 +++++++ channels/cliprdr/server/cliprdr_main.c | 184 +++++++++++++++++++++++++++++++++ channels/cliprdr/server/cliprdr_main.h | 36 +++++++ channels/server/channels.c | 14 ++- client/Windows/wf_interface.c | 2 +- client/X11/xf_client.c | 2 +- include/freerdp/channels/wtsvc.h | 1 + include/freerdp/client/cliprdr.h | 2 + include/freerdp/codec/rfx.h | 4 +- include/freerdp/server/cliprdr.h | 59 +++++++++++ libfreerdp/codec/rfx.c | 49 +++++++-- libfreerdp/gdi/gdi.c | 2 +- server/Mac/mf_peer.c | 2 +- server/Sample/sfreerdp.c | 2 +- server/Windows/wf_update.c | 2 +- server/X11/xf_peer.c | 2 +- 18 files changed, 383 insertions(+), 20 deletions(-) create mode 100644 channels/cliprdr/server/CMakeLists.txt create mode 100644 channels/cliprdr/server/cliprdr_main.c create mode 100644 channels/cliprdr/server/cliprdr_main.h create mode 100644 include/freerdp/server/cliprdr.h diff --git a/channels/cliprdr/CMakeLists.txt b/channels/cliprdr/CMakeLists.txt index b5f1cf4..c5cfd72 100644 --- a/channels/cliprdr/CMakeLists.txt +++ b/channels/cliprdr/CMakeLists.txt @@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS) add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) endif() +if(WITH_SERVER_CHANNELS) + add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() diff --git a/channels/cliprdr/ChannelOptions.cmake b/channels/cliprdr/ChannelOptions.cmake index 9cafcd9..f175f3f 100644 --- a/channels/cliprdr/ChannelOptions.cmake +++ b/channels/cliprdr/ChannelOptions.cmake @@ -1,7 +1,7 @@ set(OPTION_DEFAULT OFF) set(OPTION_CLIENT_DEFAULT ON) -set(OPTION_SERVER_DEFAULT OFF) +set(OPTION_SERVER_DEFAULT ON) define_channel_options(NAME "cliprdr" TYPE "static" DESCRIPTION "Clipboard Virtual Channel Extension" diff --git a/channels/cliprdr/server/CMakeLists.txt b/channels/cliprdr/server/CMakeLists.txt new file mode 100644 index 0000000..3e2ef0b --- /dev/null +++ b/channels/cliprdr/server/CMakeLists.txt @@ -0,0 +1,35 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +define_channel_server("cliprdr") + +set(${MODULE_PREFIX}_SRCS + cliprdr_main.c + cliprdr_main.h) + +add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry") + +set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") + +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE freerdp + MODULES freerdp-utils) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c new file mode 100644 index 0000000..7323513 --- /dev/null +++ b/channels/cliprdr/server/cliprdr_main.c @@ -0,0 +1,184 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Clipboard Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "cliprdr_main.h" + +/** + * Initialization Sequence\n + * Client Server\n + * | |\n + * |<----------------------Server Clipboard Capabilities PDU-----------------|\n + * |<-----------------------------Monitor Ready PDU--------------------------|\n + * |-----------------------Client Clipboard Capabilities PDU---------------->|\n + * |---------------------------Temporary Directory PDU---------------------->|\n + * |-------------------------------Format List PDU-------------------------->|\n + * |<--------------------------Format List Response PDU----------------------|\n + * + */ + +static int cliprdr_server_send_capabilities(CliprdrServerContext* context) +{ + return 0; +} + +static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context) +{ + return 0; +} + +static int cliprdr_server_send_format_list_response(CliprdrServerContext* context) +{ + return 0; +} + +static void* cliprdr_server_thread(void* arg) +{ + wStream* s; + DWORD status; + DWORD nCount; + void* buffer; + HANDLE events[8]; + HANDLE ChannelEvent; + UINT32 BytesReturned; + CliprdrServerContext* context; + + context = (CliprdrServerContext*) arg; + + buffer = NULL; + BytesReturned = 0; + ChannelEvent = NULL; + + s = Stream_New(NULL, 4096); + + if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) + { + if (BytesReturned == sizeof(HANDLE)) + CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); + + WTSFreeMemory(buffer); + } + + nCount = 0; + events[nCount++] = ChannelEvent; + events[nCount++] = context->priv->StopEvent; + + while (1) + { + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + + if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) + { + if (BytesReturned == 0) + break; + + Stream_EnsureRemainingCapacity(s, (int) BytesReturned); + + if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) + { + break; + } + } + } + + Stream_Free(s, TRUE); + + return NULL; +} + +static int cliprdr_server_start(CliprdrServerContext* context) +{ + context->priv->ChannelHandle = WTSVirtualChannelOpenEx(context->vcm, "cliprdr", 0); + + if (!context->priv->ChannelHandle) + return -1; + + context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + context->priv->Thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL); + + return 0; +} + +static int cliprdr_server_stop(CliprdrServerContext* context) +{ + SetEvent(context->priv->StopEvent); + + WaitForSingleObject(context->priv->Thread, INFINITE); + CloseHandle(context->priv->Thread); + + return 0; +} + +CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm) +{ + CliprdrServerContext* context; + + context = (CliprdrServerContext*) malloc(sizeof(CliprdrServerContext)); + + if (context) + { + ZeroMemory(context, sizeof(CliprdrServerContext)); + + context->vcm = vcm; + + context->Start = cliprdr_server_start; + context->Stop = cliprdr_server_stop; + + context->SendCapabilities = cliprdr_server_send_capabilities; + context->SendMonitorReady = cliprdr_server_send_monitor_ready; + context->SendFormatListResponse = cliprdr_server_send_format_list_response; + + context->priv = (CliprdrServerPrivate*) malloc(sizeof(CliprdrServerPrivate)); + + if (context->priv) + { + ZeroMemory(context->priv, sizeof(CliprdrServerPrivate)); + } + } + + return context; +} + +void cliprdr_server_context_free(CliprdrServerContext* context) +{ + if (context) + { + if (context->priv) + { + free(context->priv); + } + + free(context); + } +} diff --git a/channels/cliprdr/server/cliprdr_main.h b/channels/cliprdr/server/cliprdr_main.h new file mode 100644 index 0000000..540c333 --- /dev/null +++ b/channels/cliprdr/server/cliprdr_main.h @@ -0,0 +1,36 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Clipboard Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H +#define FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H + +#include +#include +#include + +#include + +struct _cliprdr_server_private +{ + HANDLE Thread; + HANDLE StopEvent; + void* ChannelHandle; +}; + +#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H */ diff --git a/channels/server/channels.c b/channels/server/channels.c index eeae1dc..2bef641 100644 --- a/channels/server/channels.c +++ b/channels/server/channels.c @@ -42,6 +42,7 @@ #include #include +#include void freerdp_channels_dummy() { @@ -50,6 +51,9 @@ void freerdp_channels_dummy() rdpsnd_server_context_new(NULL); rdpsnd_server_context_free(NULL); + + cliprdr_server_context_new(NULL); + cliprdr_server_context_free(NULL); } /** @@ -420,7 +424,7 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client) vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager)); - if (vcm != NULL) + if (vcm) { ZeroMemory(vcm, sizeof(WTSVirtualChannelManager)); @@ -659,6 +663,7 @@ BOOL WTSVirtualChannelQuery( BOOL result = FALSE; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; ZeroMemory(fds, sizeof(fds)); + switch (WtsVirtualClass) { case WTSVirtualFileHandle: @@ -677,6 +682,13 @@ BOOL WTSVirtualChannelQuery( result = TRUE; break; + case WTSVirtualEventHandle: + *ppBuffer = malloc(sizeof(HANDLE)); + CopyMemory(*ppBuffer, &(channel->receive_event), sizeof(HANDLE)); + *pBytesReturned = sizeof(void*); + result = TRUE; + break; + case WTSVirtualChannelReady: if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 9ae2de7..d3c76aa 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -371,7 +371,7 @@ BOOL wf_post_connect(freerdp* instance) if (settings->RemoteFxCodec) { wfc->tile = wf_image_new(wfc, 64, 64, 32, NULL); - wfc->rfx_context = rfx_context_new(); + wfc->rfx_context = rfx_context_new(FALSE); } if (settings->NSCodec) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 5ad3f4f..273df06 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -893,7 +893,7 @@ BOOL xf_post_connect(freerdp* instance) if (instance->settings->RemoteFxCodec) { - rfx_context = (void*) rfx_context_new(); + rfx_context = (void*) rfx_context_new(FALSE); xfc->rfx_context = rfx_context; } diff --git a/include/freerdp/channels/wtsvc.h b/include/freerdp/channels/wtsvc.h index 227c75f..1b59d8e 100644 --- a/include/freerdp/channels/wtsvc.h +++ b/include/freerdp/channels/wtsvc.h @@ -43,6 +43,7 @@ typedef enum _WTS_VIRTUAL_CLASS { WTSVirtualClientData, WTSVirtualFileHandle, + WTSVirtualEventHandle, WTSVirtualChannelReady } WTS_VIRTUAL_CLASS; diff --git a/include/freerdp/client/cliprdr.h b/include/freerdp/client/cliprdr.h index ea0d1cf..a0455dc 100644 --- a/include/freerdp/client/cliprdr.h +++ b/include/freerdp/client/cliprdr.h @@ -20,6 +20,8 @@ #ifndef FREERDP_CHANNEL_CLIENT_CLIPRDR_H #define FREERDP_CHANNEL_CLIENT_CLIPRDR_H +#include + /** * Client Interface */ diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 254cadf..d8fa52c 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -55,7 +55,6 @@ struct _RFX_TILE int height; BYTE* data; int scanline; - BYTE quantIdxY; BYTE quantIdxCb; BYTE quantIdxCr; @@ -117,6 +116,7 @@ struct _RFX_CONTEXT { RFX_STATE state; + BOOL encoder; UINT16 flags; UINT16 properties; UINT16 width; @@ -152,7 +152,7 @@ struct _RFX_CONTEXT }; typedef struct _RFX_CONTEXT RFX_CONTEXT; -FREERDP_API RFX_CONTEXT* rfx_context_new(void); +FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder); FREERDP_API void rfx_context_free(RFX_CONTEXT* context); FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format); FREERDP_API void rfx_context_reset(RFX_CONTEXT* context); diff --git a/include/freerdp/server/cliprdr.h b/include/freerdp/server/cliprdr.h new file mode 100644 index 0000000..01e612b --- /dev/null +++ b/include/freerdp/server/cliprdr.h @@ -0,0 +1,59 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Clipboard Virtual Channel Server Interface + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_SERVER_CLIPRDR_H +#define FREERDP_CHANNEL_SERVER_CLIPRDR_H + +#include +#include +#include +#include + +/** + * Server Interface + */ + +typedef struct _cliprdr_server_context CliprdrServerContext; +typedef struct _cliprdr_server_private CliprdrServerPrivate; + +typedef int (*psCliprdrStart)(CliprdrServerContext* context); +typedef int (*psCliprdrStop)(CliprdrServerContext* context); + +typedef int (*psCliprdrSendCapabilities)(CliprdrServerContext* context); +typedef int (*psCliprdrSendMonitorReady)(CliprdrServerContext* context); +typedef int (*psCliprdrSendFormatListResponse)(CliprdrServerContext* context); + +struct _cliprdr_server_context +{ + WTSVirtualChannelManager* vcm; + + psCliprdrStart Start; + psCliprdrStop Stop; + + psCliprdrSendCapabilities SendCapabilities; + psCliprdrSendMonitorReady SendMonitorReady; + psCliprdrSendFormatListResponse SendFormatListResponse; + + CliprdrServerPrivate* priv; +}; + +FREERDP_API CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm); +FREERDP_API void cliprdr_server_context_free(CliprdrServerContext* context); + +#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_H */ diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 5d6bbe7..d6e6547 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -153,7 +153,7 @@ void rfx_tile_init(RFX_TILE* tile) } } -RFX_TILE* rfx_tile_new() +RFX_TILE* rfx_decoder_tile_new() { RFX_TILE* tile = NULL; @@ -169,7 +169,7 @@ RFX_TILE* rfx_tile_new() return tile; } -void rfx_tile_free(RFX_TILE* tile) +void rfx_decoder_tile_free(RFX_TILE* tile) { if (tile) { @@ -178,7 +178,29 @@ void rfx_tile_free(RFX_TILE* tile) } } -RFX_CONTEXT* rfx_context_new(void) +RFX_TILE* rfx_encoder_tile_new() +{ + RFX_TILE* tile = NULL; + + tile = (RFX_TILE*) malloc(sizeof(RFX_TILE)); + + if (tile) + { + ZeroMemory(tile, sizeof(RFX_TILE)); + } + + return tile; +} + +void rfx_encoder_tile_free(RFX_TILE* tile) +{ + if (tile) + { + free(tile); + } +} + +RFX_CONTEXT* rfx_context_new(BOOL encoder) { HKEY hKey; LONG status; @@ -191,13 +213,24 @@ RFX_CONTEXT* rfx_context_new(void) context = (RFX_CONTEXT*) malloc(sizeof(RFX_CONTEXT)); ZeroMemory(context, sizeof(RFX_CONTEXT)); + context->encoder = encoder; + context->priv = (RFX_CONTEXT_PRIV*) malloc(sizeof(RFX_CONTEXT_PRIV)); ZeroMemory(context->priv, sizeof(RFX_CONTEXT_PRIV)); context->priv->TilePool = ObjectPool_New(TRUE); - ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_tile_new; ObjectPool_Object(context->priv->TilePool)->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init; - ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_tile_free; + + if (context->encoder) + { + ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_encoder_tile_new; + ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_encoder_tile_free; + } + else + { + ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_decoder_tile_new; + ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_decoder_tile_free; + } /* * align buffers to 16 byte boundary (needed for SSE/NEON instructions) @@ -1065,7 +1098,8 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, if (!context->numQuant) { context->numQuant = 1; - context->quants = (UINT32*) rfx_default_quantization_values; + context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values)); + CopyMemory(context->quants, &rfx_default_quantization_values, sizeof(rfx_default_quantization_values)); context->quantIdxY = 0; context->quantIdxCb = 0; context->quantIdxCr = 0; @@ -1225,9 +1259,6 @@ RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, in RFX_MESSAGE* message; RFX_MESSAGE* messages; - printf("rfx_encode_messages: numRects: %d maxDataSize: %d x: %d y: %d w: %d/%d h: %d/%d\n", numRects, maxDataSize, - rects[0].x, rects[0].y, rects[0].width, width, rects[0].height, height); - message = rfx_encode_message(context, rects, numRects, data, width, height, scanline); messages = rfx_split_message(context, message, numMessages, maxDataSize); rfx_message_free(context, message); diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 95443ab..566a12d 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -1042,7 +1042,7 @@ int gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer) gdi_register_graphics(instance->context->graphics); - gdi->rfx_context = rfx_context_new(); + gdi->rfx_context = rfx_context_new(FALSE); gdi->nsc_context = nsc_context_new(); return 0; diff --git a/server/Mac/mf_peer.c b/server/Mac/mf_peer.c index 074ece0..0d059cf 100644 --- a/server/Mac/mf_peer.c +++ b/server/Mac/mf_peer.c @@ -175,7 +175,7 @@ void mf_peer_rfx_update(freerdp_peer* client) int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context) { context->info = mf_info_get_instance(); - context->rfx_context = rfx_context_new(); + context->rfx_context = rfx_context_new(TRUE); context->rfx_context->mode = RLGR3; context->rfx_context->width = client->settings->DesktopWidth; context->rfx_context->height = client->settings->DesktopHeight; diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index e988a2e..a889861 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -49,7 +49,7 @@ static BOOL test_dump_rfx_realtime = TRUE; void test_peer_context_new(freerdp_peer* client, testPeerContext* context) { - context->rfx_context = rfx_context_new(); + context->rfx_context = rfx_context_new(TRUE); context->rfx_context->mode = RLGR3; context->rfx_context->width = SAMPLE_SERVER_DEFAULT_WIDTH; context->rfx_context->height = SAMPLE_SERVER_DEFAULT_HEIGHT; diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index e6daf5c..0332316 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -198,7 +198,7 @@ void wf_update_encoder_reset(wfInfo* wfi) } else { - wfi->rfx_context = rfx_context_new(); + wfi->rfx_context = rfx_context_new(TRUE); wfi->rfx_context->mode = RLGR3; wfi->rfx_context->width = wfi->servscreen_width; wfi->rfx_context->height = wfi->servscreen_height; diff --git a/server/X11/xf_peer.c b/server/X11/xf_peer.c index 7b08eff..fe92598 100644 --- a/server/X11/xf_peer.c +++ b/server/X11/xf_peer.c @@ -295,7 +295,7 @@ xfInfo* xf_info_init() void xf_peer_context_new(freerdp_peer* client, xfPeerContext* context) { context->info = xf_info_init(); - context->rfx_context = rfx_context_new(); + context->rfx_context = rfx_context_new(TRUE); context->rfx_context->mode = RLGR3; context->rfx_context->width = context->info->width; context->rfx_context->height = context->info->height; -- 2.7.4