Blame client/X11/xf_monitor.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * X11 Monitor Handling
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 * Copyright 2017 David Fort <contact@hardening-consulting.com>
Packit Service fa4841
 * Copyright 2018 Kai Harms <kharms@rangee.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <stdio.h>
Packit Service fa4841
#include <stdlib.h>
Packit Service fa4841
#include <string.h>
Packit Service fa4841
#include <X11/Xlib.h>
Packit Service fa4841
#include <X11/Xutil.h>
Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
Packit Service fa4841
#include <freerdp/log.h>
Packit Service fa4841
Packit Service fa4841
#define TAG CLIENT_TAG("x11")
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_XINERAMA
Packit Service fa4841
#include <X11/extensions/Xinerama.h>
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_XRANDR
Packit Service fa4841
#include <X11/extensions/Xrandr.h>
Packit Service fa4841
#include <X11/extensions/randr.h>
Packit Service fa4841
Packit Service fa4841
#if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105
Packit Service b1ea74
#define USABLE_XRANDR
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include "xf_monitor.h"
Packit Service fa4841
Packit Service b1ea74
/* See MSDN Section on Multiple Display Monitors: http://msdn.microsoft.com/en-us/library/dd145071
Packit Service b1ea74
 */
Packit Service fa4841
Packit Service fa4841
int xf_list_monitors(xfContext* xfc)
Packit Service fa4841
{
Packit Service fa4841
	Display* display;
Packit Service fa4841
	int major, minor;
Packit Service fa4841
	int i, nmonitors = 0;
Packit Service fa4841
	display = XOpenDisplay(NULL);
Packit Service fa4841
Packit Service fa4841
	if (!display)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "failed to open X display");
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
#if defined(USABLE_XRANDR)
Packit Service fa4841
Packit Service fa4841
	if (XRRQueryExtension(xfc->display, &major, &minor) &&
Packit Service b1ea74
	    (XRRQueryVersion(xfc->display, &major, &minor) == True) && (major * 100 + minor >= 105))
Packit Service fa4841
	{
Packit Service b1ea74
		XRRMonitorInfo* monitors =
Packit Service b1ea74
		    XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, &nmonitors);
Packit Service fa4841
Packit Service fa4841
		for (i = 0; i < nmonitors; i++)
Packit Service fa4841
		{
Packit Service b1ea74
			printf("      %s [%d] %dx%d\t+%d+%d\n", monitors[i].primary ? "*" : " ", i,
Packit Service b1ea74
			       monitors[i].width, monitors[i].height, monitors[i].x, monitors[i].y);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		XRRFreeMonitors(monitors);
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
#endif
Packit Service fa4841
#ifdef WITH_XINERAMA
Packit Service b1ea74
	    if (XineramaQueryExtension(display, &major, &minor))
Packit Service b1ea74
	{
Packit Service b1ea74
		if (XineramaIsActive(display))
Packit Service fa4841
		{
Packit Service b1ea74
			XineramaScreenInfo* screen = XineramaQueryScreens(display, &nmonitors);
Packit Service fa4841
Packit Service b1ea74
			for (i = 0; i < nmonitors; i++)
Packit Service b1ea74
			{
Packit Service b1ea74
				printf("      %s [%d] %hdx%hd\t+%hd+%hd\n", (i == 0) ? "*" : " ", i,
Packit Service b1ea74
				       screen[i].width, screen[i].height, screen[i].x_org, screen[i].y_org);
Packit Service bb5c11
			}
Packit Service b1ea74
Packit Service b1ea74
			XFree(screen);
Packit Service fa4841
		}
Packit Service b1ea74
	}
Packit Service b1ea74
	else
Packit Service fa4841
#else
Packit Service fa4841
	{
Packit Service fa4841
		Screen* screen = ScreenOfDisplay(display, DefaultScreen(display));
Packit Service fa4841
		printf("      * [0] %dx%d\t+0+0\n", WidthOfScreen(screen), HeightOfScreen(screen));
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
#endif
Packit Service b1ea74
		XCloseDisplay(display);
Packit Service fa4841
	return 0;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL xf_is_monitor_id_active(xfContext* xfc, UINT32 id)
Packit Service fa4841
{
Packit Service b1ea74
	UINT32 index;
Packit Service fa4841
	rdpSettings* settings = xfc->context.settings;
Packit Service fa4841
Packit Service fa4841
	if (!settings->NumMonitorIds)
Packit Service fa4841
		return TRUE;
Packit Service fa4841
Packit Service fa4841
	for (index = 0; index < settings->NumMonitorIds; index++)
Packit Service fa4841
	{
Packit Service fa4841
		if (settings->MonitorIds[index] == id)
Packit Service fa4841
			return TRUE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return FALSE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
Packit Service fa4841
{
Packit Service fa4841
	int nmonitors = 0;
Packit Service fa4841
	int monitor_index = 0;
Packit Service fa4841
	BOOL primaryMonitorFound = FALSE;
Packit Service fa4841
	VIRTUAL_SCREEN* vscreen;
Packit Service b1ea74
	rdpSettings* settings;
Packit Service fa4841
	int mouse_x, mouse_y, _dummy_i;
Packit Service fa4841
	Window _dummy_w;
Packit Service fa4841
	int current_monitor = 0;
Packit Service fa4841
	Screen* screen;
Packit Service fa4841
	MONITOR_INFO* monitor;
Packit Service fa4841
#if defined WITH_XINERAMA || defined WITH_XRANDR
Packit Service fa4841
	int major, minor;
Packit Service fa4841
#endif
Packit Service fa4841
#if defined(USABLE_XRANDR)
Packit Service fa4841
	XRRMonitorInfo* rrmonitors = NULL;
Packit Service fa4841
	BOOL useXRandr = FALSE;
Packit Service fa4841
#endif
Packit Service b1ea74
Packit Service b1ea74
	if (!xfc || !pMaxWidth || !pMaxHeight || !xfc->context.settings)
Packit Service b1ea74
		return FALSE;
Packit Service b1ea74
Packit Service b1ea74
	settings = xfc->context.settings;
Packit Service fa4841
	vscreen = &xfc->vscreen;
Packit Service fa4841
	*pMaxWidth = settings->DesktopWidth;
Packit Service fa4841
	*pMaxHeight = settings->DesktopHeight;
Packit Service fa4841
Packit Service fa4841
	/* get mouse location */
Packit Service b1ea74
	if (!XQueryPointer(xfc->display, DefaultRootWindow(xfc->display), &_dummy_w, &_dummy_w,
Packit Service b1ea74
	                   &mouse_x, &mouse_y, &_dummy_i, &_dummy_i, (void*)&_dummy_i))
Packit Service fa4841
		mouse_x = mouse_y = 0;
Packit Service fa4841
Packit Service fa4841
#if defined(USABLE_XRANDR)
Packit Service fa4841
Packit Service fa4841
	if (XRRQueryExtension(xfc->display, &major, &minor) &&
Packit Service b1ea74
	    (XRRQueryVersion(xfc->display, &major, &minor) == True) && (major * 100 + minor >= 105))
Packit Service fa4841
	{
Packit Service b1ea74
		XRRMonitorInfo* rrmonitors =
Packit Service b1ea74
		    XRRGetMonitors(xfc->display, DefaultRootWindow(xfc->display), 1, &vscreen->nmonitors);
Packit Service fa4841
Packit Service fa4841
		if (vscreen->nmonitors > 16)
Packit Service fa4841
			vscreen->nmonitors = 0;
Packit Service fa4841
Packit Service fa4841
		if (vscreen->nmonitors)
Packit Service fa4841
		{
Packit Service b1ea74
			int i;
Packit Service b1ea74
Packit Service fa4841
			for (i = 0; i < vscreen->nmonitors; i++)
Packit Service fa4841
			{
Packit Service fa4841
				vscreen->monitors[i].area.left = rrmonitors[i].x;
Packit Service fa4841
				vscreen->monitors[i].area.top = rrmonitors[i].y;
Packit Service fa4841
				vscreen->monitors[i].area.right = rrmonitors[i].x + rrmonitors[i].width - 1;
Packit Service fa4841
				vscreen->monitors[i].area.bottom = rrmonitors[i].y + rrmonitors[i].height - 1;
Packit Service fa4841
				vscreen->monitors[i].primary = rrmonitors[i].primary > 0;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		XRRFreeMonitors(rrmonitors);
Packit Service fa4841
		useXRandr = TRUE;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
#endif
Packit Service fa4841
#ifdef WITH_XINERAMA
Packit Service b1ea74
	    if (XineramaQueryExtension(xfc->display, &major, &minor) && XineramaIsActive(xfc->display))
Packit Service b1ea74
	{
Packit Service b1ea74
		XineramaScreenInfo* screenInfo = XineramaQueryScreens(xfc->display, &vscreen->nmonitors);
Packit Service b1ea74
Packit Service b1ea74
		if (vscreen->nmonitors > 16)
Packit Service b1ea74
			vscreen->nmonitors = 0;
Packit Service fa4841
Packit Service b1ea74
		if (vscreen->nmonitors)
Packit Service b1ea74
		{
Packit Service b1ea74
			int i;
Packit Service bb5c11
Packit Service b1ea74
			for (i = 0; i < vscreen->nmonitors; i++)
Packit Service fa4841
			{
Packit Service b1ea74
				vscreen->monitors[i].area.left = screenInfo[i].x_org;
Packit Service b1ea74
				vscreen->monitors[i].area.top = screenInfo[i].y_org;
Packit Service b1ea74
				vscreen->monitors[i].area.right = screenInfo[i].x_org + screenInfo[i].width - 1;
Packit Service b1ea74
				vscreen->monitors[i].area.bottom = screenInfo[i].y_org + screenInfo[i].height - 1;
Packit Service fa4841
			}
Packit Service bb5c11
		}
Packit Service fa4841
Packit Service b1ea74
		XFree(screenInfo);
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service fa4841
#endif
Packit Service b1ea74
	xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom = xfc->fullscreenMonitors.left =
Packit Service b1ea74
	    xfc->fullscreenMonitors.right = 0;
Packit Service fa4841
Packit Service fa4841
	/* Determine which monitor that the mouse cursor is on */
Packit Service fa4841
	if (vscreen->monitors)
Packit Service fa4841
	{
Packit Service b1ea74
		int i;
Packit Service b1ea74
Packit Service fa4841
		for (i = 0; i < vscreen->nmonitors; i++)
Packit Service fa4841
		{
Packit Service fa4841
			if ((mouse_x >= vscreen->monitors[i].area.left) &&
Packit Service fa4841
			    (mouse_x <= vscreen->monitors[i].area.right) &&
Packit Service fa4841
			    (mouse_y >= vscreen->monitors[i].area.top) &&
Packit Service fa4841
			    (mouse_y <= vscreen->monitors[i].area.bottom))
Packit Service fa4841
			{
Packit Service fa4841
				current_monitor = i;
Packit Service fa4841
				break;
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/*
Packit Service fa4841
	   Even for a single monitor, we need to calculate the virtual screen to support
Packit Service fa4841
	   window managers that do not implement all X window state hints.
Packit Service fa4841
Packit Service fa4841
	   If the user did not request multiple monitor or is using workarea
Packit Service fa4841
	   without remote app, we force the number of monitors be 1 so later
Packit Service fa4841
	   the rest of the client don't end up using more monitors than the user desires.
Packit Service fa4841
	 */
Packit Service fa4841
	if ((!settings->UseMultimon && !settings->SpanMonitors) ||
Packit Service fa4841
	    (settings->Workarea && !settings->RemoteApplicationMode))
Packit Service fa4841
	{
Packit Service b1ea74
		/* If no monitors were specified on the command-line then set the current monitor as active
Packit Service b1ea74
		 */
Packit Service fa4841
		if (!settings->NumMonitorIds)
Packit Service fa4841
		{
Packit Service fa4841
			settings->MonitorIds[0] = current_monitor;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		/* Always sets number of monitors from command-line to just 1.
Packit Service fa4841
		 * If the monitor is invalid then we will default back to current monitor
Packit Service fa4841
		 * later as a fallback. So, there is no need to validate command-line entry here.
Packit Service fa4841
		 */
Packit Service fa4841
		settings->NumMonitorIds = 1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* WORKAROUND: With Remote Application Mode - using NET_WM_WORKAREA
Packit Service fa4841
	 * causes issues with the ability to fully size the window vertically
Packit Service fa4841
	 * (the bottom of the window area is never updated). So, we just set
Packit Service fa4841
	 * the workArea to match the full Screen width/height.
Packit Service fa4841
	 */
Packit Service fa4841
	if (settings->RemoteApplicationMode || !xf_GetWorkArea(xfc))
Packit Service fa4841
	{
Packit Service fa4841
		/*
Packit Service fa4841
		   if only 1 monitor is enabled, use monitor area
Packit Service fa4841
		   this is required in case of a screen composed of more than one monitor
Packit Service fa4841
		   but user did not enable multimonitor
Packit Service fa4841
		*/
Packit Service b1ea74
		if ((settings->NumMonitorIds == 1) && (vscreen->nmonitors > current_monitor))
Packit Service fa4841
		{
Packit Service fa4841
			monitor = vscreen->monitors + current_monitor;
Packit Service b1ea74
Packit Service b1ea74
			if (!monitor)
Packit Service b1ea74
				return FALSE;
Packit Service b1ea74
Packit Service fa4841
			xfc->workArea.x = monitor->area.left;
Packit Service fa4841
			xfc->workArea.y = monitor->area.top;
Packit Service fa4841
			xfc->workArea.width = monitor->area.right - monitor->area.left + 1;
Packit Service fa4841
			xfc->workArea.height = monitor->area.bottom - monitor->area.top + 1;
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			xfc->workArea.x = 0;
Packit Service fa4841
			xfc->workArea.y = 0;
Packit Service fa4841
			xfc->workArea.width = WidthOfScreen(xfc->screen);
Packit Service fa4841
			xfc->workArea.height = HeightOfScreen(xfc->screen);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (settings->Fullscreen)
Packit Service fa4841
	{
Packit Service fa4841
		*pMaxWidth = WidthOfScreen(xfc->screen);
Packit Service fa4841
		*pMaxHeight = HeightOfScreen(xfc->screen);
Packit Service fa4841
	}
Packit Service fa4841
	else if (settings->Workarea)
Packit Service fa4841
	{
Packit Service fa4841
		*pMaxWidth = xfc->workArea.width;
Packit Service fa4841
		*pMaxHeight = xfc->workArea.height;
Packit Service fa4841
	}
Packit Service fa4841
	else if (settings->PercentScreen)
Packit Service fa4841
	{
Packit Service fa4841
		/* If we have specific monitor information then limit the PercentScreen value
Packit Service fa4841
		 * to only affect the current monitor vs. the entire desktop
Packit Service fa4841
		 */
Packit Service fa4841
		if (vscreen->nmonitors > 0)
Packit Service fa4841
		{
Packit Service b1ea74
			if (!vscreen->monitors)
Packit Service b1ea74
				return FALSE;
Packit Service b1ea74
Packit Service fa4841
			*pMaxWidth = vscreen->monitors[current_monitor].area.right -
Packit Service fa4841
			             vscreen->monitors[current_monitor].area.left + 1;
Packit Service fa4841
			*pMaxHeight = vscreen->monitors[current_monitor].area.bottom -
Packit Service fa4841
			              vscreen->monitors[current_monitor].area.top + 1;
Packit Service fa4841
Packit Service fa4841
			if (settings->PercentScreenUseWidth)
Packit Service fa4841
				*pMaxWidth = ((vscreen->monitors[current_monitor].area.right -
Packit Service b1ea74
				               vscreen->monitors[current_monitor].area.left + 1) *
Packit Service b1ea74
				              settings->PercentScreen) /
Packit Service fa4841
				             100;
Packit Service fa4841
Packit Service fa4841
			if (settings->PercentScreenUseHeight)
Packit Service fa4841
				*pMaxHeight = ((vscreen->monitors[current_monitor].area.bottom -
Packit Service b1ea74
				                vscreen->monitors[current_monitor].area.top + 1) *
Packit Service b1ea74
				               settings->PercentScreen) /
Packit Service fa4841
				              100;
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			*pMaxWidth = xfc->workArea.width;
Packit Service fa4841
			*pMaxHeight = xfc->workArea.height;
Packit Service fa4841
Packit Service fa4841
			if (settings->PercentScreenUseWidth)
Packit Service fa4841
				*pMaxWidth = (xfc->workArea.width * settings->PercentScreen) / 100;
Packit Service fa4841
Packit Service fa4841
			if (settings->PercentScreenUseHeight)
Packit Service fa4841
				*pMaxHeight = (xfc->workArea.height * settings->PercentScreen) / 100;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
	else if (settings->DesktopWidth && settings->DesktopHeight)
Packit Service fa4841
	{
Packit Service fa4841
		*pMaxWidth = settings->DesktopWidth;
Packit Service fa4841
		*pMaxHeight = settings->DesktopHeight;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	/* Create array of all active monitors by taking into account monitors requested on the
Packit Service b1ea74
	 * command-line */
Packit Service fa4841
	{
Packit Service b1ea74
		int i;
Packit Service fa4841
Packit Service b1ea74
		for (i = 0; i < vscreen->nmonitors; i++)
Packit Service bb5c11
		{
Packit Service b1ea74
			MONITOR_ATTRIBUTES* attrs;
Packit Service b1ea74
Packit Service b1ea74
			if (!xf_is_monitor_id_active(xfc, (UINT32)i))
Packit Service b1ea74
				continue;
Packit Service b1ea74
Packit Service b1ea74
			if (!vscreen->monitors)
Packit Service b1ea74
				return FALSE;
Packit Service b1ea74
Packit Service b1ea74
			settings->MonitorDefArray[nmonitors].x =
Packit Service b1ea74
			    (vscreen->monitors[i].area.left *
Packit Service b1ea74
			     (settings->PercentScreenUseWidth ? settings->PercentScreen : 100)) /
Packit Service b1ea74
			    100;
Packit Service b1ea74
			settings->MonitorDefArray[nmonitors].y =
Packit Service b1ea74
			    (vscreen->monitors[i].area.top *
Packit Service b1ea74
			     (settings->PercentScreenUseHeight ? settings->PercentScreen : 100)) /
Packit Service b1ea74
			    100;
Packit Service b1ea74
			settings->MonitorDefArray[nmonitors].width =
Packit Service b1ea74
			    ((vscreen->monitors[i].area.right - vscreen->monitors[i].area.left + 1) *
Packit Service b1ea74
			     (settings->PercentScreenUseWidth ? settings->PercentScreen : 100)) /
Packit Service b1ea74
			    100;
Packit Service b1ea74
			settings->MonitorDefArray[nmonitors].height =
Packit Service b1ea74
			    ((vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1) *
Packit Service b1ea74
			     (settings->PercentScreenUseWidth ? settings->PercentScreen : 100)) /
Packit Service b1ea74
			    100;
Packit Service b1ea74
			settings->MonitorDefArray[nmonitors].orig_screen = i;
Packit Service b1ea74
#ifdef USABLE_XRANDR
Packit Service b1ea74
Packit Service b1ea74
			if (useXRandr && rrmonitors)
Packit Service b1ea74
			{
Packit Service b1ea74
				Rotation rot, ret;
Packit Service b1ea74
				attrs = &settings->MonitorDefArray[nmonitors].attributes;
Packit Service b1ea74
				attrs->physicalWidth = rrmonitors[i].mwidth;
Packit Service b1ea74
				attrs->physicalHeight = rrmonitors[i].mheight;
Packit Service b1ea74
				ret = XRRRotations(xfc->display, i, &rot);
Packit Service b1ea74
				attrs->orientation = rot;
Packit Service b1ea74
			}
Packit Service fa4841
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service b1ea74
			if ((UINT32)i == settings->MonitorIds[0])
Packit Service b1ea74
			{
Packit Service b1ea74
				settings->MonitorDefArray[nmonitors].is_primary = TRUE;
Packit Service b1ea74
				settings->MonitorLocalShiftX = settings->MonitorDefArray[nmonitors].x;
Packit Service b1ea74
				settings->MonitorLocalShiftY = settings->MonitorDefArray[nmonitors].y;
Packit Service b1ea74
				primaryMonitorFound = TRUE;
Packit Service b1ea74
			}
Packit Service bb5c11
Packit Service b1ea74
			nmonitors++;
Packit Service b1ea74
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	/* If no monitor is active(bogus command-line monitor specification) - then lets try to fallback
Packit Service b1ea74
	 * to go fullscreen on the current monitor only */
Packit Service fa4841
	if (nmonitors == 0 && vscreen->nmonitors > 0)
Packit Service fa4841
	{
Packit Service b1ea74
		INT32 width, height;
Packit Service b1ea74
		if (!vscreen->monitors)
Packit Service b1ea74
			return FALSE;
Packit Service b1ea74
Packit Service b1ea74
		width = vscreen->monitors[current_monitor].area.right -
Packit Service b1ea74
		        vscreen->monitors[current_monitor].area.left + 1L;
Packit Service b1ea74
		height = vscreen->monitors[current_monitor].area.bottom -
Packit Service b1ea74
		         vscreen->monitors[current_monitor].area.top + 1L;
Packit Service b1ea74
Packit Service fa4841
		settings->MonitorDefArray[0].x = vscreen->monitors[current_monitor].area.left;
Packit Service fa4841
		settings->MonitorDefArray[0].y = vscreen->monitors[current_monitor].area.top;
Packit Service b1ea74
		settings->MonitorDefArray[0].width = MIN(width, (INT64)(*pMaxWidth));
Packit Service b1ea74
		settings->MonitorDefArray[0].height = MIN(height, (INT64)(*pMaxHeight));
Packit Service fa4841
		settings->MonitorDefArray[0].orig_screen = current_monitor;
Packit Service fa4841
		nmonitors = 1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	settings->MonitorCount = nmonitors;
Packit Service fa4841
Packit Service fa4841
	/* If we have specific monitor information */
Packit Service fa4841
	if (settings->MonitorCount)
Packit Service fa4841
	{
Packit Service b1ea74
		UINT32 i;
Packit Service fa4841
		/* Initialize bounding rectangle for all monitors */
Packit Service fa4841
		int vX = settings->MonitorDefArray[0].x;
Packit Service fa4841
		int vY = settings->MonitorDefArray[0].y;
Packit Service fa4841
		int vR = vX + settings->MonitorDefArray[0].width;
Packit Service fa4841
		int vB = vY + settings->MonitorDefArray[0].height;
Packit Service fa4841
		xfc->fullscreenMonitors.top = xfc->fullscreenMonitors.bottom =
Packit Service b1ea74
		    xfc->fullscreenMonitors.left = xfc->fullscreenMonitors.right =
Packit Service b1ea74
		        settings->MonitorDefArray[0].orig_screen;
Packit Service fa4841
Packit Service fa4841
		/* Calculate bounding rectangle around all monitors to be used AND
Packit Service fa4841
		 * also set the Xinerama indices which define left/top/right/bottom monitors.
Packit Service fa4841
		 */
Packit Service fa4841
		for (i = 1; i < settings->MonitorCount; i++)
Packit Service fa4841
		{
Packit Service fa4841
			/* does the same as gdk_rectangle_union */
Packit Service fa4841
			int destX = MIN(vX, settings->MonitorDefArray[i].x);
Packit Service fa4841
			int destY = MIN(vY, settings->MonitorDefArray[i].y);
Packit Service b1ea74
			int destR =
Packit Service b1ea74
			    MAX(vR, settings->MonitorDefArray[i].x + settings->MonitorDefArray[i].width);
Packit Service b1ea74
			int destB =
Packit Service b1ea74
			    MAX(vB, settings->MonitorDefArray[i].y + settings->MonitorDefArray[i].height);
Packit Service fa4841
Packit Service fa4841
			if (vX != destX)
Packit Service fa4841
				xfc->fullscreenMonitors.left = settings->MonitorDefArray[i].orig_screen;
Packit Service fa4841
Packit Service fa4841
			if (vY != destY)
Packit Service fa4841
				xfc->fullscreenMonitors.top = settings->MonitorDefArray[i].orig_screen;
Packit Service fa4841
Packit Service fa4841
			if (vR != destR)
Packit Service fa4841
				xfc->fullscreenMonitors.right = settings->MonitorDefArray[i].orig_screen;
Packit Service fa4841
Packit Service fa4841
			if (vB != destB)
Packit Service fa4841
				xfc->fullscreenMonitors.bottom = settings->MonitorDefArray[i].orig_screen;
Packit Service fa4841
Packit Service b1ea74
			vX = destX / ((settings->PercentScreenUseWidth ? settings->PercentScreen : 100) / 100.);
Packit Service b1ea74
			vY =
Packit Service b1ea74
			    destY / ((settings->PercentScreenUseHeight ? settings->PercentScreen : 100) / 100.);
Packit Service b1ea74
			vR = destR / ((settings->PercentScreenUseWidth ? settings->PercentScreen : 100) / 100.);
Packit Service b1ea74
			vB =
Packit Service b1ea74
			    destB / ((settings->PercentScreenUseHeight ? settings->PercentScreen : 100) / 100.);
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		vscreen->area.left = 0;
Packit Service fa4841
		vscreen->area.right = vR - vX - 1;
Packit Service fa4841
		vscreen->area.top = 0;
Packit Service fa4841
		vscreen->area.bottom = vB - vY - 1;
Packit Service fa4841
Packit Service fa4841
		if (settings->Workarea)
Packit Service fa4841
		{
Packit Service fa4841
			vscreen->area.top = xfc->workArea.y;
Packit Service fa4841
			vscreen->area.bottom = xfc->workArea.height + xfc->workArea.y - 1;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (!primaryMonitorFound)
Packit Service fa4841
		{
Packit Service fa4841
			/* If we have a command line setting we should use it */
Packit Service fa4841
			if (settings->NumMonitorIds)
Packit Service fa4841
			{
Packit Service fa4841
				/* The first monitor is the first in the setting which should be used */
Packit Service b1ea74
				monitor_index = settings->MonitorIds[0];
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service fa4841
				/* This is the same as when we would trust the Xinerama results..
Packit Service fa4841
				   and set the monitor index to zero.
Packit Service fa4841
				   The monitor listed with /monitor-list on index zero is always the primary
Packit Service fa4841
				*/
Packit Service fa4841
				screen = DefaultScreenOfDisplay(xfc->display);
Packit Service fa4841
				monitor_index = XScreenNumberOfScreen(screen);
Packit Service fa4841
			}
Packit Service fa4841
Packit Service fa4841
			int j = monitor_index;
Packit Service fa4841
Packit Service fa4841
			/* If the "default" monitor is not 0,0 use it */
Packit Service fa4841
			if (settings->MonitorDefArray[j].x != 0 || settings->MonitorDefArray[j].y != 0)
Packit Service fa4841
			{
Packit Service fa4841
				settings->MonitorDefArray[j].is_primary = TRUE;
Packit Service fa4841
				settings->MonitorLocalShiftX = settings->MonitorDefArray[j].x;
Packit Service fa4841
				settings->MonitorLocalShiftY = settings->MonitorDefArray[j].y;
Packit Service fa4841
				primaryMonitorFound = TRUE;
Packit Service fa4841
			}
Packit Service fa4841
			else
Packit Service fa4841
			{
Packit Service b1ea74
				/* Lets try to see if there is a monitor with a 0,0 coordinate and use it as a
Packit Service b1ea74
				 * fallback*/
Packit Service fa4841
				for (i = 0; i < settings->MonitorCount; i++)
Packit Service fa4841
				{
Packit Service b1ea74
					if (!primaryMonitorFound && settings->MonitorDefArray[i].x == 0 &&
Packit Service b1ea74
					    settings->MonitorDefArray[i].y == 0)
Packit Service fa4841
					{
Packit Service fa4841
						settings->MonitorDefArray[i].is_primary = TRUE;
Packit Service fa4841
						settings->MonitorLocalShiftX = settings->MonitorDefArray[i].x;
Packit Service fa4841
						settings->MonitorLocalShiftY = settings->MonitorDefArray[i].y;
Packit Service fa4841
						primaryMonitorFound = TRUE;
Packit Service fa4841
					}
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		/* Subtract monitor shift from monitor variables for server-side use.
Packit Service b1ea74
		 * We maintain monitor shift value as Window requires the primary monitor to have a
Packit Service b1ea74
		 * coordinate of 0,0 In some X configurations, no monitor may have a coordinate of 0,0. This
Packit Service b1ea74
		 * can also be happen if the user requests specific monitors from the command-line as well.
Packit Service b1ea74
		 * So, we make sure to translate our primary monitor's upper-left corner to 0,0 on the
Packit Service b1ea74
		 * server.
Packit Service fa4841
		 */
Packit Service fa4841
		for (i = 0; i < settings->MonitorCount; i++)
Packit Service fa4841
		{
Packit Service b1ea74
			settings->MonitorDefArray[i].x =
Packit Service b1ea74
			    settings->MonitorDefArray[i].x - settings->MonitorLocalShiftX;
Packit Service b1ea74
			settings->MonitorDefArray[i].y =
Packit Service b1ea74
			    settings->MonitorDefArray[i].y - settings->MonitorLocalShiftY;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service b1ea74
		/* Set the desktop width and height according to the bounding rectangle around the active
Packit Service b1ea74
		 * monitors */
Packit Service b1ea74
		*pMaxWidth = MIN(*pMaxWidth, (UINT32)vscreen->area.right - vscreen->area.left + 1);
Packit Service b1ea74
		*pMaxHeight = MIN(*pMaxHeight, (UINT32)vscreen->area.bottom - vscreen->area.top + 1);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* some 2008 server freeze at logon if we announce support for monitor layout PDU with
Packit Service fa4841
	 * #monitors < 2. So let's announce it only if we have more than 1 monitor.
Packit Service fa4841
	 */
Packit Service fa4841
	if (settings->MonitorCount)
Packit Service fa4841
		settings->SupportMonitorLayoutPdu = TRUE;
Packit Service fa4841
Packit Service fa4841
#ifdef USABLE_XRANDR
Packit Service fa4841
Packit Service fa4841
	if (rrmonitors)
Packit Service fa4841
		XRRFreeMonitors(rrmonitors);
Packit Service fa4841
Packit Service fa4841
#endif
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}