2017-11-29 12:26:04 +03:00
|
|
|
/**
|
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
|
|
* X11 Display Control channel
|
|
|
|
*
|
|
|
|
* Copyright 2017 David Fort <contact@hardening-consulting.com>
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2017-12-19 17:16:14 +03:00
|
|
|
#include <winpr/sysinfo.h>
|
2017-11-29 12:26:04 +03:00
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
|
|
|
#ifdef WITH_XRANDR
|
|
|
|
#include <X11/extensions/Xrandr.h>
|
|
|
|
#include <X11/extensions/randr.h>
|
2017-12-19 17:16:14 +03:00
|
|
|
|
2017-12-23 12:27:38 +03:00
|
|
|
#if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105
|
2017-12-19 17:16:14 +03:00
|
|
|
# define USABLE_XRANDR
|
|
|
|
#endif
|
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "xf_disp.h"
|
|
|
|
#include "xf_monitor.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define TAG CLIENT_TAG("x11disp")
|
2017-12-19 17:16:14 +03:00
|
|
|
#define RESIZE_MIN_DELAY 200 /* minimum delay in ms between two resizes */
|
2017-11-29 12:26:04 +03:00
|
|
|
|
|
|
|
struct _xfDispContext
|
|
|
|
{
|
2018-07-18 10:31:04 +03:00
|
|
|
xfContext* xfc;
|
2018-09-24 17:44:25 +03:00
|
|
|
DispClientContext* disp;
|
2017-11-29 12:26:04 +03:00
|
|
|
BOOL haveXRandr;
|
|
|
|
int eventBase, errorBase;
|
2017-12-19 17:16:14 +03:00
|
|
|
int lastSentWidth, lastSentHeight;
|
|
|
|
UINT64 lastSentDate;
|
|
|
|
int targetWidth, targetHeight;
|
2017-11-29 12:26:04 +03:00
|
|
|
BOOL activated;
|
|
|
|
BOOL waitingResize;
|
2018-08-08 14:04:26 +03:00
|
|
|
BOOL fullscreen;
|
2018-07-18 10:31:04 +03:00
|
|
|
UINT16 lastSentDesktopOrientation;
|
|
|
|
UINT32 lastSentDesktopScaleFactor;
|
|
|
|
UINT32 lastSentDeviceScaleFactor;
|
2017-11-29 12:26:04 +03:00
|
|
|
};
|
|
|
|
|
2018-08-08 14:04:26 +03:00
|
|
|
static UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, int nmonitors);
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
static BOOL xf_disp_settings_changed(xfDispContext* xfDisp)
|
|
|
|
{
|
2018-10-02 13:33:52 +03:00
|
|
|
rdpSettings* settings = xfDisp->xfc->context.settings;
|
2018-07-18 10:31:04 +03:00
|
|
|
|
|
|
|
if (xfDisp->lastSentWidth != xfDisp->targetWidth)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (xfDisp->lastSentHeight != xfDisp->targetHeight)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (xfDisp->lastSentDesktopOrientation != settings->DesktopOrientation)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (xfDisp->lastSentDesktopScaleFactor != settings->DesktopScaleFactor)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (xfDisp->lastSentDeviceScaleFactor != settings->DeviceScaleFactor)
|
|
|
|
return TRUE;
|
|
|
|
|
2018-08-08 14:04:26 +03:00
|
|
|
if (xfDisp->fullscreen != xfDisp->xfc->fullscreen)
|
|
|
|
return TRUE;
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL xf_update_last_sent(xfDispContext* xfDisp)
|
|
|
|
{
|
2018-10-02 13:33:52 +03:00
|
|
|
rdpSettings* settings = xfDisp->xfc->context.settings;
|
2018-07-18 10:31:04 +03:00
|
|
|
xfDisp->lastSentWidth = xfDisp->targetWidth;
|
|
|
|
xfDisp->lastSentHeight = xfDisp->targetHeight;
|
|
|
|
xfDisp->lastSentDesktopOrientation = settings->DesktopOrientation;
|
|
|
|
xfDisp->lastSentDesktopScaleFactor = settings->DesktopScaleFactor;
|
|
|
|
xfDisp->lastSentDeviceScaleFactor = settings->DeviceScaleFactor;
|
2018-08-08 14:04:26 +03:00
|
|
|
xfDisp->fullscreen = xfDisp->xfc->fullscreen;
|
2018-07-18 10:31:04 +03:00
|
|
|
return TRUE;
|
|
|
|
}
|
2017-12-19 17:16:14 +03:00
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
|
2017-12-19 17:16:14 +03:00
|
|
|
{
|
|
|
|
DISPLAY_CONTROL_MONITOR_LAYOUT layout;
|
2018-09-24 17:24:32 +03:00
|
|
|
xfContext* xfc;
|
|
|
|
rdpSettings* settings;
|
|
|
|
|
|
|
|
if (!xfDisp || !xfDisp->xfc)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
xfc = xfDisp->xfc;
|
|
|
|
settings = xfc->context.settings;
|
|
|
|
|
|
|
|
if (!settings)
|
|
|
|
return FALSE;
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2018-09-24 17:44:25 +03:00
|
|
|
if (!xfDisp->activated || !xfDisp->disp)
|
2018-07-18 10:31:04 +03:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY)
|
|
|
|
return TRUE;
|
2017-12-19 17:16:14 +03:00
|
|
|
|
|
|
|
xfDisp->lastSentDate = GetTickCount64();
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
if (!xf_disp_settings_changed(xfDisp))
|
|
|
|
return TRUE;
|
|
|
|
|
2018-08-21 13:58:55 +03:00
|
|
|
if (xfc->fullscreen && (settings->MonitorCount > 0))
|
2018-08-08 14:04:26 +03:00
|
|
|
{
|
2018-09-24 17:44:25 +03:00
|
|
|
if (xf_disp_sendLayout(xfDisp->disp, settings->MonitorDefArray,
|
2018-08-08 14:04:26 +03:00
|
|
|
settings->MonitorCount) != CHANNEL_RC_OK)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xfDisp->waitingResize = TRUE;
|
|
|
|
layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY;
|
|
|
|
layout.Top = layout.Left = 0;
|
|
|
|
layout.Width = xfDisp->targetWidth;
|
|
|
|
layout.Height = xfDisp->targetHeight;
|
|
|
|
layout.Orientation = settings->DesktopOrientation;
|
|
|
|
layout.DesktopScaleFactor = settings->DesktopScaleFactor;
|
|
|
|
layout.DeviceScaleFactor = settings->DeviceScaleFactor;
|
|
|
|
layout.PhysicalWidth = xfDisp->targetWidth;
|
|
|
|
layout.PhysicalHeight = xfDisp->targetHeight;
|
|
|
|
|
2018-09-24 17:44:25 +03:00
|
|
|
if (IFCALLRESULT(CHANNEL_RC_OK, xfDisp->disp->SendMonitorLayout, xfDisp->disp, 1,
|
2018-09-24 17:24:32 +03:00
|
|
|
&layout) != CHANNEL_RC_OK)
|
2018-08-08 14:04:26 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
2018-07-18 10:31:04 +03:00
|
|
|
|
|
|
|
return xf_update_last_sent(xfDisp);
|
2017-12-19 17:16:14 +03:00
|
|
|
}
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
static BOOL xf_disp_set_window_resizable(xfDispContext* xfDisp)
|
2017-12-19 17:16:14 +03:00
|
|
|
{
|
2018-07-18 10:31:04 +03:00
|
|
|
XSizeHints* size_hints;
|
2017-12-19 17:16:14 +03:00
|
|
|
|
|
|
|
if (!(size_hints = XAllocSizeHints()))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
size_hints->flags = PMinSize | PMaxSize | PWinGravity;
|
|
|
|
size_hints->win_gravity = NorthWestGravity;
|
|
|
|
size_hints->min_width = size_hints->min_height = 320;
|
|
|
|
size_hints->max_width = size_hints->max_height = 8192;
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-12-20 18:16:33 +03:00
|
|
|
if (xfDisp->xfc->window)
|
|
|
|
XSetWMNormalHints(xfDisp->xfc->display, xfDisp->xfc->window->handle, size_hints);
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-12-19 17:16:14 +03:00
|
|
|
XFree(size_hints);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-10-02 13:33:52 +03:00
|
|
|
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;
|
|
|
|
}
|
2017-12-19 17:16:14 +03:00
|
|
|
|
2018-02-14 12:14:33 +03:00
|
|
|
static void xf_disp_OnActivated(void* context, ActivatedEventArgs* e)
|
2017-12-19 17:16:14 +03:00
|
|
|
{
|
2018-10-02 13:33:52 +03:00
|
|
|
xfContext* xfc;
|
|
|
|
xfDispContext* xfDisp;
|
|
|
|
rdpSettings* settings;
|
|
|
|
|
|
|
|
if (!xf_disp_check_context(context, &xfc, &xfDisp, &settings))
|
|
|
|
return;
|
|
|
|
|
2017-12-19 17:16:14 +03:00
|
|
|
xfDisp->waitingResize = FALSE;
|
|
|
|
|
|
|
|
if (xfDisp->activated && !settings->Fullscreen)
|
|
|
|
{
|
|
|
|
xf_disp_set_window_resizable(xfDisp);
|
|
|
|
|
|
|
|
if (e->firstActivation)
|
|
|
|
return;
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
xf_disp_sendResize(xfDisp);
|
2017-12-19 17:16:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-14 12:14:33 +03:00
|
|
|
static void xf_disp_OnGraphicsReset(void* context, GraphicsResetEventArgs* e)
|
Fix for #4330
Since ec027bf dynamic resolution is broken when used with egfx. Before that commit
we were tracking a server sent resize by setting a DesktopResize callback. This callback
is called when the desktop is resized by the server. Anyway the problem was that when this
callback is called, the activation sequence is not always completed, which were leading to
some freeze with 2012r2 servers (sending packets before the sequence is finished).
So with the faulty commit, we are tracking server resizes by subscribing to the Actived
event, that is called at the end of a reactivation sequence, so we're sure to not send packets
when not fully activated.
Anyway the issue that shows on (#4330) is that when you use egfx, no reactivation sequence happens,
the server only sends a ResetGraphics message with the new size, and so we miss the resized event.
This fix introduces a new GraphicsReset event, makes the display channel subscribe to that event,
and react accordingly.
2017-12-23 15:50:54 +03:00
|
|
|
{
|
2018-10-02 13:33:52 +03:00
|
|
|
xfContext* xfc;
|
|
|
|
xfDispContext* xfDisp;
|
|
|
|
rdpSettings* settings;
|
|
|
|
|
2019-02-07 19:53:21 +03:00
|
|
|
WINPR_UNUSED(e);
|
|
|
|
|
2018-10-02 13:33:52 +03:00
|
|
|
if (!xf_disp_check_context(context, &xfc, &xfDisp, &settings))
|
|
|
|
return;
|
|
|
|
|
Fix for #4330
Since ec027bf dynamic resolution is broken when used with egfx. Before that commit
we were tracking a server sent resize by setting a DesktopResize callback. This callback
is called when the desktop is resized by the server. Anyway the problem was that when this
callback is called, the activation sequence is not always completed, which were leading to
some freeze with 2012r2 servers (sending packets before the sequence is finished).
So with the faulty commit, we are tracking server resizes by subscribing to the Actived
event, that is called at the end of a reactivation sequence, so we're sure to not send packets
when not fully activated.
Anyway the issue that shows on (#4330) is that when you use egfx, no reactivation sequence happens,
the server only sends a ResetGraphics message with the new size, and so we miss the resized event.
This fix introduces a new GraphicsReset event, makes the display channel subscribe to that event,
and react accordingly.
2017-12-23 15:50:54 +03:00
|
|
|
xfDisp->waitingResize = FALSE;
|
|
|
|
|
|
|
|
if (xfDisp->activated && !settings->Fullscreen)
|
|
|
|
{
|
|
|
|
xf_disp_set_window_resizable(xfDisp);
|
2018-07-18 10:31:04 +03:00
|
|
|
xf_disp_sendResize(xfDisp);
|
Fix for #4330
Since ec027bf dynamic resolution is broken when used with egfx. Before that commit
we were tracking a server sent resize by setting a DesktopResize callback. This callback
is called when the desktop is resized by the server. Anyway the problem was that when this
callback is called, the activation sequence is not always completed, which were leading to
some freeze with 2012r2 servers (sending packets before the sequence is finished).
So with the faulty commit, we are tracking server resizes by subscribing to the Actived
event, that is called at the end of a reactivation sequence, so we're sure to not send packets
when not fully activated.
Anyway the issue that shows on (#4330) is that when you use egfx, no reactivation sequence happens,
the server only sends a ResetGraphics message with the new size, and so we miss the resized event.
This fix introduces a new GraphicsReset event, makes the display channel subscribe to that event,
and react accordingly.
2017-12-23 15:50:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-14 12:14:33 +03:00
|
|
|
static void xf_disp_OnTimer(void* context, TimerEventArgs* e)
|
2017-12-19 17:16:14 +03:00
|
|
|
{
|
2018-10-02 13:33:52 +03:00
|
|
|
xfContext* xfc;
|
|
|
|
xfDispContext* xfDisp;
|
|
|
|
rdpSettings* settings;
|
|
|
|
|
2019-02-07 19:53:21 +03:00
|
|
|
WINPR_UNUSED(e);
|
|
|
|
|
2018-10-02 13:33:52 +03:00
|
|
|
if (!xf_disp_check_context(context, &xfc, &xfDisp, &settings))
|
|
|
|
return;
|
2017-12-19 17:16:14 +03:00
|
|
|
|
|
|
|
if (!xfDisp->activated || settings->Fullscreen)
|
|
|
|
return;
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
xf_disp_sendResize(xfDisp);
|
2017-12-19 17:16:14 +03:00
|
|
|
}
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
xfDispContext* xf_disp_new(xfContext* xfc)
|
2017-11-29 12:26:04 +03:00
|
|
|
{
|
2018-10-02 13:33:52 +03:00
|
|
|
xfDispContext* ret;
|
|
|
|
|
|
|
|
if (!xfc || !xfc->context.settings || !xfc->context.pubSub)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret = calloc(1, sizeof(xfDispContext));
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret->xfc = xfc;
|
2017-12-19 17:16:14 +03:00
|
|
|
#ifdef USABLE_XRANDR
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
if (XRRQueryExtension(xfc->display, &ret->eventBase, &ret->errorBase))
|
|
|
|
{
|
|
|
|
ret->haveXRandr = TRUE;
|
|
|
|
}
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
#endif
|
2017-12-19 17:16:14 +03:00
|
|
|
ret->lastSentWidth = ret->targetWidth = xfc->context.settings->DesktopWidth;
|
|
|
|
ret->lastSentHeight = ret->targetHeight = xfc->context.settings->DesktopHeight;
|
2018-02-14 12:14:33 +03:00
|
|
|
PubSub_SubscribeActivated(xfc->context.pubSub, xf_disp_OnActivated);
|
|
|
|
PubSub_SubscribeGraphicsReset(xfc->context.pubSub, xf_disp_OnGraphicsReset);
|
|
|
|
PubSub_SubscribeTimer(xfc->context.pubSub, xf_disp_OnTimer);
|
2017-11-29 12:26:04 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
void xf_disp_free(xfDispContext* disp)
|
2017-11-29 12:26:04 +03:00
|
|
|
{
|
2018-10-02 13:33:52 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
free(disp);
|
|
|
|
}
|
|
|
|
|
2018-10-02 13:33:52 +03:00
|
|
|
UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, int nmonitors)
|
2017-11-29 12:26:04 +03:00
|
|
|
{
|
|
|
|
UINT ret = CHANNEL_RC_OK;
|
2018-07-18 10:31:04 +03:00
|
|
|
DISPLAY_CONTROL_MONITOR_LAYOUT* layouts;
|
2017-11-29 12:26:04 +03:00
|
|
|
int i;
|
2018-07-18 10:31:04 +03:00
|
|
|
xfDispContext* xfDisp = (xfDispContext*)disp->custom;
|
|
|
|
rdpSettings* settings = xfDisp->xfc->context.settings;
|
2017-11-29 12:26:04 +03:00
|
|
|
layouts = calloc(nmonitors, sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT));
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
if (!layouts)
|
|
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
|
|
|
|
|
|
for (i = 0; i < nmonitors; i++)
|
|
|
|
{
|
|
|
|
layouts[i].Flags = (monitors[i].is_primary ? DISPLAY_CONTROL_MONITOR_PRIMARY : 0);
|
|
|
|
layouts[i].Left = monitors[i].x;
|
|
|
|
layouts[i].Top = monitors[i].y;
|
|
|
|
layouts[i].Width = monitors[i].width;
|
|
|
|
layouts[i].Height = monitors[i].height;
|
|
|
|
layouts[i].Orientation = ORIENTATION_LANDSCAPE;
|
2017-12-23 12:27:38 +03:00
|
|
|
layouts[i].PhysicalWidth = monitors[i].attributes.physicalWidth;
|
|
|
|
layouts[i].PhysicalHeight = monitors[i].attributes.physicalHeight;
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
switch (monitors[i].attributes.orientation)
|
2017-12-23 12:27:38 +03:00
|
|
|
{
|
2018-07-18 10:31:04 +03:00
|
|
|
case 90:
|
|
|
|
layouts[i].Orientation = ORIENTATION_PORTRAIT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 180:
|
|
|
|
layouts[i].Orientation = ORIENTATION_LANDSCAPE_FLIPPED;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 270:
|
|
|
|
layouts[i].Orientation = ORIENTATION_PORTRAIT_FLIPPED;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
default:
|
|
|
|
/* MS-RDPEDISP - 2.2.2.2.1:
|
|
|
|
* Orientation (4 bytes): A 32-bit unsigned integer that specifies the
|
|
|
|
* orientation of the monitor in degrees. Valid values are 0, 90, 180
|
|
|
|
* or 270
|
|
|
|
*
|
|
|
|
* So we default to ORIENTATION_LANDSCAPE
|
|
|
|
*/
|
|
|
|
layouts[i].Orientation = ORIENTATION_LANDSCAPE;
|
|
|
|
break;
|
2017-12-23 12:27:38 +03:00
|
|
|
}
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-12-23 12:27:38 +03:00
|
|
|
layouts[i].DesktopScaleFactor = settings->DesktopScaleFactor;
|
|
|
|
layouts[i].DeviceScaleFactor = settings->DeviceScaleFactor;
|
2017-11-29 12:26:04 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 17:24:32 +03:00
|
|
|
ret = IFCALLRESULT(CHANNEL_RC_OK, disp->SendMonitorLayout, disp, nmonitors, layouts);
|
2017-11-29 12:26:04 +03:00
|
|
|
free(layouts);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
BOOL xf_disp_handle_xevent(xfContext* xfc, XEvent* event)
|
2017-11-29 12:26:04 +03:00
|
|
|
{
|
2018-09-24 17:24:32 +03:00
|
|
|
xfDispContext* xfDisp;
|
|
|
|
rdpSettings* settings;
|
2017-11-29 12:26:04 +03:00
|
|
|
UINT32 maxWidth, maxHeight;
|
|
|
|
|
2018-09-24 17:24:32 +03:00
|
|
|
if (!xfc || !event)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
xfDisp = xfc->xfDisp;
|
|
|
|
|
|
|
|
if (!xfDisp)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
settings = xfc->context.settings;
|
|
|
|
|
|
|
|
if (!settings)
|
|
|
|
return FALSE;
|
|
|
|
|
2018-09-24 17:44:25 +03:00
|
|
|
if (!xfDisp->haveXRandr || !xfDisp->disp)
|
2017-11-29 12:26:04 +03:00
|
|
|
return TRUE;
|
|
|
|
|
2017-12-19 17:16:14 +03:00
|
|
|
#ifdef USABLE_XRANDR
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
if (event->type != xfDisp->eventBase + RRScreenChangeNotify)
|
|
|
|
return TRUE;
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
#endif
|
2017-11-29 12:26:04 +03:00
|
|
|
xf_detect_monitors(xfc, &maxWidth, &maxHeight);
|
2018-09-24 17:44:25 +03:00
|
|
|
return xf_disp_sendLayout(xfDisp->disp, settings->MonitorDefArray,
|
2018-07-18 10:31:04 +03:00
|
|
|
settings->MonitorCount) == CHANNEL_RC_OK;
|
2017-11-29 12:26:04 +03:00
|
|
|
}
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
BOOL xf_disp_handle_configureNotify(xfContext* xfc, int width, int height)
|
2017-11-29 12:26:04 +03:00
|
|
|
{
|
2018-09-24 17:24:32 +03:00
|
|
|
xfDispContext* xfDisp;
|
|
|
|
|
2018-09-24 17:44:25 +03:00
|
|
|
if (!xfc)
|
2018-09-24 17:24:32 +03:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
xfDisp = xfc->xfDisp;
|
2018-10-02 13:33:52 +03:00
|
|
|
|
|
|
|
if (!xfDisp)
|
|
|
|
return FALSE;
|
|
|
|
|
2018-07-18 10:31:04 +03:00
|
|
|
xfDisp->targetWidth = width;
|
|
|
|
xfDisp->targetHeight = height;
|
|
|
|
return xf_disp_sendResize(xfDisp);
|
2017-11-29 12:26:04 +03:00
|
|
|
}
|
|
|
|
|
2018-10-02 13:33:52 +03:00
|
|
|
static UINT xf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors,
|
|
|
|
UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB)
|
2017-11-29 12:26:04 +03:00
|
|
|
{
|
|
|
|
/* we're called only if dynamic resolution update is activated */
|
2018-07-18 10:31:04 +03:00
|
|
|
xfDispContext* xfDisp = (xfDispContext*)disp->custom;
|
|
|
|
rdpSettings* settings = xfDisp->xfc->context.settings;
|
|
|
|
WLog_DBG(TAG,
|
|
|
|
"DisplayControlCapsPdu: MaxNumMonitors: %"PRIu32" MaxMonitorAreaFactorA: %"PRIu32" MaxMonitorAreaFactorB: %"PRIu32"",
|
|
|
|
maxNumMonitors, maxMonitorAreaFactorA, maxMonitorAreaFactorB);
|
2017-11-29 12:26:04 +03:00
|
|
|
xfDisp->activated = TRUE;
|
|
|
|
|
|
|
|
if (settings->Fullscreen)
|
|
|
|
return CHANNEL_RC_OK;
|
|
|
|
|
2018-11-22 14:06:30 +03:00
|
|
|
WLog_DBG(TAG, "DisplayControlCapsPdu: setting the window as resizable");
|
2017-11-29 12:26:04 +03:00
|
|
|
return xf_disp_set_window_resizable(xfDisp) ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
2018-09-24 17:44:25 +03:00
|
|
|
BOOL xf_disp_init(xfDispContext* xfDisp, DispClientContext* disp)
|
2017-11-29 12:26:04 +03:00
|
|
|
{
|
2018-09-24 17:44:25 +03:00
|
|
|
rdpSettings* settings;
|
|
|
|
|
|
|
|
if (!xfDisp || !xfDisp->xfc || !disp)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
settings = xfDisp->xfc->context.settings;
|
2018-10-02 13:33:52 +03:00
|
|
|
|
|
|
|
if (!settings)
|
|
|
|
return FALSE;
|
|
|
|
|
2018-09-24 17:44:25 +03:00
|
|
|
xfDisp->disp = disp;
|
|
|
|
disp->custom = (void*) xfDisp;
|
2017-11-29 12:26:04 +03:00
|
|
|
|
|
|
|
if (settings->DynamicResolutionUpdate)
|
|
|
|
{
|
|
|
|
disp->DisplayControlCaps = xf_DisplayControlCaps;
|
2017-12-19 17:16:14 +03:00
|
|
|
#ifdef USABLE_XRANDR
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
if (settings->Fullscreen)
|
|
|
|
{
|
|
|
|
/* ask X11 to notify us of screen changes */
|
2018-09-24 17:44:25 +03:00
|
|
|
XRRSelectInput(xfDisp->xfc->display, DefaultRootWindow(xfDisp->xfc->display),
|
|
|
|
RRScreenChangeNotifyMask);
|
2017-11-29 12:26:04 +03:00
|
|
|
}
|
2018-07-18 10:31:04 +03:00
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-09-24 17:44:25 +03:00
|
|
|
BOOL xf_disp_uninit(xfDispContext* xfDisp, DispClientContext* disp)
|
|
|
|
{
|
|
|
|
if (!xfDisp || !disp)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
xfDisp->disp = NULL;
|
2018-10-03 16:16:59 +03:00
|
|
|
return TRUE;
|
2018-09-24 17:44:25 +03:00
|
|
|
}
|