Remove override redirect flag for fullscreen with keyboard grab enabled. Window manager should always know about the main window.

Small cleanup of passing around decorations flag.
Limit PercentScreen to single monitor vs. entire desktop. IMO - this is better behavior in a multimonitor environment.

Handle fullscreen windows better:
1. Ensure that size hints are set to allow resizing before setting a window to fullscreen as some window managers do not behave properly.
2. Handle fullscreen toggles without destroying and recreating window.
3. Use NET_WM_STATE_FULLSCREEN Extended Window Manager Hint for fullscreen functionality
4. Use the NET_WM_FULLSCREEN_MONITORS Extended Window Manager Hint when appropriate
5. When a single monitor fullscreen is requested - use the current monitor(as determined from mouse location)
6. Handle cases where there is no local monitor at coordinate 0,0. The Windows server expect there to be a monitor at this location, so we maintain offset if necessary between our local primary monitor and the server side primary monitor located at 0,0.
This commit is contained in:
bjcollins 2015-02-23 11:22:28 -06:00
parent 1fd5508afd
commit d4a9a2d3a8
7 changed files with 252 additions and 75 deletions

View File

@ -516,7 +516,7 @@ BOOL xf_create_window(xfContext* xfc)
xfc->attribs.background_pixel = BlackPixelOfScreen(xfc->screen);
xfc->attribs.border_pixel = WhitePixelOfScreen(xfc->screen);
xfc->attribs.backing_store = xfc->primary ? NotUseful : Always;
xfc->attribs.override_redirect = xfc->grab_keyboard ? xfc->fullscreen : False;
xfc->attribs.override_redirect = False;
xfc->attribs.colormap = xfc->colormap;
xfc->attribs.bit_gravity = NorthWestGravity;
xfc->attribs.win_gravity = NorthWestGravity;
@ -571,7 +571,7 @@ BOOL xf_create_window(xfContext* xfc)
}
#endif
xfc->window = xf_CreateDesktopWindow(xfc, windowTitle, width, height, xfc->decorations);
xfc->window = xf_CreateDesktopWindow(xfc, windowTitle, width, height);
free(windowTitle);
@ -579,6 +579,10 @@ BOOL xf_create_window(xfContext* xfc)
xf_SetWindowFullscreen(xfc, xfc->window, xfc->fullscreen);
xfc->unobscured = (xevent.xvisibility.state == VisibilityUnobscured);
/* Disallow resize now that any initial fullscreen window operation is complete */
xf_SetWindowSizeHints(xfc, xfc->window, FALSE, xfc->width, xfc->height);
XSetWMProtocols(xfc->display, xfc->window->handle, &(xfc->WM_DELETE_WINDOW), 1);
xfc->drawable = xfc->window->handle;
}
@ -686,16 +690,12 @@ void xf_toggle_fullscreen(xfContext* xfc)
rdpContext* context = (rdpContext*) xfc;
rdpSettings* settings = context->settings;
xf_lock_x11(xfc, TRUE);
xf_window_free(xfc);
xfc->fullscreen = (xfc->fullscreen) ? FALSE : TRUE;
xfc->decorations = (xfc->fullscreen) ? FALSE : settings->Decorations;
xf_create_window(xfc);
xf_unlock_x11(xfc, TRUE);
xf_SetWindowSizeHints(xfc, xfc->window, TRUE, xfc->width, xfc->height);
xf_SetWindowFullscreen(xfc, xfc->window, xfc->fullscreen);
xf_SetWindowSizeHints(xfc, xfc->window, FALSE, xfc->width, xfc->height);
EventArgsInit(&e, "xfreerdp");
e.state = xfc->fullscreen ? FREERDP_WINDOW_STATE_FULLSCREEN : 0;
@ -1697,6 +1697,7 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
xfc->_NET_WORKAREA = XInternAtom(xfc->display, "_NET_WORKAREA", False);
xfc->_NET_WM_STATE = XInternAtom(xfc->display, "_NET_WM_STATE", False);
xfc->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfc->display, "_NET_WM_STATE_FULLSCREEN", False);
xfc->_NET_WM_FULLSCREEN_MONITORS = XInternAtom(xfc->display, "_NET_WM_FULLSCREEN_MONITORS", False);
xfc->_NET_WM_WINDOW_TYPE = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE", False);
xfc->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
xfc->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE_DIALOG", False);

View File

@ -118,13 +118,17 @@ BOOL xf_is_monitor_id_active(xfContext* xfc, UINT32 id)
BOOL xf_detect_monitors(xfContext* xfc)
{
int i;
int nmonitors;
int primaryMonitor;
int vWidth, vHeight;
int nmonitors = 0;
int primaryMonitorFound = FALSE;
int vX, vY, vWidth, vHeight;
int maxWidth, maxHeight;
VIRTUAL_SCREEN* vscreen;
rdpSettings* settings = xfc->settings;
int mouse_x, mouse_y, _dummy_i;
Window _dummy_w;
int current_monitor = 0;
#ifdef WITH_XINERAMA
int major, minor;
XineramaScreenInfo* screenInfo = NULL;
@ -134,6 +138,12 @@ BOOL xf_detect_monitors(xfContext* xfc)
xfc->desktopWidth = settings->DesktopWidth;
xfc->desktopHeight = settings->DesktopHeight;
/* get mouse location */
if (!XQueryPointer(xfc->display, DefaultRootWindow(xfc->display),
&_dummy_w, &_dummy_w, &mouse_x, &mouse_y,
&_dummy_i, &_dummy_i, (void *) &_dummy_i))
mouse_x = mouse_y = 0;
#ifdef WITH_XINERAMA
if (XineramaQueryExtension(xfc->display, &major, &minor))
{
@ -153,8 +163,12 @@ BOOL xf_detect_monitors(xfContext* xfc)
vscreen->monitors[i].area.right = screenInfo[i].x_org + screenInfo[i].width - 1;
vscreen->monitors[i].area.bottom = screenInfo[i].y_org + screenInfo[i].height - 1;
if ((screenInfo[i].x_org == 0) && (screenInfo[i].y_org == 0))
vscreen->monitors[i].primary = TRUE;
/* Determine which monitor that the mouse cursor is on */
if ((mouse_x >= vscreen->monitors[i].area.left) &&
(mouse_x <= vscreen->monitors[i].area.right) &&
(mouse_y >= vscreen->monitors[i].area.top) &&
(mouse_y <= vscreen->monitors[i].area.bottom))
current_monitor = i;
}
}
@ -163,6 +177,9 @@ BOOL xf_detect_monitors(xfContext* xfc)
}
#endif
xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom =
xfc->fullscreenMonitors.left = xfc->fullscreenMonitors.right = 0;
/* WORKAROUND: With Remote Application Mode - using NET_WM_WORKAREA
* causes issues with the ability to fully size the window vertically
* (the bottom of the window area is never updated). So, we just set
@ -194,6 +211,16 @@ BOOL xf_detect_monitors(xfContext* xfc)
{
xfc->desktopWidth = (xfc->workArea.width * settings->PercentScreen) / 100;
xfc->desktopHeight = (xfc->workArea.height * settings->PercentScreen) / 100;
/* If we have specific monitor information then limit the PercentScreen value
* to only affect the current monitor vs. the entire desktop
*/
if (vscreen->nmonitors > 0)
{
settings->DesktopWidth = ((vscreen->monitors[current_monitor].area.right - vscreen->monitors[current_monitor].area.left + 1) * settings->PercentScreen) / 100;
settings->DesktopHeight = ((vscreen->monitors[current_monitor].area.bottom - vscreen->monitors[current_monitor].area.top + 1) * settings->PercentScreen) / 100;
}
maxWidth = xfc->desktopWidth;
maxHeight = xfc->desktopHeight;
}
@ -206,30 +233,24 @@ BOOL xf_detect_monitors(xfContext* xfc)
if (!settings->Fullscreen && !settings->Workarea && !settings->UseMultimon)
return TRUE;
/* If single monitor fullscreen OR workarea without remote app */
if ((settings->Fullscreen && !settings->UseMultimon && !settings->SpanMonitors) ||
(settings->Workarea && !settings->RemoteApplicationMode))
{
/* Select a single monitor */
if (settings->NumMonitorIds != 1)
/* If no monitors were specified on the command-line then set the current monitor as active */
if (!settings->NumMonitorIds)
{
settings->NumMonitorIds = 1;
settings->MonitorIds[0] = 0;
for (i = 0; i < vscreen->nmonitors; i++)
{
if (vscreen->monitors[i].primary)
{
settings->MonitorIds[0] = i;
break;
}
}
settings->MonitorIds[0] = current_monitor;
}
/* Always sets number of monitors from command-line to just 1.
* If the monitor is invalid then we will default back to current monitor
* later as a fallback. So, there is no need to validate command-line entry here.
*/
settings->NumMonitorIds = 1;
}
nmonitors = 0;
primaryMonitor = 0;
/* Create array of all active monitors by taking into account monitors requested on the command-line */
for (i = 0; i < vscreen->nmonitors; i++)
{
if (!xf_is_monitor_id_active(xfc, i))
@ -239,43 +260,114 @@ BOOL xf_detect_monitors(xfContext* xfc)
settings->MonitorDefArray[nmonitors].y = vscreen->monitors[i].area.top;
settings->MonitorDefArray[nmonitors].width = MIN(vscreen->monitors[i].area.right - vscreen->monitors[i].area.left + 1, xfc->desktopWidth);
settings->MonitorDefArray[nmonitors].height = MIN(vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1, xfc->desktopHeight);
settings->MonitorDefArray[nmonitors].is_primary = vscreen->monitors[i].primary;
settings->MonitorDefArray[nmonitors].orig_screen = i;
primaryMonitor |= vscreen->monitors[i].primary;
nmonitors++;
}
/* If no monitor is active(bogus command-line monitor specification) - then lets try to fallback to go fullscreen on the current monitor only */
if (nmonitors == 0 && vscreen->nmonitors > 0)
{
settings->MonitorDefArray[0].x = vscreen->monitors[current_monitor].area.left;
settings->MonitorDefArray[0].y = vscreen->monitors[current_monitor].area.top;
settings->MonitorDefArray[0].width = MIN(vscreen->monitors[current_monitor].area.right - vscreen->monitors[current_monitor].area.left + 1, xfc->desktopWidth);
settings->MonitorDefArray[0].height = MIN(vscreen->monitors[current_monitor].area.bottom - vscreen->monitors[current_monitor].area.top + 1, xfc->desktopHeight);
settings->MonitorDefArray[0].orig_screen = current_monitor;
nmonitors = 1;
}
settings->MonitorCount = nmonitors;
vWidth = vHeight = 0;
settings->DesktopPosX = maxWidth - 1;
settings->DesktopPosY = maxHeight - 1;
for (i = 0; i < settings->MonitorCount; i++)
{
settings->DesktopPosX = MIN(settings->DesktopPosX, settings->MonitorDefArray[i].x);
settings->DesktopPosY = MIN(settings->DesktopPosY, settings->MonitorDefArray[i].y);
vWidth += settings->MonitorDefArray[i].width;
vHeight = MAX(vHeight, settings->MonitorDefArray[i].height);
}
vscreen->area.left = 0;
vscreen->area.right = vWidth - 1;
vscreen->area.top = 0;
vscreen->area.bottom = vHeight - 1;
if (settings->Workarea)
{
vscreen->area.top = xfc->workArea.y;
vscreen->area.bottom = (vHeight - (vHeight - (xfc->workArea.height + xfc->workArea.y))) - 1;
}
if (nmonitors && !primaryMonitor)
settings->MonitorDefArray[0].is_primary = TRUE;
/* If we have specific monitor information */
if (settings->MonitorCount)
{
/* Initialize bounding rectangle for all monitors */
vWidth = settings->MonitorDefArray[0].width;
vHeight = settings->MonitorDefArray[0].height;
vX = settings->MonitorDefArray[0].x;
vY = settings->MonitorDefArray[0].y;
xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom =
xfc->fullscreenMonitors.left = xfc->fullscreenMonitors.right = settings->MonitorDefArray[0].orig_screen;
/* Calculate bounding rectangle around all monitors to be used AND
* also set the Xinerama indices which define left/top/right/bottom monitors.
*/
for (i = 1; i < settings->MonitorCount; i++)
{
/* does the same as gdk_rectangle_union */
int destX = MIN(vX, settings->MonitorDefArray[i].x);
int destY = MIN(vY, settings->MonitorDefArray[i].y);
int destWidth = MAX(vX + vWidth, settings->MonitorDefArray[i].x + settings->MonitorDefArray[i].width) - destX;
int destHeight = MAX(vY + vHeight, settings->MonitorDefArray[i].y + settings->MonitorDefArray[i].height) - destY;
if (vX != destX)
xfc->fullscreenMonitors.left = settings->MonitorDefArray[i].orig_screen;
if (vY != destY)
xfc->fullscreenMonitors.top = settings->MonitorDefArray[i].orig_screen;
if (vWidth != destWidth)
xfc->fullscreenMonitors.right = settings->MonitorDefArray[i].orig_screen;
if (vHeight != destHeight)
xfc->fullscreenMonitors.bottom = settings->MonitorDefArray[i].orig_screen;
vX = destX;
vY = destY;
vWidth = destWidth;
vHeight = destHeight;
}
settings->DesktopPosX = vX;
settings->DesktopPosY = vY;
vscreen->area.left = 0;
vscreen->area.right = vWidth - 1;
vscreen->area.top = 0;
vscreen->area.bottom = vHeight - 1;
if (settings->Workarea)
{
vscreen->area.top = xfc->workArea.y;
vscreen->area.bottom = (vHeight - (vHeight - (xfc->workArea.height + xfc->workArea.y))) - 1;
}
/* If there are multiple monitors and we have not selected a primary */
if (!primaryMonitorFound)
{
/* First lets try to see if there is a monitor with a 0,0 coordinate */
for (i=0; i<settings->MonitorCount; i++)
{
if (!primaryMonitorFound && settings->MonitorDefArray[i].x == 0 && settings->MonitorDefArray[i].y == 0)
{
settings->MonitorDefArray[i].is_primary = TRUE;
settings->MonitorLocalShiftX = settings->MonitorDefArray[i].x;
settings->MonitorLocalShiftY = settings->MonitorDefArray[i].y;
primaryMonitorFound = TRUE;
}
}
/* If we still do not have a primary monitor then just arbitrarily choose first monitor */
if (!primaryMonitorFound)
{
settings->MonitorDefArray[0].is_primary = TRUE;
settings->MonitorLocalShiftX = settings->MonitorDefArray[0].x;
settings->MonitorLocalShiftY = settings->MonitorDefArray[0].y;
primaryMonitorFound = TRUE;
}
}
/* Subtract monitor shift from monitor variables for server-side use.
* We maintain monitor shift value as Window requires the primary monitor to have a coordinate of 0,0
* In some X configurations, no monitor may have a coordinate of 0,0. This can also be happen if the user
* requests specific monitors from the command-line as well. So, we make sure to translate our primary monitor's
* upper-left corner to 0,0 on the server.
*/
for (i=0; i < settings->MonitorCount; i++)
{
settings->MonitorDefArray[i].x = settings->MonitorDefArray[i].x - settings->MonitorLocalShiftX;
settings->MonitorDefArray[i].y = settings->MonitorDefArray[i].y - settings->MonitorLocalShiftY;
}
/* Set the desktop width and height according to the bounding rectangle around the active monitors */
xfc->desktopWidth = vscreen->area.right - vscreen->area.left + 1;
xfc->desktopHeight = vscreen->area.bottom - vscreen->area.top + 1;
}

View File

@ -139,19 +139,57 @@ void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom, unsigned int n
void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
{
if (fullscreen)
int i;
int startX = xfc->instance->settings->DesktopPosX;
int startY = xfc->instance->settings->DesktopPosY;
window->decorations = xfc->decorations;
xf_SetWindowDecorations(xfc, window->handle, window->decorations);
/* Determine the x,y starting location for the fullscreen window */
if (xfc->instance->settings->MonitorCount)
{
rdpSettings* settings = xfc->settings;
/* Initialize startX and startY with reasonable values */
startX = xfc->instance->settings->MonitorDefArray[0].x;
startY = xfc->instance->settings->MonitorDefArray[0].y;
xf_SetWindowDecorations(xfc, window->handle, FALSE);
/* Search all monitors to find the lowest startX and startY values */
for (i=0; i < xfc->instance->settings->MonitorCount; i++)
{
startX = MIN(startX, xfc->instance->settings->MonitorDefArray[i].x);
startY = MIN(startY, xfc->instance->settings->MonitorDefArray[i].y);
}
XMoveResizeWindow(xfc->display, window->handle,
settings->DesktopPosX, settings->DesktopPosY, window->width, window->height);
XMapRaised(xfc->display, window->handle);
window->fullscreen = TRUE;
/* Lastly apply any monitor shift(translation from remote to local coordinate system)
* to startX and startY values
*/
startX = startX + xfc->instance->settings->MonitorLocalShiftX;
startY = startY + xfc->instance->settings->MonitorLocalShiftY;
}
XMoveResizeWindow(xfc->display, window->handle, startX, startY, window->width, window->height);
XMapRaised(xfc->display, window->handle);
/* Set the fullscreen state */
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4,
fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE,
xfc->_NET_WM_STATE_FULLSCREEN, 0, 0);
/* Only send monitor bounds if they are valid */
if ((xfc->fullscreenMonitors.top >= 0) &&
(xfc->fullscreenMonitors.bottom >= 0) &&
(xfc->fullscreenMonitors.left >= 0) &&
(xfc->fullscreenMonitors.right >= 0))
{
xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_FULLSCREEN_MONITORS, 5,
xfc->fullscreenMonitors.top,
xfc->fullscreenMonitors.bottom,
xfc->fullscreenMonitors.left,
xfc->fullscreenMonitors.right,
1);
}
window->fullscreen = TRUE;
}
/* http://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html */
@ -283,7 +321,7 @@ static const char* get_shm_id()
return shm_id;
}
xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height, BOOL decorations)
xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height)
{
XEvent xevent;
int input_mask;
@ -303,7 +341,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
window->width = width;
window->height = height;
window->fullscreen = FALSE;
window->decorations = decorations;
window->decorations = xfc->decorations;
window->is_mapped = FALSE;
window->is_transient = FALSE;
@ -354,9 +392,15 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
}
xf_ResizeDesktopWindow(xfc, window, width, height);
xf_SetWindowDecorations(xfc, window->handle, decorations);
xf_SetWindowDecorations(xfc, window->handle, window->decorations);
xf_SetWindowPID(xfc, window->handle, 0);
/* Set the window hints to allow minimal resize, so fullscreen
* changes can work in window managers that might disallow otherwise.
* We will set back afterwards.
*/
xf_SetWindowSizeHints(xfc, window, TRUE, xfc->width, xfc->height);
input_mask =
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
@ -406,14 +450,20 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
}
void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height)
{
xf_SetWindowSizeHints(xfc, window, FALSE, width, height);
}
void xf_SetWindowSizeHints(xfContext* xfc, xfWindow *window, BOOL can_resize, int width, int height)
{
XSizeHints* size_hints;
size_hints = XAllocSizeHints();
if (size_hints)
{
size_hints->flags = PMinSize | PMaxSize;
size_hints->flags = PMinSize | PMaxSize | PWinGravity;
size_hints->win_gravity = NorthWestGravity;
size_hints->min_width = size_hints->max_width = width;
size_hints->min_height = size_hints->max_height = height;
@ -425,6 +475,17 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int hei
}
#endif
/* Allows the window to resize larger by 1 pixel - so we can
* fullscreen the window with no worries about window manager disallowing based
* on size parameters
*/
if (can_resize)
{
size_hints->width_inc = size_hints->height_inc = 1;
size_hints->max_width = xfc->width + 1;
size_hints->max_height = xfc->height + 1;
}
XSetWMNormalHints(xfc->display, window->handle, size_hints);
XResizeWindow(xfc->display, window->handle, width, height);
XFree(size_hints);

View File

@ -46,6 +46,10 @@ typedef struct xf_window xfWindow;
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
#define _NET_WM_STATE_ADD 1 /* add/set property */
#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
enum xf_localmove_state
{
LMS_NOT_ACTIVE,
@ -143,8 +147,9 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen);
void xf_SetWindowDecorations(xfContext* xfc, Window window, BOOL show);
void xf_SetWindowUnlisted(xfContext* xfc, Window window);
xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height, BOOL decorations);
xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height);
void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height);
void xf_SetWindowSizeHints(xfContext* xfc, xfWindow* window, BOOL can_resize, int width, int height);
void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window);
BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int length,

View File

@ -38,6 +38,15 @@ typedef struct xf_context xfContext;
#include <freerdp/codec/progressive.h>
#include <freerdp/codec/region.h>
struct xf_FullscreenMonitors
{
UINT32 top;
UINT32 bottom;
UINT32 left;
UINT32 right;
};
typedef struct xf_FullscreenMonitors xfFullscreenMonitors;
struct xf_WorkArea
{
UINT32 x;
@ -111,6 +120,7 @@ struct xf_context
xfAppWindow* appWindow;
xfPointer* pointer;
xfWorkArea workArea;
xfFullscreenMonitors fullscreenMonitors;
int current_desktop;
BOOL remote_app;
BOOL disconnect;
@ -181,6 +191,8 @@ struct xf_context
Atom _NET_WM_STATE_SKIP_TASKBAR;
Atom _NET_WM_STATE_SKIP_PAGER;
Atom _NET_WM_FULLSCREEN_MONITORS;
Atom _NET_WM_WINDOW_TYPE;
Atom _NET_WM_WINDOW_TYPE_NORMAL;
Atom _NET_WM_WINDOW_TYPE_DIALOG;

View File

@ -399,6 +399,7 @@ struct rdp_monitor
INT32 width;
INT32 height;
UINT32 is_primary;
UINT32 orig_screen;
};
typedef struct rdp_monitor rdpMonitor;
@ -897,7 +898,10 @@ struct rdp_settings
ALIGN64 BOOL ListMonitors; /* 392 */
ALIGN64 UINT32* MonitorIds; /* 393 */
ALIGN64 UINT32 NumMonitorIds; /* 394 */
UINT64 padding0448[448 - 395]; /* 395 */
ALIGN64 UINT32 MonitorLocalShiftX; /*395 */
ALIGN64 UINT32 MonitorLocalShiftY; /* 396 */
UINT64 padding0448[448 - 397]; /* 397 */
/* Client Message Channel Data */
UINT64 padding0512[512 - 448]; /* 448 */

View File

@ -273,6 +273,8 @@ rdpSettings* freerdp_settings_new(DWORD flags)
settings->MonitorCount = 0;
settings->MonitorDefArraySize = 32;
settings->MonitorDefArray = (rdpMonitor*) calloc(settings->MonitorDefArraySize, sizeof(rdpMonitor));
settings->MonitorLocalShiftX = 0;
settings->MonitorLocalShiftY = 0;
settings->MonitorIds = (UINT32*) calloc(16, sizeof(UINT32));