Blame client/X11/xf_monitor.c

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