Merge pull request #4885 from akallabeth/autoreconnect_handle_window_events

Fixed #3423: Process xevents when in reconnect mode.
This commit is contained in:
David Fort 2018-10-03 09:42:16 +02:00 committed by GitHub
commit 2e1bf90bd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 187 additions and 60 deletions

View File

@ -68,7 +68,7 @@ void xf_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs*
}
else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0)
{
xf_disp_init(xfc, (DispClientContext*)e->pInterface);
xf_disp_init(xfc->xfDisp, (DispClientContext*)e->pInterface);
}
else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
{
@ -96,6 +96,10 @@ void xf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEven
{
xfc->rdpei = NULL;
}
else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0)
{
xf_disp_uninit(xfc->xfDisp, (DispClientContext*)e->pInterface);
}
else if (strcmp(e->name, TSMF_DVC_CHANNEL_NAME) == 0)
{
xf_tsmf_uninit(xfc, (TsmfClientContext*) e->pInterface);

View File

@ -1414,6 +1414,27 @@ static DWORD WINAPI xf_input_thread(LPVOID arg)
return 0;
}
static BOOL handle_window_events(freerdp* instance)
{
rdpSettings* settings;
if (!instance || !instance->settings)
return FALSE;
settings = instance->settings;
if (!settings->AsyncInput)
{
if (!xf_process_x_events(instance))
{
WLog_INFO(TAG, "Closed from X11");
return FALSE;
}
}
return TRUE;
}
/** Main loop for the rdp connection.
* It will be run from the thread's entry point (thread_func()).
* It initiates the connection, and will continue to run until the session ends,
@ -1552,7 +1573,7 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
{
if (!freerdp_check_event_handles(context))
{
if (client_auto_reconnect(instance))
if (client_auto_reconnect_ex(instance, handle_window_events))
continue;
else
{
@ -1571,14 +1592,8 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
}
}
if (!settings->AsyncInput)
{
if (!xf_process_x_events(instance))
{
WLog_INFO(TAG, "Closed from X11");
break;
}
}
if (!handle_window_events(instance))
break;
if ((status != WAIT_TIMEOUT) && (waitStatus == WAIT_OBJECT_0))
{

View File

@ -40,6 +40,7 @@
struct _xfDispContext
{
xfContext* xfc;
DispClientContext* disp;
BOOL haveXRandr;
int eventBase, errorBase;
int lastSentWidth, lastSentHeight;
@ -57,8 +58,7 @@ static UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, in
static BOOL xf_disp_settings_changed(xfDispContext* xfDisp)
{
rdpSettings* settings;
settings = xfDisp->xfc->context.settings;
rdpSettings* settings = xfDisp->xfc->context.settings;
if (xfDisp->lastSentWidth != xfDisp->targetWidth)
return TRUE;
@ -96,10 +96,19 @@ static BOOL xf_update_last_sent(xfDispContext* xfDisp)
static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
{
DISPLAY_CONTROL_MONITOR_LAYOUT layout;
xfContext* xfc = xfDisp->xfc;
rdpSettings* settings = xfc->context.settings;
xfContext* xfc;
rdpSettings* settings;
if (!xfDisp->activated)
if (!xfDisp || !xfDisp->xfc)
return FALSE;
xfc = xfDisp->xfc;
settings = xfc->context.settings;
if (!settings)
return FALSE;
if (!xfDisp->activated || !xfDisp->disp)
return TRUE;
if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY)
@ -112,7 +121,7 @@ static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
if (xfc->fullscreen && (settings->MonitorCount > 0))
{
if (xf_disp_sendLayout(xfc->disp, settings->MonitorDefArray,
if (xf_disp_sendLayout(xfDisp->disp, settings->MonitorDefArray,
settings->MonitorCount) != CHANNEL_RC_OK)
return FALSE;
}
@ -129,14 +138,14 @@ static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
layout.PhysicalWidth = xfDisp->targetWidth;
layout.PhysicalHeight = xfDisp->targetHeight;
if (xfc->disp->SendMonitorLayout(xfc->disp, 1, &layout) != CHANNEL_RC_OK)
if (IFCALLRESULT(CHANNEL_RC_OK, xfDisp->disp->SendMonitorLayout, xfDisp->disp, 1,
&layout) != CHANNEL_RC_OK)
return FALSE;
}
return xf_update_last_sent(xfDisp);
}
static BOOL xf_disp_set_window_resizable(xfDispContext* xfDisp)
{
XSizeHints* size_hints;
@ -156,12 +165,37 @@ static BOOL xf_disp_set_window_resizable(xfDispContext* xfDisp)
return TRUE;
}
static BOOL xf_disp_check_context(void* context, xfContext** ppXfc, xfDispContext** ppXfDisp,
rdpSettings** ppSettings)
{
xfContext* xfc;
if (!context)
return FALSE;
xfc = (xfContext*)context;
if (!(xfc->xfDisp))
return FALSE;
if (!xfc->context.settings)
return FALSE;
*ppXfc = xfc;
*ppXfDisp = xfc->xfDisp;
*ppSettings = xfc->context.settings;
return TRUE;
}
static void xf_disp_OnActivated(void* context, ActivatedEventArgs* e)
{
xfContext* xfc = (xfContext*)context;
xfDispContext* xfDisp = xfc->xfDisp;
rdpSettings* settings = xfc->context.settings;
xfContext* xfc;
xfDispContext* xfDisp;
rdpSettings* settings;
if (!xf_disp_check_context(context, &xfc, &xfDisp, &settings))
return;
xfDisp->waitingResize = FALSE;
if (xfDisp->activated && !settings->Fullscreen)
@ -175,12 +209,15 @@ static void xf_disp_OnActivated(void* context, ActivatedEventArgs* e)
}
}
static void xf_disp_OnGraphicsReset(void* context, GraphicsResetEventArgs* e)
{
xfContext* xfc = (xfContext*)context;
xfDispContext* xfDisp = xfc->xfDisp;
rdpSettings* settings = xfc->context.settings;
xfContext* xfc;
xfDispContext* xfDisp;
rdpSettings* settings;
if (!xf_disp_check_context(context, &xfc, &xfDisp, &settings))
return;
xfDisp->waitingResize = FALSE;
if (xfDisp->activated && !settings->Fullscreen)
@ -192,9 +229,12 @@ static void xf_disp_OnGraphicsReset(void* context, GraphicsResetEventArgs* e)
static void xf_disp_OnTimer(void* context, TimerEventArgs* e)
{
xfContext* xfc = (xfContext*)context;
xfDispContext* xfDisp = xfc->xfDisp;
rdpSettings* settings = xfc->context.settings;
xfContext* xfc;
xfDispContext* xfDisp;
rdpSettings* settings;
if (!xf_disp_check_context(context, &xfc, &xfDisp, &settings))
return;
if (!xfDisp->activated || settings->Fullscreen)
return;
@ -204,7 +244,12 @@ static void xf_disp_OnTimer(void* context, TimerEventArgs* e)
xfDispContext* xf_disp_new(xfContext* xfc)
{
xfDispContext* ret = calloc(1, sizeof(xfDispContext));
xfDispContext* ret;
if (!xfc || !xfc->context.settings || !xfc->context.pubSub)
return NULL;
ret = calloc(1, sizeof(xfDispContext));
if (!ret)
return NULL;
@ -228,13 +273,20 @@ xfDispContext* xf_disp_new(xfContext* xfc)
void xf_disp_free(xfDispContext* disp)
{
PubSub_UnsubscribeActivated(disp->xfc->context.pubSub, xf_disp_OnActivated);
PubSub_UnsubscribeGraphicsReset(disp->xfc->context.pubSub, xf_disp_OnGraphicsReset);
PubSub_UnsubscribeTimer(disp->xfc->context.pubSub, xf_disp_OnTimer);
if (!disp)
return;
if (disp->xfc)
{
PubSub_UnsubscribeActivated(disp->xfc->context.pubSub, xf_disp_OnActivated);
PubSub_UnsubscribeGraphicsReset(disp->xfc->context.pubSub, xf_disp_OnGraphicsReset);
PubSub_UnsubscribeTimer(disp->xfc->context.pubSub, xf_disp_OnTimer);
}
free(disp);
}
static UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, int nmonitors)
UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, int nmonitors)
{
UINT ret = CHANNEL_RC_OK;
DISPLAY_CONTROL_MONITOR_LAYOUT* layouts;
@ -288,18 +340,31 @@ static UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, in
layouts[i].DeviceScaleFactor = settings->DeviceScaleFactor;
}
ret = disp->SendMonitorLayout(disp, nmonitors, layouts);
ret = IFCALLRESULT(CHANNEL_RC_OK, disp->SendMonitorLayout, disp, nmonitors, layouts);
free(layouts);
return ret;
}
BOOL xf_disp_handle_xevent(xfContext* xfc, XEvent* event)
{
xfDispContext* xfDisp = xfc->xfDisp;
rdpSettings* settings = xfc->context.settings;
xfDispContext* xfDisp;
rdpSettings* settings;
UINT32 maxWidth, maxHeight;
if (!xfDisp->haveXRandr)
if (!xfc || !event)
return FALSE;
xfDisp = xfc->xfDisp;
if (!xfDisp)
return FALSE;
settings = xfc->context.settings;
if (!settings)
return FALSE;
if (!xfDisp->haveXRandr || !xfDisp->disp)
return TRUE;
#ifdef USABLE_XRANDR
@ -309,22 +374,29 @@ BOOL xf_disp_handle_xevent(xfContext* xfc, XEvent* event)
#endif
xf_detect_monitors(xfc, &maxWidth, &maxHeight);
return xf_disp_sendLayout(xfc->disp, settings->MonitorDefArray,
return xf_disp_sendLayout(xfDisp->disp, settings->MonitorDefArray,
settings->MonitorCount) == CHANNEL_RC_OK;
}
BOOL xf_disp_handle_configureNotify(xfContext* xfc, int width, int height)
{
xfDispContext* xfDisp = xfc->xfDisp;
xfDispContext* xfDisp;
if (!xfc)
return FALSE;
xfDisp = xfc->xfDisp;
if (!xfDisp)
return FALSE;
xfDisp->targetWidth = width;
xfDisp->targetHeight = height;
return xf_disp_sendResize(xfDisp);
}
UINT xf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors,
UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB)
static UINT xf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors,
UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB)
{
/* we're called only if dynamic resolution update is activated */
xfDispContext* xfDisp = (xfDispContext*)disp->custom;
@ -341,11 +413,20 @@ UINT xf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors,
return xf_disp_set_window_resizable(xfDisp) ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY;
}
BOOL xf_disp_init(xfContext* xfc, DispClientContext* disp)
BOOL xf_disp_init(xfDispContext* xfDisp, DispClientContext* disp)
{
rdpSettings* settings = xfc->context.settings;
xfc->disp = disp;
disp->custom = (void*) xfc->xfDisp;
rdpSettings* settings;
if (!xfDisp || !xfDisp->xfc || !disp)
return FALSE;
settings = xfDisp->xfc->context.settings;
if (!settings)
return FALSE;
xfDisp->disp = disp;
disp->custom = (void*) xfDisp;
if (settings->DynamicResolutionUpdate)
{
@ -355,7 +436,8 @@ BOOL xf_disp_init(xfContext* xfc, DispClientContext* disp)
if (settings->Fullscreen)
{
/* ask X11 to notify us of screen changes */
XRRSelectInput(xfc->display, DefaultRootWindow(xfc->display), RRScreenChangeNotifyMask);
XRRSelectInput(xfDisp->xfc->display, DefaultRootWindow(xfDisp->xfc->display),
RRScreenChangeNotifyMask);
}
#endif
@ -364,3 +446,10 @@ BOOL xf_disp_init(xfContext* xfc, DispClientContext* disp)
return TRUE;
}
BOOL xf_disp_uninit(xfDispContext* xfDisp, DispClientContext* disp)
{
if (!xfDisp || !disp)
return FALSE;
xfDisp->disp = NULL;
}

View File

@ -25,12 +25,13 @@
#include "xf_client.h"
#include "xfreerdp.h"
FREERDP_API BOOL xf_disp_init(xfContext* xfc, DispClientContext *disp);
FREERDP_API BOOL xf_disp_init(xfDispContext* xfDisp, DispClientContext* disp);
FREERDP_API BOOL xf_disp_uninit(xfDispContext* xfDisp, DispClientContext* disp);
xfDispContext *xf_disp_new(xfContext* xfc);
void xf_disp_free(xfDispContext *disp);
BOOL xf_disp_handle_xevent(xfContext *xfc, XEvent *event);
BOOL xf_disp_handle_configureNotify(xfContext *xfc, int width, int height);
void xf_disp_resized(xfDispContext *disp);
xfDispContext* xf_disp_new(xfContext* xfc);
void xf_disp_free(xfDispContext* disp);
BOOL xf_disp_handle_xevent(xfContext* xfc, XEvent* event);
BOOL xf_disp_handle_configureNotify(xfContext* xfc, int width, int height);
void xf_disp_resized(xfDispContext* disp);
#endif /* FREERDP_CLIENT_X11_DISP_H */

View File

@ -1112,7 +1112,7 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
break;
default:
if (settings->SupportDisplayControl && xfc->xfDisp)
if (settings->SupportDisplayControl)
xf_disp_handle_xevent(xfc, event);
break;

View File

@ -221,7 +221,6 @@ struct xf_context
RdpeiClientContext* rdpei;
EncomspClientContext* encomsp;
xfDispContext* xfDisp;
DispClientContext* disp;
RailClientContext* rail;
wHashTable* railWindows;

View File

@ -554,6 +554,11 @@ DWORD client_cli_verify_changed_certificate(freerdp* instance,
}
BOOL client_auto_reconnect(freerdp* instance)
{
return client_auto_reconnect_ex(instance, NULL);
}
BOOL client_auto_reconnect_ex(freerdp* instance, BOOL(*window_events)(freerdp* instance))
{
UINT32 maxRetries;
UINT32 numRetries = 0;
@ -581,6 +586,8 @@ BOOL client_auto_reconnect(freerdp* instance)
/* Perform an auto-reconnect. */
while (TRUE)
{
UINT32 x;
/* Quit retrying if max retries has been exceeded */
if ((maxRetries > 0) && (numRetries++ >= maxRetries))
{
@ -593,7 +600,13 @@ BOOL client_auto_reconnect(freerdp* instance)
if (freerdp_reconnect(instance))
return TRUE;
Sleep(5000);
for (x = 0; x < 50; x++)
{
if (!IFCALLRESULT(TRUE, window_events, instance))
return FALSE;
Sleep(100);
}
}
WLog_ERR(TAG, "Maximum reconnect retries exceeded");

View File

@ -113,6 +113,8 @@ FREERDP_API DWORD client_cli_verify_changed_certificate(freerdp* instance, const
const char* old_subject, const char* old_issuer,
const char* old_fingerprint);
FREERDP_API BOOL client_auto_reconnect(freerdp* instance);
FREERDP_API BOOL client_auto_reconnect_ex(freerdp* instance,
BOOL(*window_events)(freerdp* instance));
#ifdef __cplusplus
}

View File

@ -782,13 +782,16 @@ int transport_write(rdpTransport* transport, wStream* s)
int status = -1;
int writtenlength = 0;
if (!transport)
if (!s)
return -1;
if (!transport)
goto fail;
if (!transport->frontBio)
{
transport->layer = TRANSPORT_LAYER_CLOSED;
return -1;
goto fail;
}
EnterCriticalSection(&(transport->WriteLock));
@ -868,8 +871,9 @@ out_cleanup:
transport->layer = TRANSPORT_LAYER_CLOSED;
}
Stream_Release(s);
LeaveCriticalSection(&(transport->WriteLock));
fail:
Stream_Release(s);
return status;
}