105b261ecSmrg/* 205b261ecSmrg * Copyright (c) 1994-2003 by The XFree86 Project, Inc. 305b261ecSmrg * 405b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 505b261ecSmrg * copy of this software and associated documentation files (the "Software"), 605b261ecSmrg * to deal in the Software without restriction, including without limitation 705b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 805b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 905b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1005b261ecSmrg * 1105b261ecSmrg * The above copyright notice and this permission notice shall be included in 1205b261ecSmrg * all copies or substantial portions of the Software. 1305b261ecSmrg * 1405b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1705b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1805b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1905b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2005b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE. 2105b261ecSmrg * 2205b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s) 2305b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote 2405b261ecSmrg * the sale, use or other dealings in this Software without prior written 2505b261ecSmrg * authorization from the copyright holder(s) and author(s). 2605b261ecSmrg */ 2705b261ecSmrg 2805b261ecSmrg#ifdef HAVE_XORG_CONFIG_H 2905b261ecSmrg#include <xorg-config.h> 3005b261ecSmrg#endif 3105b261ecSmrg 3205b261ecSmrg#include <X11/X.h> 3305b261ecSmrg#include <X11/Xmd.h> 3405b261ecSmrg#include "input.h" 3505b261ecSmrg#include "cursor.h" 3605b261ecSmrg#include "mipointer.h" 3705b261ecSmrg#include "scrnintstr.h" 3805b261ecSmrg#include "globals.h" 3905b261ecSmrg 4005b261ecSmrg#include "xf86.h" 4105b261ecSmrg#include "xf86Priv.h" 4205b261ecSmrg#include "xf86_OSproc.h" 4305b261ecSmrg 4405b261ecSmrg#include <X11/extensions/XIproto.h> 4505b261ecSmrg#include "xf86Xinput.h" 4605b261ecSmrg 4705b261ecSmrg#ifdef XFreeXDGA 4805b261ecSmrg#include "dgaproc.h" 4905b261ecSmrg#endif 5005b261ecSmrg 5105b261ecSmrgtypedef struct _xf86EdgeRec { 5235c4bbdfSmrg short screen; 5335c4bbdfSmrg short start; 5435c4bbdfSmrg short end; 5535c4bbdfSmrg DDXPointRec offset; 5635c4bbdfSmrg struct _xf86EdgeRec *next; 5705b261ecSmrg} xf86EdgeRec, *xf86EdgePtr; 5805b261ecSmrg 5905b261ecSmrgtypedef struct { 6035c4bbdfSmrg xf86EdgePtr left, right, up, down; 6105b261ecSmrg} xf86ScreenLayoutRec, *xf86ScreenLayoutPtr; 6205b261ecSmrg 6305b261ecSmrgstatic Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y); 6405b261ecSmrgstatic void xf86CrossScreen(ScreenPtr pScreen, Bool entering); 654642e01fSmrgstatic void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); 6605b261ecSmrg 6735c4bbdfSmrgstatic void xf86PointerMoved(ScrnInfoPtr pScrn, int x, int y); 6805b261ecSmrg 6905b261ecSmrgstatic miPointerScreenFuncRec xf86PointerScreenFuncs = { 7035c4bbdfSmrg xf86CursorOffScreen, 7135c4bbdfSmrg xf86CrossScreen, 7235c4bbdfSmrg xf86WarpCursor, 7305b261ecSmrg}; 7405b261ecSmrg 7505b261ecSmrgstatic xf86ScreenLayoutRec xf86ScreenLayout[MAXSCREENS]; 7605b261ecSmrg 7705b261ecSmrg/* 7805b261ecSmrg * xf86InitViewport -- 7905b261ecSmrg * Initialize paning & zooming parameters, so that a driver must only 8005b261ecSmrg * check what resolutions are possible and whether the virtual area 8105b261ecSmrg * is valid if specified. 8205b261ecSmrg */ 8305b261ecSmrg 8405b261ecSmrgvoid 8505b261ecSmrgxf86InitViewport(ScrnInfoPtr pScr) 8605b261ecSmrg{ 8705b261ecSmrg 8835c4bbdfSmrg pScr->PointerMoved = xf86PointerMoved; 8935c4bbdfSmrg 9035c4bbdfSmrg /* 9135c4bbdfSmrg * Compute the initial Viewport if necessary 9235c4bbdfSmrg */ 9335c4bbdfSmrg if (pScr->display) { 9435c4bbdfSmrg if (pScr->display->frameX0 < 0) { 9535c4bbdfSmrg pScr->frameX0 = (pScr->virtualX - pScr->modes->HDisplay) / 2; 9635c4bbdfSmrg pScr->frameY0 = (pScr->virtualY - pScr->modes->VDisplay) / 2; 9735c4bbdfSmrg } 9835c4bbdfSmrg else { 9935c4bbdfSmrg pScr->frameX0 = pScr->display->frameX0; 10035c4bbdfSmrg pScr->frameY0 = pScr->display->frameY0; 10135c4bbdfSmrg } 10205b261ecSmrg } 10335c4bbdfSmrg 10435c4bbdfSmrg pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; 10535c4bbdfSmrg pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; 10635c4bbdfSmrg 10735c4bbdfSmrg /* 10835c4bbdfSmrg * Now adjust the initial Viewport, so it lies within the virtual area 10935c4bbdfSmrg */ 11035c4bbdfSmrg if (pScr->frameX1 >= pScr->virtualX) { 11135c4bbdfSmrg pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay; 11235c4bbdfSmrg pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; 11305b261ecSmrg } 11405b261ecSmrg 11535c4bbdfSmrg if (pScr->frameY1 >= pScr->virtualY) { 11635c4bbdfSmrg pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay; 11735c4bbdfSmrg pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; 11805b261ecSmrg } 11905b261ecSmrg} 12005b261ecSmrg 12105b261ecSmrg/* 12205b261ecSmrg * xf86SetViewport -- 12305b261ecSmrg * Scroll the visual part of the screen so the pointer is visible. 12405b261ecSmrg */ 12505b261ecSmrg 12605b261ecSmrgvoid 12705b261ecSmrgxf86SetViewport(ScreenPtr pScreen, int x, int y) 12805b261ecSmrg{ 12935c4bbdfSmrg ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen); 13005b261ecSmrg 13135c4bbdfSmrg (*pScr->PointerMoved) (pScr, x, y); 13205b261ecSmrg} 13305b261ecSmrg 13435c4bbdfSmrgstatic void 13535c4bbdfSmrgxf86PointerMoved(ScrnInfoPtr pScr, int x, int y) 13605b261ecSmrg{ 13735c4bbdfSmrg Bool frameChanged = FALSE; 13835c4bbdfSmrg 13935c4bbdfSmrg /* 140ed6184dfSmrg * check whether (x,y) belongs to the visual part of the screen 141ed6184dfSmrg * if not, change the base of the displayed frame occurring 14235c4bbdfSmrg */ 14335c4bbdfSmrg if (pScr->frameX0 > x) { 14435c4bbdfSmrg pScr->frameX0 = x; 14535c4bbdfSmrg pScr->frameX1 = x + pScr->currentMode->HDisplay - 1; 14635c4bbdfSmrg frameChanged = TRUE; 14735c4bbdfSmrg } 14835c4bbdfSmrg 14935c4bbdfSmrg if (pScr->frameX1 < x) { 15035c4bbdfSmrg pScr->frameX1 = x + 1; 15135c4bbdfSmrg pScr->frameX0 = x - pScr->currentMode->HDisplay + 1; 15235c4bbdfSmrg frameChanged = TRUE; 15335c4bbdfSmrg } 15435c4bbdfSmrg 15535c4bbdfSmrg if (pScr->frameY0 > y) { 15635c4bbdfSmrg pScr->frameY0 = y; 15735c4bbdfSmrg pScr->frameY1 = y + pScr->currentMode->VDisplay - 1; 15835c4bbdfSmrg frameChanged = TRUE; 15935c4bbdfSmrg } 16035c4bbdfSmrg 16135c4bbdfSmrg if (pScr->frameY1 < y) { 16235c4bbdfSmrg pScr->frameY1 = y; 16335c4bbdfSmrg pScr->frameY0 = y - pScr->currentMode->VDisplay + 1; 16435c4bbdfSmrg frameChanged = TRUE; 16535c4bbdfSmrg } 16635c4bbdfSmrg 16735c4bbdfSmrg if (frameChanged && pScr->AdjustFrame != NULL) 16835c4bbdfSmrg pScr->AdjustFrame(pScr, pScr->frameX0, pScr->frameY0); 16905b261ecSmrg} 17005b261ecSmrg 17105b261ecSmrg/* 17205b261ecSmrg * xf86LockZoom -- 17305b261ecSmrg * Enable/disable ZoomViewport 17405b261ecSmrg */ 17505b261ecSmrg 17605b261ecSmrgvoid 17705b261ecSmrgxf86LockZoom(ScreenPtr pScreen, Bool lock) 17805b261ecSmrg{ 17935c4bbdfSmrg ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen); 18035c4bbdfSmrg pScr->zoomLocked = lock; 18105b261ecSmrg} 18205b261ecSmrg 18305b261ecSmrg/* 18405b261ecSmrg * xf86SwitchMode -- 18505b261ecSmrg * This is called by both keyboard processing and the VidMode extension to 18605b261ecSmrg * set a new mode. 18705b261ecSmrg */ 18805b261ecSmrg 18905b261ecSmrgBool 19005b261ecSmrgxf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) 19105b261ecSmrg{ 19235c4bbdfSmrg ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen); 19335c4bbdfSmrg ScreenPtr pCursorScreen; 19435c4bbdfSmrg Bool Switched; 19535c4bbdfSmrg int px, py; 19635c4bbdfSmrg DeviceIntPtr dev, it; 19705b261ecSmrg 19835c4bbdfSmrg if (!pScr->vtSema || !mode || !pScr->SwitchMode) 19935c4bbdfSmrg return FALSE; 20005b261ecSmrg 20105b261ecSmrg#ifdef XFreeXDGA 20235c4bbdfSmrg if (DGAActive(pScr->scrnIndex)) 20335c4bbdfSmrg return FALSE; 20405b261ecSmrg#endif 20505b261ecSmrg 20635c4bbdfSmrg if (mode == pScr->currentMode) 20735c4bbdfSmrg return TRUE; 20805b261ecSmrg 20935c4bbdfSmrg if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY) 21035c4bbdfSmrg return FALSE; 2114642e01fSmrg 21235c4bbdfSmrg /* Let's take an educated guess for which pointer to take here. And about as 21335c4bbdfSmrg educated as it gets is to take the first pointer we find. 21405b261ecSmrg */ 21535c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 21635c4bbdfSmrg if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner) 21735c4bbdfSmrg break; 21805b261ecSmrg } 21905b261ecSmrg 22035c4bbdfSmrg pCursorScreen = miPointerGetScreen(dev); 22105b261ecSmrg if (pScreen == pCursorScreen) 22235c4bbdfSmrg miPointerGetPosition(dev, &px, &py); 22335c4bbdfSmrg 2241b5d61b8Smrg input_lock(); 22535c4bbdfSmrg Switched = (*pScr->SwitchMode) (pScr, mode); 22635c4bbdfSmrg if (Switched) { 22735c4bbdfSmrg pScr->currentMode = mode; 22835c4bbdfSmrg 22935c4bbdfSmrg /* 23035c4bbdfSmrg * Adjust frame for new display size. 23135c4bbdfSmrg * Frame is centered around cursor position if cursor is on same screen. 23235c4bbdfSmrg */ 23335c4bbdfSmrg if (pScreen == pCursorScreen) 23435c4bbdfSmrg pScr->frameX0 = px - (mode->HDisplay / 2) + 1; 23535c4bbdfSmrg else 23635c4bbdfSmrg pScr->frameX0 = 23735c4bbdfSmrg (pScr->frameX0 + pScr->frameX1 + 1 - mode->HDisplay) / 2; 23835c4bbdfSmrg 23935c4bbdfSmrg if (pScr->frameX0 < 0) 24035c4bbdfSmrg pScr->frameX0 = 0; 24135c4bbdfSmrg 24235c4bbdfSmrg pScr->frameX1 = pScr->frameX0 + mode->HDisplay - 1; 24335c4bbdfSmrg if (pScr->frameX1 >= pScr->virtualX) { 24435c4bbdfSmrg pScr->frameX0 = pScr->virtualX - mode->HDisplay; 24535c4bbdfSmrg pScr->frameX1 = pScr->virtualX - 1; 24635c4bbdfSmrg } 24735c4bbdfSmrg 24835c4bbdfSmrg if (pScreen == pCursorScreen) 24935c4bbdfSmrg pScr->frameY0 = py - (mode->VDisplay / 2) + 1; 25035c4bbdfSmrg else 25135c4bbdfSmrg pScr->frameY0 = 25235c4bbdfSmrg (pScr->frameY0 + pScr->frameY1 + 1 - mode->VDisplay) / 2; 25335c4bbdfSmrg 25435c4bbdfSmrg if (pScr->frameY0 < 0) 25535c4bbdfSmrg pScr->frameY0 = 0; 25635c4bbdfSmrg 25735c4bbdfSmrg pScr->frameY1 = pScr->frameY0 + mode->VDisplay - 1; 25835c4bbdfSmrg if (pScr->frameY1 >= pScr->virtualY) { 25935c4bbdfSmrg pScr->frameY0 = pScr->virtualY - mode->VDisplay; 26035c4bbdfSmrg pScr->frameY1 = pScr->virtualY - 1; 26135c4bbdfSmrg } 26235c4bbdfSmrg } 2631b5d61b8Smrg input_unlock(); 26405b261ecSmrg 26535c4bbdfSmrg if (pScr->AdjustFrame) 26635c4bbdfSmrg (*pScr->AdjustFrame) (pScr, pScr->frameX0, pScr->frameY0); 26705b261ecSmrg 26835c4bbdfSmrg /* The original code centered the frame around the cursor if possible. 26935c4bbdfSmrg * Since this is hard to achieve with multiple cursors, we do the following: 27035c4bbdfSmrg * - center around the first pointer 27135c4bbdfSmrg * - move all other pointers to the nearest edge on the screen (or leave 27235c4bbdfSmrg * them unmodified if they are within the boundaries). 27335c4bbdfSmrg */ 27435c4bbdfSmrg if (pScreen == pCursorScreen) { 27535c4bbdfSmrg xf86WarpCursor(dev, pScreen, px, py); 27605b261ecSmrg } 27735c4bbdfSmrg 27835c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 27935c4bbdfSmrg if (it == dev) 28035c4bbdfSmrg continue; 28135c4bbdfSmrg 28235c4bbdfSmrg if (IsPointerDevice(it) && it->spriteInfo->spriteOwner) { 28335c4bbdfSmrg pCursorScreen = miPointerGetScreen(it); 28435c4bbdfSmrg if (pScreen == pCursorScreen) { 28535c4bbdfSmrg miPointerGetPosition(it, &px, &py); 28635c4bbdfSmrg if (px < pScr->frameX0) 28735c4bbdfSmrg px = pScr->frameX0; 28835c4bbdfSmrg else if (px > pScr->frameX1) 28935c4bbdfSmrg px = pScr->frameX1; 29035c4bbdfSmrg 29135c4bbdfSmrg if (py < pScr->frameY0) 29235c4bbdfSmrg py = pScr->frameY0; 29335c4bbdfSmrg else if (py > pScr->frameY1) 29435c4bbdfSmrg py = pScr->frameY1; 29535c4bbdfSmrg 29635c4bbdfSmrg xf86WarpCursor(it, pScreen, px, py); 29735c4bbdfSmrg } 29835c4bbdfSmrg } 29935c4bbdfSmrg } 30035c4bbdfSmrg 30135c4bbdfSmrg return Switched; 30205b261ecSmrg} 30335c4bbdfSmrg 30405b261ecSmrg/* 30505b261ecSmrg * xf86ZoomViewport -- 30605b261ecSmrg * Reinitialize the visual part of the screen for another mode. 30705b261ecSmrg */ 30805b261ecSmrg 30905b261ecSmrgvoid 31005b261ecSmrgxf86ZoomViewport(ScreenPtr pScreen, int zoom) 31105b261ecSmrg{ 31235c4bbdfSmrg ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen); 31335c4bbdfSmrg DisplayModePtr mode; 31405b261ecSmrg 31535c4bbdfSmrg if (pScr->zoomLocked || !(mode = pScr->currentMode)) 31635c4bbdfSmrg return; 31705b261ecSmrg 31835c4bbdfSmrg do { 31935c4bbdfSmrg if (zoom > 0) 32035c4bbdfSmrg mode = mode->next; 32135c4bbdfSmrg else 32235c4bbdfSmrg mode = mode->prev; 32335c4bbdfSmrg } while (mode != pScr->currentMode && !(mode->type & M_T_USERDEF)); 32405b261ecSmrg 32535c4bbdfSmrg (void) xf86SwitchMode(pScreen, mode); 32605b261ecSmrg} 32705b261ecSmrg 32805b261ecSmrgstatic xf86EdgePtr 32905b261ecSmrgFindEdge(xf86EdgePtr edge, int val) 33005b261ecSmrg{ 33135c4bbdfSmrg while (edge && (edge->end <= val)) 33235c4bbdfSmrg edge = edge->next; 33305b261ecSmrg 33435c4bbdfSmrg if (edge && (edge->start <= val)) 33535c4bbdfSmrg return edge; 33605b261ecSmrg 33705b261ecSmrg return NULL; 33805b261ecSmrg} 33905b261ecSmrg 34005b261ecSmrg/* 34105b261ecSmrg * xf86CursorOffScreen -- 34205b261ecSmrg * Check whether it is necessary to switch to another screen 34305b261ecSmrg */ 34405b261ecSmrg 34505b261ecSmrgstatic Bool 34605b261ecSmrgxf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y) 34705b261ecSmrg{ 34805b261ecSmrg xf86EdgePtr edge; 34905b261ecSmrg int tmp; 35005b261ecSmrg 35135c4bbdfSmrg if (screenInfo.numScreens == 1) 35235c4bbdfSmrg return FALSE; 35305b261ecSmrg 35435c4bbdfSmrg if (*x < 0) { 35505b261ecSmrg tmp = *y; 35635c4bbdfSmrg if (tmp < 0) 35735c4bbdfSmrg tmp = 0; 35835c4bbdfSmrg if (tmp >= (*pScreen)->height) 35935c4bbdfSmrg tmp = (*pScreen)->height - 1; 36035c4bbdfSmrg 36135c4bbdfSmrg if ((edge = xf86ScreenLayout[(*pScreen)->myNum].left)) 36235c4bbdfSmrg edge = FindEdge(edge, tmp); 36335c4bbdfSmrg 36435c4bbdfSmrg if (!edge) 36535c4bbdfSmrg *x = 0; 36635c4bbdfSmrg else { 36735c4bbdfSmrg *x += edge->offset.x; 36835c4bbdfSmrg *y += edge->offset.y; 36935c4bbdfSmrg *pScreen = xf86Screens[edge->screen]->pScreen; 37035c4bbdfSmrg } 37105b261ecSmrg } 37205b261ecSmrg 37335c4bbdfSmrg if (*x >= (*pScreen)->width) { 37405b261ecSmrg tmp = *y; 37535c4bbdfSmrg if (tmp < 0) 37635c4bbdfSmrg tmp = 0; 37735c4bbdfSmrg if (tmp >= (*pScreen)->height) 37835c4bbdfSmrg tmp = (*pScreen)->height - 1; 37935c4bbdfSmrg 38035c4bbdfSmrg if ((edge = xf86ScreenLayout[(*pScreen)->myNum].right)) 38135c4bbdfSmrg edge = FindEdge(edge, tmp); 38235c4bbdfSmrg 38335c4bbdfSmrg if (!edge) 38435c4bbdfSmrg *x = (*pScreen)->width - 1; 38535c4bbdfSmrg else { 38635c4bbdfSmrg *x += edge->offset.x; 38735c4bbdfSmrg *y += edge->offset.y; 38835c4bbdfSmrg *pScreen = xf86Screens[edge->screen]->pScreen; 38935c4bbdfSmrg } 39005b261ecSmrg } 39105b261ecSmrg 39235c4bbdfSmrg if (*y < 0) { 39305b261ecSmrg tmp = *x; 39435c4bbdfSmrg if (tmp < 0) 39535c4bbdfSmrg tmp = 0; 39635c4bbdfSmrg if (tmp >= (*pScreen)->width) 39735c4bbdfSmrg tmp = (*pScreen)->width - 1; 39835c4bbdfSmrg 39935c4bbdfSmrg if ((edge = xf86ScreenLayout[(*pScreen)->myNum].up)) 40035c4bbdfSmrg edge = FindEdge(edge, tmp); 40135c4bbdfSmrg 40235c4bbdfSmrg if (!edge) 40335c4bbdfSmrg *y = 0; 40435c4bbdfSmrg else { 40535c4bbdfSmrg *x += edge->offset.x; 40635c4bbdfSmrg *y += edge->offset.y; 40735c4bbdfSmrg *pScreen = xf86Screens[edge->screen]->pScreen; 40835c4bbdfSmrg } 40905b261ecSmrg } 41005b261ecSmrg 41135c4bbdfSmrg if (*y >= (*pScreen)->height) { 41205b261ecSmrg tmp = *x; 41335c4bbdfSmrg if (tmp < 0) 41435c4bbdfSmrg tmp = 0; 41535c4bbdfSmrg if (tmp >= (*pScreen)->width) 41635c4bbdfSmrg tmp = (*pScreen)->width - 1; 41735c4bbdfSmrg 41835c4bbdfSmrg if ((edge = xf86ScreenLayout[(*pScreen)->myNum].down)) 41935c4bbdfSmrg edge = FindEdge(edge, tmp); 42035c4bbdfSmrg 42135c4bbdfSmrg if (!edge) 42235c4bbdfSmrg *y = (*pScreen)->height - 1; 42335c4bbdfSmrg else { 42435c4bbdfSmrg *x += edge->offset.x; 42535c4bbdfSmrg *y += edge->offset.y; 42635c4bbdfSmrg (*pScreen) = xf86Screens[edge->screen]->pScreen; 42735c4bbdfSmrg } 42805b261ecSmrg } 42905b261ecSmrg 43005b261ecSmrg return TRUE; 43105b261ecSmrg} 43205b261ecSmrg 43305b261ecSmrg/* 43405b261ecSmrg * xf86CrossScreen -- 43505b261ecSmrg * Switch to another screen 43605b261ecSmrg * 43705b261ecSmrg * Currently nothing special happens, but mi assumes the CrossScreen 43805b261ecSmrg * method exists. 43905b261ecSmrg */ 44005b261ecSmrg 44105b261ecSmrgstatic void 44235c4bbdfSmrgxf86CrossScreen(ScreenPtr pScreen, Bool entering) 44305b261ecSmrg{ 44405b261ecSmrg} 44505b261ecSmrg 44605b261ecSmrg/* 44705b261ecSmrg * xf86WarpCursor -- 44805b261ecSmrg * Warp possible to another screen 44905b261ecSmrg */ 45005b261ecSmrg 45105b261ecSmrg/* ARGSUSED */ 45205b261ecSmrgstatic void 45335c4bbdfSmrgxf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 45405b261ecSmrg{ 4551b5d61b8Smrg input_lock(); 4564642e01fSmrg miPointerWarpCursor(pDev, pScreen, x, y); 45705b261ecSmrg 4584642e01fSmrg xf86Info.currentScreen = pScreen; 4591b5d61b8Smrg input_unlock(); 46005b261ecSmrg} 46105b261ecSmrg 4626747b715Smrgvoid * 46305b261ecSmrgxf86GetPointerScreenFuncs(void) 46405b261ecSmrg{ 46535c4bbdfSmrg return (void *) &xf86PointerScreenFuncs; 46605b261ecSmrg} 46705b261ecSmrg 46805b261ecSmrgstatic xf86EdgePtr 46935c4bbdfSmrgAddEdge(xf86EdgePtr edge, 47035c4bbdfSmrg short min, short max, short dx, short dy, short screen) 47135c4bbdfSmrg{ 47235c4bbdfSmrg xf86EdgePtr pEdge = edge, pPrev = NULL, pNew; 47335c4bbdfSmrg 47435c4bbdfSmrg while (1) { 47535c4bbdfSmrg while (pEdge && (min >= pEdge->end)) { 47635c4bbdfSmrg pPrev = pEdge; 47735c4bbdfSmrg pEdge = pEdge->next; 47835c4bbdfSmrg } 47935c4bbdfSmrg 48035c4bbdfSmrg if (!pEdge) { 48135c4bbdfSmrg if (!(pNew = malloc(sizeof(xf86EdgeRec)))) 48235c4bbdfSmrg break; 48335c4bbdfSmrg 48435c4bbdfSmrg pNew->screen = screen; 48535c4bbdfSmrg pNew->start = min; 48635c4bbdfSmrg pNew->end = max; 48735c4bbdfSmrg pNew->offset.x = dx; 48835c4bbdfSmrg pNew->offset.y = dy; 48935c4bbdfSmrg pNew->next = NULL; 49035c4bbdfSmrg 49135c4bbdfSmrg if (pPrev) 49235c4bbdfSmrg pPrev->next = pNew; 49335c4bbdfSmrg else 49435c4bbdfSmrg edge = pNew; 49535c4bbdfSmrg 49635c4bbdfSmrg break; 49735c4bbdfSmrg } 49835c4bbdfSmrg else if (min < pEdge->start) { 49935c4bbdfSmrg if (!(pNew = malloc(sizeof(xf86EdgeRec)))) 50035c4bbdfSmrg break; 50135c4bbdfSmrg 50235c4bbdfSmrg pNew->screen = screen; 50335c4bbdfSmrg pNew->start = min; 50435c4bbdfSmrg pNew->offset.x = dx; 50535c4bbdfSmrg pNew->offset.y = dy; 50635c4bbdfSmrg pNew->next = pEdge; 50735c4bbdfSmrg 50835c4bbdfSmrg if (pPrev) 50935c4bbdfSmrg pPrev->next = pNew; 51035c4bbdfSmrg else 51135c4bbdfSmrg edge = pNew; 51235c4bbdfSmrg 51335c4bbdfSmrg if (max <= pEdge->start) { 51435c4bbdfSmrg pNew->end = max; 51535c4bbdfSmrg break; 51635c4bbdfSmrg } 51735c4bbdfSmrg else { 51835c4bbdfSmrg pNew->end = pEdge->start; 51935c4bbdfSmrg min = pEdge->end; 52035c4bbdfSmrg } 52135c4bbdfSmrg } 52235c4bbdfSmrg else 52335c4bbdfSmrg min = pEdge->end; 52435c4bbdfSmrg 52535c4bbdfSmrg pPrev = pEdge; 52635c4bbdfSmrg pEdge = pEdge->next; 52735c4bbdfSmrg 52835c4bbdfSmrg if (max <= min) 52935c4bbdfSmrg break; 53035c4bbdfSmrg } 53135c4bbdfSmrg 53235c4bbdfSmrg return edge; 53305b261ecSmrg} 53405b261ecSmrg 53505b261ecSmrgstatic void 53605b261ecSmrgFillOutEdge(xf86EdgePtr pEdge, int limit) 53705b261ecSmrg{ 53805b261ecSmrg xf86EdgePtr pNext; 53905b261ecSmrg int diff; 54005b261ecSmrg 54135c4bbdfSmrg if (pEdge->start > 0) 54235c4bbdfSmrg pEdge->start = 0; 54305b261ecSmrg 54435c4bbdfSmrg while ((pNext = pEdge->next)) { 54535c4bbdfSmrg diff = pNext->start - pEdge->end; 54635c4bbdfSmrg if (diff > 0) { 54735c4bbdfSmrg pEdge->end += diff >> 1; 54835c4bbdfSmrg pNext->start -= diff - (diff >> 1); 54935c4bbdfSmrg } 55035c4bbdfSmrg pEdge = pNext; 55105b261ecSmrg } 55205b261ecSmrg 55335c4bbdfSmrg if (pEdge->end < limit) 55435c4bbdfSmrg pEdge->end = limit; 55505b261ecSmrg} 55605b261ecSmrg 55705b261ecSmrg/* 55805b261ecSmrg * xf86InitOrigins() can deal with a maximum of 32 screens 55905b261ecSmrg * on 32 bit architectures, 64 on 64 bit architectures. 56005b261ecSmrg */ 56105b261ecSmrg 56205b261ecSmrgvoid 56305b261ecSmrgxf86InitOrigins(void) 56405b261ecSmrg{ 56505b261ecSmrg unsigned long screensLeft, prevScreensLeft, mask; 56605b261ecSmrg screenLayoutPtr screen; 5676747b715Smrg ScreenPtr pScreen, refScreen; 56805b261ecSmrg int x1, x2, y1, y2, left, right, top, bottom; 56905b261ecSmrg int i, j, ref, minX, minY, min, max; 57005b261ecSmrg xf86ScreenLayoutPtr pLayout; 57105b261ecSmrg Bool OldStyleConfig = FALSE; 57205b261ecSmrg 5736747b715Smrg memset(xf86ScreenLayout, 0, MAXSCREENS * sizeof(xf86ScreenLayoutRec)); 57435c4bbdfSmrg 57505b261ecSmrg screensLeft = prevScreensLeft = (1 << xf86NumScreens) - 1; 57605b261ecSmrg 57735c4bbdfSmrg while (1) { 57835c4bbdfSmrg for (mask = screensLeft, i = 0; mask; mask >>= 1, i++) { 57935c4bbdfSmrg if (!(mask & 1L)) 58035c4bbdfSmrg continue; 58135c4bbdfSmrg 58235c4bbdfSmrg screen = &xf86ConfigLayout.screens[i]; 58335c4bbdfSmrg 58435c4bbdfSmrg if (screen->refscreen != NULL && 58535c4bbdfSmrg screen->refscreen->screennum >= xf86NumScreens) { 58635c4bbdfSmrg screensLeft &= ~(1 << i); 58735c4bbdfSmrg xf86Msg(X_WARNING, 58835c4bbdfSmrg "Not including screen \"%s\" in origins calculation.\n", 58935c4bbdfSmrg screen->screen->id); 59035c4bbdfSmrg continue; 59135c4bbdfSmrg } 59235c4bbdfSmrg 59335c4bbdfSmrg pScreen = xf86Screens[i]->pScreen; 59435c4bbdfSmrg switch (screen->where) { 59535c4bbdfSmrg case PosObsolete: 59635c4bbdfSmrg OldStyleConfig = TRUE; 59735c4bbdfSmrg pLayout = &xf86ScreenLayout[i]; 59835c4bbdfSmrg /* force edge lists */ 59935c4bbdfSmrg if (screen->left) { 60035c4bbdfSmrg ref = screen->left->screennum; 60135c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 60235c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 60335c4bbdfSmrg break; 60435c4bbdfSmrg } 60535c4bbdfSmrg pLayout->left = AddEdge(pLayout->left, 60635c4bbdfSmrg 0, pScreen->height, 60735c4bbdfSmrg xf86Screens[ref]->pScreen->width, 0, 60835c4bbdfSmrg ref); 60935c4bbdfSmrg } 61035c4bbdfSmrg if (screen->right) { 61135c4bbdfSmrg ref = screen->right->screennum; 61235c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 61335c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 61435c4bbdfSmrg break; 61535c4bbdfSmrg } 61635c4bbdfSmrg pLayout->right = AddEdge(pLayout->right, 61735c4bbdfSmrg 0, pScreen->height, 61835c4bbdfSmrg -pScreen->width, 0, ref); 61935c4bbdfSmrg } 62035c4bbdfSmrg if (screen->top) { 62135c4bbdfSmrg ref = screen->top->screennum; 62235c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 62335c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 62435c4bbdfSmrg break; 62535c4bbdfSmrg } 62635c4bbdfSmrg pLayout->up = AddEdge(pLayout->up, 62735c4bbdfSmrg 0, pScreen->width, 62835c4bbdfSmrg 0, xf86Screens[ref]->pScreen->height, 62935c4bbdfSmrg ref); 63035c4bbdfSmrg } 63135c4bbdfSmrg if (screen->bottom) { 63235c4bbdfSmrg ref = screen->bottom->screennum; 63335c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 63435c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 63535c4bbdfSmrg break; 63635c4bbdfSmrg } 63735c4bbdfSmrg pLayout->down = AddEdge(pLayout->down, 63835c4bbdfSmrg 0, pScreen->width, 0, 63935c4bbdfSmrg -pScreen->height, ref); 64035c4bbdfSmrg } 64135c4bbdfSmrg /* we could also try to place it based on those 64235c4bbdfSmrg relative locations if we wanted to */ 64335c4bbdfSmrg screen->x = screen->y = 0; 64435c4bbdfSmrg /* FALLTHROUGH */ 64535c4bbdfSmrg case PosAbsolute: 64635c4bbdfSmrg pScreen->x = screen->x; 64735c4bbdfSmrg pScreen->y = screen->y; 64835c4bbdfSmrg screensLeft &= ~(1 << i); 64935c4bbdfSmrg break; 65035c4bbdfSmrg case PosRelative: 65135c4bbdfSmrg ref = screen->refscreen->screennum; 65235c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 65335c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 65435c4bbdfSmrg break; 65535c4bbdfSmrg } 65635c4bbdfSmrg if (screensLeft & (1 << ref)) 65735c4bbdfSmrg break; 65835c4bbdfSmrg refScreen = xf86Screens[ref]->pScreen; 65935c4bbdfSmrg pScreen->x = refScreen->x + screen->x; 66035c4bbdfSmrg pScreen->y = refScreen->y + screen->y; 66135c4bbdfSmrg screensLeft &= ~(1 << i); 66235c4bbdfSmrg break; 66335c4bbdfSmrg case PosRightOf: 66435c4bbdfSmrg ref = screen->refscreen->screennum; 66535c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 66635c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 66735c4bbdfSmrg break; 66835c4bbdfSmrg } 66935c4bbdfSmrg if (screensLeft & (1 << ref)) 67035c4bbdfSmrg break; 67135c4bbdfSmrg refScreen = xf86Screens[ref]->pScreen; 67235c4bbdfSmrg pScreen->x = refScreen->x + refScreen->width; 67335c4bbdfSmrg pScreen->y = refScreen->y; 67435c4bbdfSmrg screensLeft &= ~(1 << i); 67535c4bbdfSmrg break; 67635c4bbdfSmrg case PosLeftOf: 67735c4bbdfSmrg ref = screen->refscreen->screennum; 67835c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 67935c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 68035c4bbdfSmrg break; 68135c4bbdfSmrg } 68235c4bbdfSmrg if (screensLeft & (1 << ref)) 68335c4bbdfSmrg break; 68435c4bbdfSmrg refScreen = xf86Screens[ref]->pScreen; 68535c4bbdfSmrg pScreen->x = refScreen->x - pScreen->width; 68635c4bbdfSmrg pScreen->y = refScreen->y; 68735c4bbdfSmrg screensLeft &= ~(1 << i); 68835c4bbdfSmrg break; 68935c4bbdfSmrg case PosBelow: 69035c4bbdfSmrg ref = screen->refscreen->screennum; 69135c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 69235c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 69335c4bbdfSmrg break; 69435c4bbdfSmrg } 69535c4bbdfSmrg if (screensLeft & (1 << ref)) 69635c4bbdfSmrg break; 69735c4bbdfSmrg refScreen = xf86Screens[ref]->pScreen; 69835c4bbdfSmrg pScreen->x = refScreen->x; 69935c4bbdfSmrg pScreen->y = refScreen->y + refScreen->height; 70035c4bbdfSmrg screensLeft &= ~(1 << i); 70135c4bbdfSmrg break; 70235c4bbdfSmrg case PosAbove: 70335c4bbdfSmrg ref = screen->refscreen->screennum; 70435c4bbdfSmrg if (!xf86Screens[ref] || !xf86Screens[ref]->pScreen) { 70535c4bbdfSmrg ErrorF("Referenced uninitialized screen in Layout!\n"); 70635c4bbdfSmrg break; 70735c4bbdfSmrg } 70835c4bbdfSmrg if (screensLeft & (1 << ref)) 70935c4bbdfSmrg break; 71035c4bbdfSmrg refScreen = xf86Screens[ref]->pScreen; 71135c4bbdfSmrg pScreen->x = refScreen->x; 71235c4bbdfSmrg pScreen->y = refScreen->y - pScreen->height; 71335c4bbdfSmrg screensLeft &= ~(1 << i); 71435c4bbdfSmrg break; 71535c4bbdfSmrg default: 71635c4bbdfSmrg ErrorF("Illegal placement keyword in Layout!\n"); 71735c4bbdfSmrg break; 71835c4bbdfSmrg } 71935c4bbdfSmrg 72035c4bbdfSmrg } 72135c4bbdfSmrg 72235c4bbdfSmrg if (!screensLeft) 72335c4bbdfSmrg break; 72435c4bbdfSmrg 72535c4bbdfSmrg if (screensLeft == prevScreensLeft) { 72635c4bbdfSmrg /* All the remaining screens are referencing each other. 72735c4bbdfSmrg Assign a value to one of them and go through again */ 72835c4bbdfSmrg i = 0; 72935c4bbdfSmrg while (!((1 << i) & screensLeft)) { 73035c4bbdfSmrg i++; 73135c4bbdfSmrg } 73235c4bbdfSmrg 73335c4bbdfSmrg ref = xf86ConfigLayout.screens[i].refscreen->screennum; 73435c4bbdfSmrg xf86Screens[ref]->pScreen->x = xf86Screens[ref]->pScreen->y = 0; 73535c4bbdfSmrg screensLeft &= ~(1 << ref); 73635c4bbdfSmrg } 73735c4bbdfSmrg 73835c4bbdfSmrg prevScreensLeft = screensLeft; 73905b261ecSmrg } 74005b261ecSmrg 74105b261ecSmrg /* justify the topmost and leftmost to (0,0) */ 7426747b715Smrg minX = xf86Screens[0]->pScreen->x; 7436747b715Smrg minY = xf86Screens[0]->pScreen->y; 74405b261ecSmrg 74535c4bbdfSmrg for (i = 1; i < xf86NumScreens; i++) { 74635c4bbdfSmrg if (xf86Screens[i]->pScreen->x < minX) 74735c4bbdfSmrg minX = xf86Screens[i]->pScreen->x; 74835c4bbdfSmrg if (xf86Screens[i]->pScreen->y < minY) 74935c4bbdfSmrg minY = xf86Screens[i]->pScreen->y; 75005b261ecSmrg } 75105b261ecSmrg 75205b261ecSmrg if (minX || minY) { 75335c4bbdfSmrg for (i = 0; i < xf86NumScreens; i++) { 75435c4bbdfSmrg xf86Screens[i]->pScreen->x -= minX; 75535c4bbdfSmrg xf86Screens[i]->pScreen->y -= minY; 75635c4bbdfSmrg } 75705b261ecSmrg } 75805b261ecSmrg 75905b261ecSmrg /* Create the edge lists */ 76005b261ecSmrg 76135c4bbdfSmrg if (!OldStyleConfig) { 76235c4bbdfSmrg for (i = 0; i < xf86NumScreens; i++) { 76335c4bbdfSmrg pLayout = &xf86ScreenLayout[i]; 76435c4bbdfSmrg 76535c4bbdfSmrg pScreen = xf86Screens[i]->pScreen; 76635c4bbdfSmrg 76735c4bbdfSmrg left = pScreen->x; 76835c4bbdfSmrg right = left + pScreen->width; 76935c4bbdfSmrg top = pScreen->y; 77035c4bbdfSmrg bottom = top + pScreen->height; 77135c4bbdfSmrg 77235c4bbdfSmrg for (j = 0; j < xf86NumScreens; j++) { 77335c4bbdfSmrg if (i == j) 77435c4bbdfSmrg continue; 77535c4bbdfSmrg 77635c4bbdfSmrg refScreen = xf86Screens[j]->pScreen; 77735c4bbdfSmrg 77835c4bbdfSmrg x1 = refScreen->x; 77935c4bbdfSmrg x2 = x1 + refScreen->width; 78035c4bbdfSmrg y1 = refScreen->y; 78135c4bbdfSmrg y2 = y1 + refScreen->height; 78235c4bbdfSmrg 78335c4bbdfSmrg if ((bottom > y1) && (top < y2)) { 78435c4bbdfSmrg min = y1 - top; 78535c4bbdfSmrg if (min < 0) 78635c4bbdfSmrg min = 0; 78735c4bbdfSmrg max = pScreen->height - (bottom - y2); 78835c4bbdfSmrg if (max > pScreen->height) 78935c4bbdfSmrg max = pScreen->height; 79035c4bbdfSmrg 79135c4bbdfSmrg if (((left - 1) >= x1) && ((left - 1) < x2)) 79235c4bbdfSmrg pLayout->left = AddEdge(pLayout->left, min, max, 79335c4bbdfSmrg pScreen->x - refScreen->x, 79435c4bbdfSmrg pScreen->y - refScreen->y, j); 79535c4bbdfSmrg 79635c4bbdfSmrg if ((right >= x1) && (right < x2)) 79735c4bbdfSmrg pLayout->right = AddEdge(pLayout->right, min, max, 79835c4bbdfSmrg pScreen->x - refScreen->x, 79935c4bbdfSmrg pScreen->y - refScreen->y, j); 80035c4bbdfSmrg } 80135c4bbdfSmrg 80235c4bbdfSmrg if ((left < x2) && (right > x1)) { 80335c4bbdfSmrg min = x1 - left; 80435c4bbdfSmrg if (min < 0) 80535c4bbdfSmrg min = 0; 80635c4bbdfSmrg max = pScreen->width - (right - x2); 80735c4bbdfSmrg if (max > pScreen->width) 80835c4bbdfSmrg max = pScreen->width; 80935c4bbdfSmrg 81035c4bbdfSmrg if (((top - 1) >= y1) && ((top - 1) < y2)) 81135c4bbdfSmrg pLayout->up = AddEdge(pLayout->up, min, max, 81235c4bbdfSmrg pScreen->x - refScreen->x, 81335c4bbdfSmrg pScreen->y - refScreen->y, j); 81435c4bbdfSmrg 81535c4bbdfSmrg if ((bottom >= y1) && (bottom < y2)) 81635c4bbdfSmrg pLayout->down = AddEdge(pLayout->down, min, max, 81735c4bbdfSmrg pScreen->x - refScreen->x, 81835c4bbdfSmrg pScreen->y - refScreen->y, j); 81935c4bbdfSmrg } 82035c4bbdfSmrg } 82135c4bbdfSmrg } 82205b261ecSmrg } 82305b261ecSmrg 82435c4bbdfSmrg if (!OldStyleConfig) { 82535c4bbdfSmrg for (i = 0; i < xf86NumScreens; i++) { 82635c4bbdfSmrg pLayout = &xf86ScreenLayout[i]; 82735c4bbdfSmrg pScreen = xf86Screens[i]->pScreen; 82835c4bbdfSmrg if (pLayout->left) 82935c4bbdfSmrg FillOutEdge(pLayout->left, pScreen->height); 83035c4bbdfSmrg if (pLayout->right) 83135c4bbdfSmrg FillOutEdge(pLayout->right, pScreen->height); 83235c4bbdfSmrg if (pLayout->up) 83335c4bbdfSmrg FillOutEdge(pLayout->up, pScreen->width); 83435c4bbdfSmrg if (pLayout->down) 83535c4bbdfSmrg FillOutEdge(pLayout->down, pScreen->width); 83635c4bbdfSmrg } 83705b261ecSmrg } 83835c4bbdfSmrg 83935c4bbdfSmrg update_desktop_dimensions(); 84005b261ecSmrg} 84105b261ecSmrg 84205b261ecSmrgvoid 84305b261ecSmrgxf86ReconfigureLayout(void) 84405b261ecSmrg{ 84505b261ecSmrg int i; 84605b261ecSmrg 84705b261ecSmrg for (i = 0; i < MAXSCREENS; i++) { 84835c4bbdfSmrg xf86ScreenLayoutPtr sl = &xf86ScreenLayout[i]; 84935c4bbdfSmrg 85035c4bbdfSmrg /* we don't have to zero these, xf86InitOrigins() takes care of that */ 85135c4bbdfSmrg free(sl->left); 85235c4bbdfSmrg free(sl->right); 85335c4bbdfSmrg free(sl->up); 85435c4bbdfSmrg free(sl->down); 85505b261ecSmrg } 85605b261ecSmrg 85705b261ecSmrg xf86InitOrigins(); 85805b261ecSmrg} 859