/* 
 * OroboROX Window Manager
 * xinerama functions
 *
 * Copyright (C) 2004 Tony Houghton
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
 */

#include "config.h"
#include <glib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include "main.h"
#include "xinerama.h"

int xinerama_nscreens = 0;

XineramaScreenInfo *xinerama_screen_info = NULL;

static gboolean screen_info_isnt_x = FALSE;

static void xinerama_free_old_screen_info(void)
{
	if (xinerama_screen_info)
	{
		if (screen_info_isnt_x)
			g_free(xinerama_screen_info);
		else
			XFree(xinerama_screen_info);
	}
	xinerama_screen_info = NULL;
}

#ifdef HAVE_XINERAMA
static void xinerama_disabled_cache_screen_info(void)
{
#else
void xinerama_cache_screen_info(void)
{
	xinerama_free_old_screen_info();
#endif
	xinerama_screen_info = g_new(XineramaScreenInfo, 1);
	xinerama_screen_info->screen_number = 0;
	xinerama_screen_info->x_org = xinerama_screen_info->y_org = 0;
	xinerama_screen_info->width = display_width;
	xinerama_screen_info->height = display_height;
	screen_info_isnt_x = TRUE;
	xinerama_nscreens = 1;
#ifdef DEBUG
	fprintf(stderr, "No Xinerama, screen width and height %d x %d\n",
			xinerama_screen_info->width, xinerama_screen_info->height);
#endif
}

#ifdef HAVE_XINERAMA

void xinerama_cache_screen_info(void)
{
	xinerama_free_old_screen_info();
#ifdef HAVE_SOLARIS_XINERAMA
	if (XINERAMA_IS_ACTIVE())
	{
		/* GDK source uses MAXFRAMEBUFFERS and magic number 16 in this way, but
		 * MAXFRAMEBUFFERS isn't defined anywhere in GDK's source or libraries
		 * it depends on in a Linux system AFAICT. Hopefully it is available in
		 * Solaris. If not, presumably 16 is a safe value instead? */
		XRectangle monitors[MAXFRAMEBUFFERS];
		unsigned char hints[16];
		int result = XineramaGetInfo(dpy, screen, monitors, hints,
									 &xinerama_nscreens);

		screen_info_isnt_x = TRUE;
		if (result)
		{
			int m;

			xinerama_screen_info = g_new(XineramaScreenInfo, xinerama_nscreens);
			for (m = 0; m < xinerama_nscreens; ++m)
			{
				xinerama_screen_info[m].screen_number = m;
				xinerama_screen_info[m].x_org = monitors[m].x;
				xinerama_screen_info[m].y_org = monitors[m].y;
				xinerama_screen_info[m].width = monitors[m].width;
				xinerama_screen_info[m].height = monitors[m].height;
			}
		}
		else
		{
			fprintf(stderr, "Error getting Xinerama information\n");
			xinerama_nscreens = 0;
		}
	}
#else /* Must be XFree86 */
	if (XINERAMA_IS_ACTIVE())
	{
		xinerama_screen_info = XineramaQueryScreens(dpy, &xinerama_nscreens);
		if (xinerama_nscreens > 0)
			screen_info_isnt_x = FALSE;
	}
#endif
	else
		xinerama_nscreens = 0;
	if (xinerama_nscreens <= 0)
		xinerama_disabled_cache_screen_info();
#ifdef DEBUG
	{
		int m;

		for (m = 0; m < xinerama_nscreens; ++m)
		{
			printf("Monitor %d (%d) starts at (%d, %d) "
				   "and extends for %d x %d\n",
				   m, xinerama_screen_info[m].screen_number,
				   xinerama_screen_info[m].x_org,
				   xinerama_screen_info[m].y_org,
				   xinerama_screen_info[m].width, xinerama_screen_info[m].height);
		}
	}
#endif
}

int xineramaGetMonitorUnderPoint(int mx, int my)
{
	int n;

#ifdef DEBUG
	printf("Looking for monitor under (%d, %d)\n", mx, my);
#endif
	for (n = 0; n < xinerama_nscreens; ++n)
	{
		if (xinerama_screen_info[n].x_org <= mx &&
			xinerama_screen_info[n].x_org +
			xinerama_screen_info[n].width > mx &&
			xinerama_screen_info[n].y_org <= my &&
			xinerama_screen_info[n].y_org + xinerama_screen_info[n].height > my)
		{
#ifdef DEBUG
			printf("Monitor %d (%d, %d) %d x %d\n", n,
				   xinerama_screen_info[n].x_org, xinerama_screen_info[n].y_org,
				   xinerama_screen_info[n].width, xinerama_screen_info[n].height);
#endif
			return n;
		}
	}
	fprintf(stderr, "Warning: No monitor under point (%d, %d)", mx, my);
	return 0;
}

#endif /* HAVE_XINERAMA */

