1706f2543Smrg/* 2706f2543Smrg * Copyright (c) 1994-2003 by The XFree86 Project, Inc. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Software"), 6706f2543Smrg * to deal in the Software without restriction, including without limitation 7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, subject to the following conditions: 10706f2543Smrg * 11706f2543Smrg * The above copyright notice and this permission notice shall be included in 12706f2543Smrg * all copies or substantial portions of the Software. 13706f2543Smrg * 14706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE. 21706f2543Smrg * 22706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s) 23706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote 24706f2543Smrg * the sale, use or other dealings in this Software without prior written 25706f2543Smrg * authorization from the copyright holder(s) and author(s). 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 29706f2543Smrg#include <xorg-config.h> 30706f2543Smrg#endif 31706f2543Smrg 32706f2543Smrg#include <X11/X.h> 33706f2543Smrg#include <X11/Xmd.h> 34706f2543Smrg#include "input.h" 35706f2543Smrg#include "cursor.h" 36706f2543Smrg#include "mipointer.h" 37706f2543Smrg#include "scrnintstr.h" 38706f2543Smrg#include "globals.h" 39706f2543Smrg 40706f2543Smrg#include "compiler.h" 41706f2543Smrg 42706f2543Smrg#include "xf86.h" 43706f2543Smrg#include "xf86Priv.h" 44706f2543Smrg#include "xf86_OSproc.h" 45706f2543Smrg 46706f2543Smrg#include <X11/extensions/XIproto.h> 47706f2543Smrg#include "xf86Xinput.h" 48706f2543Smrg 49706f2543Smrg#ifdef XFreeXDGA 50706f2543Smrg#include "dgaproc.h" 51706f2543Smrg#endif 52706f2543Smrg 53706f2543Smrgtypedef struct _xf86EdgeRec { 54706f2543Smrg short screen; 55706f2543Smrg short start; 56706f2543Smrg short end; 57706f2543Smrg DDXPointRec offset; 58706f2543Smrg struct _xf86EdgeRec *next; 59706f2543Smrg} xf86EdgeRec, *xf86EdgePtr; 60706f2543Smrg 61706f2543Smrgtypedef struct { 62706f2543Smrg xf86EdgePtr left, right, up, down; 63706f2543Smrg} xf86ScreenLayoutRec, *xf86ScreenLayoutPtr; 64706f2543Smrg 65706f2543Smrgstatic Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y); 66706f2543Smrgstatic void xf86CrossScreen(ScreenPtr pScreen, Bool entering); 67706f2543Smrgstatic void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); 68706f2543Smrg 69706f2543Smrgstatic void xf86PointerMoved(int scrnIndex, int x, int y); 70706f2543Smrg 71706f2543Smrgstatic miPointerScreenFuncRec xf86PointerScreenFuncs = { 72706f2543Smrg xf86CursorOffScreen, 73706f2543Smrg xf86CrossScreen, 74706f2543Smrg xf86WarpCursor, 75706f2543Smrg /* let miPointerInitialize take care of these */ 76706f2543Smrg NULL, 77706f2543Smrg NULL 78706f2543Smrg}; 79706f2543Smrg 80706f2543Smrgstatic xf86ScreenLayoutRec xf86ScreenLayout[MAXSCREENS]; 81706f2543Smrg 82706f2543Smrgstatic Bool HardEdges; 83706f2543Smrg 84706f2543Smrg/* 85706f2543Smrg * xf86InitViewport -- 86706f2543Smrg * Initialize paning & zooming parameters, so that a driver must only 87706f2543Smrg * check what resolutions are possible and whether the virtual area 88706f2543Smrg * is valid if specified. 89706f2543Smrg */ 90706f2543Smrg 91706f2543Smrgvoid 92706f2543Smrgxf86InitViewport(ScrnInfoPtr pScr) 93706f2543Smrg{ 94706f2543Smrg 95706f2543Smrg pScr->PointerMoved = xf86PointerMoved; 96706f2543Smrg 97706f2543Smrg /* 98706f2543Smrg * Compute the initial Viewport if necessary 99706f2543Smrg */ 100706f2543Smrg if (pScr->display) { 101706f2543Smrg if (pScr->display->frameX0 < 0) { 102706f2543Smrg pScr->frameX0 = (pScr->virtualX - pScr->modes->HDisplay) / 2; 103706f2543Smrg pScr->frameY0 = (pScr->virtualY - pScr->modes->VDisplay) / 2; 104706f2543Smrg } else { 105706f2543Smrg pScr->frameX0 = pScr->display->frameX0; 106706f2543Smrg pScr->frameY0 = pScr->display->frameY0; 107706f2543Smrg } 108706f2543Smrg } 109706f2543Smrg 110706f2543Smrg pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; 111706f2543Smrg pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; 112706f2543Smrg 113706f2543Smrg /* 114706f2543Smrg * Now adjust the initial Viewport, so it lies within the virtual area 115706f2543Smrg */ 116706f2543Smrg if (pScr->frameX1 >= pScr->virtualX) 117706f2543Smrg { 118706f2543Smrg pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay; 119706f2543Smrg pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; 120706f2543Smrg } 121706f2543Smrg 122706f2543Smrg if (pScr->frameY1 >= pScr->virtualY) 123706f2543Smrg { 124706f2543Smrg pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay; 125706f2543Smrg pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; 126706f2543Smrg } 127706f2543Smrg} 128706f2543Smrg 129706f2543Smrg 130706f2543Smrg/* 131706f2543Smrg * xf86SetViewport -- 132706f2543Smrg * Scroll the visual part of the screen so the pointer is visible. 133706f2543Smrg */ 134706f2543Smrg 135706f2543Smrgvoid 136706f2543Smrgxf86SetViewport(ScreenPtr pScreen, int x, int y) 137706f2543Smrg{ 138706f2543Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 139706f2543Smrg 140706f2543Smrg (*pScr->PointerMoved)(pScreen->myNum, x, y); 141706f2543Smrg} 142706f2543Smrg 143706f2543Smrg 144706f2543Smrgstatic void 145706f2543Smrgxf86PointerMoved(int scrnIndex, int x, int y) 146706f2543Smrg{ 147706f2543Smrg Bool frameChanged = FALSE; 148706f2543Smrg ScrnInfoPtr pScr = xf86Screens[scrnIndex]; 149706f2543Smrg 150706f2543Smrg /* 151706f2543Smrg * check wether (x,y) belongs to the visual part of the screen 152706f2543Smrg * if not, change the base of the displayed frame accoring 153706f2543Smrg */ 154706f2543Smrg if ( pScr->frameX0 > x) { 155706f2543Smrg pScr->frameX0 = x; 156706f2543Smrg pScr->frameX1 = x + pScr->currentMode->HDisplay - 1; 157706f2543Smrg frameChanged = TRUE ; 158706f2543Smrg } 159706f2543Smrg 160706f2543Smrg if ( pScr->frameX1 < x) { 161706f2543Smrg pScr->frameX1 = x + 1; 162706f2543Smrg pScr->frameX0 = x - pScr->currentMode->HDisplay + 1; 163706f2543Smrg frameChanged = TRUE ; 164706f2543Smrg } 165706f2543Smrg 166706f2543Smrg if ( pScr->frameY0 > y) { 167706f2543Smrg pScr->frameY0 = y; 168706f2543Smrg pScr->frameY1 = y + pScr->currentMode->VDisplay - 1; 169706f2543Smrg frameChanged = TRUE; 170706f2543Smrg } 171706f2543Smrg 172706f2543Smrg if ( pScr->frameY1 < y) { 173706f2543Smrg pScr->frameY1 = y; 174706f2543Smrg pScr->frameY0 = y - pScr->currentMode->VDisplay + 1; 175706f2543Smrg frameChanged = TRUE; 176706f2543Smrg } 177706f2543Smrg 178706f2543Smrg if (frameChanged && pScr->AdjustFrame != NULL) 179706f2543Smrg pScr->AdjustFrame(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); 180706f2543Smrg} 181706f2543Smrg 182706f2543Smrg/* 183706f2543Smrg * xf86LockZoom -- 184706f2543Smrg * Enable/disable ZoomViewport 185706f2543Smrg */ 186706f2543Smrg 187706f2543Smrgvoid 188706f2543Smrgxf86LockZoom(ScreenPtr pScreen, Bool lock) 189706f2543Smrg{ 190706f2543Smrg XF86SCRNINFO(pScreen)->zoomLocked = lock; 191706f2543Smrg} 192706f2543Smrg 193706f2543Smrg/* 194706f2543Smrg * xf86SwitchMode -- 195706f2543Smrg * This is called by both keyboard processing and the VidMode extension to 196706f2543Smrg * set a new mode. 197706f2543Smrg */ 198706f2543Smrg 199706f2543SmrgBool 200706f2543Smrgxf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) 201706f2543Smrg{ 202706f2543Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 203706f2543Smrg ScreenPtr pCursorScreen; 204706f2543Smrg Bool Switched; 205706f2543Smrg int px, py, was_blocked; 206706f2543Smrg DeviceIntPtr dev, it; 207706f2543Smrg 208706f2543Smrg if (!pScr->vtSema || !mode || !pScr->SwitchMode) 209706f2543Smrg return FALSE; 210706f2543Smrg 211706f2543Smrg#ifdef XFreeXDGA 212706f2543Smrg if (DGAActive(pScr->scrnIndex)) 213706f2543Smrg return FALSE; 214706f2543Smrg#endif 215706f2543Smrg 216706f2543Smrg if (mode == pScr->currentMode) 217706f2543Smrg return TRUE; 218706f2543Smrg 219706f2543Smrg if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY) 220706f2543Smrg return FALSE; 221706f2543Smrg 222706f2543Smrg /* Let's take an educated guess for which pointer to take here. And about as 223706f2543Smrg educated as it gets is to take the first pointer we find. 224706f2543Smrg */ 225706f2543Smrg for (dev = inputInfo.devices; dev; dev = dev->next) 226706f2543Smrg { 227706f2543Smrg if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner) 228706f2543Smrg break; 229706f2543Smrg } 230706f2543Smrg 231706f2543Smrg pCursorScreen = miPointerGetScreen(dev); 232706f2543Smrg if (pScreen == pCursorScreen) 233706f2543Smrg miPointerGetPosition(dev, &px, &py); 234706f2543Smrg 235706f2543Smrg was_blocked = xf86BlockSIGIO(); 236706f2543Smrg Switched = (*pScr->SwitchMode)(pScr->scrnIndex, mode, 0); 237706f2543Smrg if (Switched) { 238706f2543Smrg pScr->currentMode = mode; 239706f2543Smrg 240706f2543Smrg /* 241706f2543Smrg * Adjust frame for new display size. 242706f2543Smrg * Frame is centered around cursor position if cursor is on same screen. 243706f2543Smrg */ 244706f2543Smrg if (pScreen == pCursorScreen) 245706f2543Smrg pScr->frameX0 = px - (mode->HDisplay / 2) + 1; 246706f2543Smrg else 247706f2543Smrg pScr->frameX0 = (pScr->frameX0 + pScr->frameX1 + 1 - mode->HDisplay) / 2; 248706f2543Smrg 249706f2543Smrg if (pScr->frameX0 < 0) 250706f2543Smrg pScr->frameX0 = 0; 251706f2543Smrg 252706f2543Smrg pScr->frameX1 = pScr->frameX0 + mode->HDisplay - 1; 253706f2543Smrg if (pScr->frameX1 >= pScr->virtualX) { 254706f2543Smrg pScr->frameX0 = pScr->virtualX - mode->HDisplay; 255706f2543Smrg pScr->frameX1 = pScr->virtualX - 1; 256706f2543Smrg } 257706f2543Smrg 258706f2543Smrg if (pScreen == pCursorScreen) 259706f2543Smrg pScr->frameY0 = py - (mode->VDisplay / 2) + 1; 260706f2543Smrg else 261706f2543Smrg pScr->frameY0 = (pScr->frameY0 + pScr->frameY1 + 1 - mode->VDisplay) / 2; 262706f2543Smrg 263706f2543Smrg if (pScr->frameY0 < 0) 264706f2543Smrg pScr->frameY0 = 0; 265706f2543Smrg 266706f2543Smrg pScr->frameY1 = pScr->frameY0 + mode->VDisplay - 1; 267706f2543Smrg if (pScr->frameY1 >= pScr->virtualY) { 268706f2543Smrg pScr->frameY0 = pScr->virtualY - mode->VDisplay; 269706f2543Smrg pScr->frameY1 = pScr->virtualY - 1; 270706f2543Smrg } 271706f2543Smrg } 272706f2543Smrg xf86UnblockSIGIO(was_blocked); 273706f2543Smrg 274706f2543Smrg if (pScr->AdjustFrame) 275706f2543Smrg (*pScr->AdjustFrame)(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); 276706f2543Smrg 277706f2543Smrg /* The original code centered the frame around the cursor if possible. 278706f2543Smrg * Since this is hard to achieve with multiple cursors, we do the following: 279706f2543Smrg * - center around the first pointer 280706f2543Smrg * - move all other pointers to the nearest edge on the screen (or leave 281706f2543Smrg * them unmodified if they are within the boundaries). 282706f2543Smrg */ 283706f2543Smrg if (pScreen == pCursorScreen) 284706f2543Smrg { 285706f2543Smrg xf86WarpCursor(dev, pScreen, px, py); 286706f2543Smrg } 287706f2543Smrg 288706f2543Smrg for (it = inputInfo.devices; it; it = it->next) 289706f2543Smrg { 290706f2543Smrg if (it == dev) 291706f2543Smrg continue; 292706f2543Smrg 293706f2543Smrg if (IsPointerDevice(it) && it->spriteInfo->spriteOwner) 294706f2543Smrg { 295706f2543Smrg pCursorScreen = miPointerGetScreen(it); 296706f2543Smrg if (pScreen == pCursorScreen) 297706f2543Smrg { 298706f2543Smrg miPointerGetPosition(it, &px, &py); 299706f2543Smrg if (px < pScr->frameX0) 300706f2543Smrg px = pScr->frameX0; 301706f2543Smrg else if (px > pScr->frameX1) 302706f2543Smrg px = pScr->frameX1; 303706f2543Smrg 304706f2543Smrg if(py < pScr->frameY0) 305706f2543Smrg py = pScr->frameY0; 306706f2543Smrg else if(py > pScr->frameY1) 307706f2543Smrg py = pScr->frameY1; 308706f2543Smrg 309706f2543Smrg xf86WarpCursor(it, pScreen, px, py); 310706f2543Smrg } 311706f2543Smrg } 312706f2543Smrg } 313706f2543Smrg 314706f2543Smrg return Switched; 315706f2543Smrg} 316706f2543Smrg 317706f2543Smrg/* 318706f2543Smrg * xf86ZoomViewport -- 319706f2543Smrg * Reinitialize the visual part of the screen for another mode. 320706f2543Smrg */ 321706f2543Smrg 322706f2543Smrgvoid 323706f2543Smrgxf86ZoomViewport(ScreenPtr pScreen, int zoom) 324706f2543Smrg{ 325706f2543Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 326706f2543Smrg DisplayModePtr mode; 327706f2543Smrg 328706f2543Smrg if (pScr->zoomLocked || !(mode = pScr->currentMode)) 329706f2543Smrg return; 330706f2543Smrg 331706f2543Smrg do { 332706f2543Smrg if (zoom > 0) 333706f2543Smrg mode = mode->next; 334706f2543Smrg else 335706f2543Smrg mode = mode->prev; 336706f2543Smrg } while (mode != pScr->currentMode && !(mode->type & M_T_USERDEF)); 337706f2543Smrg 338706f2543Smrg (void)xf86SwitchMode(pScreen, mode); 339706f2543Smrg} 340706f2543Smrg 341706f2543Smrg 342706f2543Smrgstatic xf86EdgePtr 343706f2543SmrgFindEdge(xf86EdgePtr edge, int val) 344706f2543Smrg{ 345706f2543Smrg while(edge && (edge->end <= val)) 346706f2543Smrg edge = edge->next; 347706f2543Smrg 348706f2543Smrg if(edge && (edge->start <= val)) 349706f2543Smrg return edge; 350706f2543Smrg 351706f2543Smrg return NULL; 352706f2543Smrg} 353706f2543Smrg 354706f2543Smrg/* 355706f2543Smrg * xf86CursorOffScreen -- 356706f2543Smrg * Check whether it is necessary to switch to another screen 357706f2543Smrg */ 358706f2543Smrg 359706f2543Smrgstatic Bool 360706f2543Smrgxf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y) 361706f2543Smrg{ 362706f2543Smrg xf86EdgePtr edge; 363706f2543Smrg int tmp; 364706f2543Smrg 365706f2543Smrg if(screenInfo.numScreens == 1) 366706f2543Smrg return FALSE; 367706f2543Smrg 368706f2543Smrg if(*x < 0) { 369706f2543Smrg tmp = *y; 370706f2543Smrg if(tmp < 0) tmp = 0; 371706f2543Smrg if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; 372706f2543Smrg 373706f2543Smrg if((edge = xf86ScreenLayout[(*pScreen)->myNum].left)) 374706f2543Smrg edge = FindEdge(edge, tmp); 375706f2543Smrg 376706f2543Smrg if(!edge) *x = 0; 377706f2543Smrg else { 378706f2543Smrg *x += edge->offset.x; 379706f2543Smrg *y += edge->offset.y; 380706f2543Smrg *pScreen = xf86Screens[edge->screen]->pScreen; 381706f2543Smrg } 382706f2543Smrg } 383706f2543Smrg 384706f2543Smrg if(*x >= (*pScreen)->width) { 385706f2543Smrg tmp = *y; 386706f2543Smrg if(tmp < 0) tmp = 0; 387706f2543Smrg if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; 388706f2543Smrg 389706f2543Smrg if((edge = xf86ScreenLayout[(*pScreen)->myNum].right)) 390706f2543Smrg edge = FindEdge(edge, tmp); 391706f2543Smrg 392706f2543Smrg if(!edge) *x = (*pScreen)->width - 1; 393706f2543Smrg else { 394706f2543Smrg *x += edge->offset.x; 395706f2543Smrg *y += edge->offset.y; 396706f2543Smrg *pScreen = xf86Screens[edge->screen]->pScreen; 397706f2543Smrg } 398706f2543Smrg } 399706f2543Smrg 400706f2543Smrg if(*y < 0) { 401706f2543Smrg tmp = *x; 402706f2543Smrg if(tmp < 0) tmp = 0; 403706f2543Smrg if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; 404706f2543Smrg 405706f2543Smrg if((edge = xf86ScreenLayout[(*pScreen)->myNum].up)) 406706f2543Smrg edge = FindEdge(edge, tmp); 407706f2543Smrg 408706f2543Smrg if(!edge) *y = 0; 409706f2543Smrg else { 410706f2543Smrg *x += edge->offset.x; 411706f2543Smrg *y += edge->offset.y; 412706f2543Smrg *pScreen = xf86Screens[edge->screen]->pScreen; 413706f2543Smrg } 414706f2543Smrg } 415706f2543Smrg 416706f2543Smrg if(*y >= (*pScreen)->height) { 417706f2543Smrg tmp = *x; 418706f2543Smrg if(tmp < 0) tmp = 0; 419706f2543Smrg if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; 420706f2543Smrg 421706f2543Smrg if((edge = xf86ScreenLayout[(*pScreen)->myNum].down)) 422706f2543Smrg edge = FindEdge(edge, tmp); 423706f2543Smrg 424706f2543Smrg if(!edge) *y = (*pScreen)->height - 1; 425706f2543Smrg else { 426706f2543Smrg *x += edge->offset.x; 427706f2543Smrg *y += edge->offset.y; 428706f2543Smrg (*pScreen) = xf86Screens[edge->screen]->pScreen; 429706f2543Smrg } 430706f2543Smrg } 431706f2543Smrg 432706f2543Smrg 433706f2543Smrg#if 0 434706f2543Smrg /* This presents problems for overlapping screens when 435706f2543Smrg HardEdges is used. Have to think about the logic more */ 436706f2543Smrg if((*x < 0) || (*x >= (*pScreen)->width) || 437706f2543Smrg (*y < 0) || (*y >= (*pScreen)->height)) { 438706f2543Smrg /* We may have crossed more than one screen */ 439706f2543Smrg xf86CursorOffScreen(pScreen, x, y); 440706f2543Smrg } 441706f2543Smrg#endif 442706f2543Smrg 443706f2543Smrg return TRUE; 444706f2543Smrg} 445706f2543Smrg 446706f2543Smrg 447706f2543Smrg 448706f2543Smrg/* 449706f2543Smrg * xf86CrossScreen -- 450706f2543Smrg * Switch to another screen 451706f2543Smrg * 452706f2543Smrg * Currently nothing special happens, but mi assumes the CrossScreen 453706f2543Smrg * method exists. 454706f2543Smrg */ 455706f2543Smrg 456706f2543Smrgstatic void 457706f2543Smrgxf86CrossScreen (ScreenPtr pScreen, Bool entering) 458706f2543Smrg{ 459706f2543Smrg} 460706f2543Smrg 461706f2543Smrg 462706f2543Smrg/* 463706f2543Smrg * xf86WarpCursor -- 464706f2543Smrg * Warp possible to another screen 465706f2543Smrg */ 466706f2543Smrg 467706f2543Smrg/* ARGSUSED */ 468706f2543Smrgstatic void 469706f2543Smrgxf86WarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 470706f2543Smrg{ 471706f2543Smrg int sigstate; 472706f2543Smrg sigstate = xf86BlockSIGIO (); 473706f2543Smrg miPointerWarpCursor(pDev, pScreen, x, y); 474706f2543Smrg 475706f2543Smrg xf86Info.currentScreen = pScreen; 476706f2543Smrg xf86UnblockSIGIO (sigstate); 477706f2543Smrg} 478706f2543Smrg 479706f2543Smrg 480706f2543Smrgvoid * 481706f2543Smrgxf86GetPointerScreenFuncs(void) 482706f2543Smrg{ 483706f2543Smrg return (void *)&xf86PointerScreenFuncs; 484706f2543Smrg} 485706f2543Smrg 486706f2543Smrg 487706f2543Smrgstatic xf86EdgePtr 488706f2543SmrgAddEdge( 489706f2543Smrg xf86EdgePtr edge, 490706f2543Smrg short min, 491706f2543Smrg short max, 492706f2543Smrg short dx, 493706f2543Smrg short dy, 494706f2543Smrg short screen 495706f2543Smrg){ 496706f2543Smrg xf86EdgePtr pEdge = edge, pPrev = NULL, pNew; 497706f2543Smrg 498706f2543Smrg while(1) { 499706f2543Smrg while(pEdge && (min >= pEdge->end)) { 500706f2543Smrg pPrev = pEdge; 501706f2543Smrg pEdge = pEdge->next; 502706f2543Smrg } 503706f2543Smrg 504706f2543Smrg if(!pEdge) { 505706f2543Smrg if(!(pNew = malloc(sizeof(xf86EdgeRec)))) 506706f2543Smrg break; 507706f2543Smrg 508706f2543Smrg pNew->screen = screen; 509706f2543Smrg pNew->start = min; 510706f2543Smrg pNew->end = max; 511706f2543Smrg pNew->offset.x = dx; 512706f2543Smrg pNew->offset.y = dy; 513706f2543Smrg pNew->next = NULL; 514706f2543Smrg 515706f2543Smrg if(pPrev) 516706f2543Smrg pPrev->next = pNew; 517706f2543Smrg else 518706f2543Smrg edge = pNew; 519706f2543Smrg 520706f2543Smrg break; 521706f2543Smrg } else if (min < pEdge->start) { 522706f2543Smrg if(!(pNew = malloc(sizeof(xf86EdgeRec)))) 523706f2543Smrg break; 524706f2543Smrg 525706f2543Smrg pNew->screen = screen; 526706f2543Smrg pNew->start = min; 527706f2543Smrg pNew->offset.x = dx; 528706f2543Smrg pNew->offset.y = dy; 529706f2543Smrg pNew->next = pEdge; 530706f2543Smrg 531706f2543Smrg if(pPrev) pPrev->next = pNew; 532706f2543Smrg else edge = pNew; 533706f2543Smrg 534706f2543Smrg if(max <= pEdge->start) { 535706f2543Smrg pNew->end = max; 536706f2543Smrg break; 537706f2543Smrg } else { 538706f2543Smrg pNew->end = pEdge->start; 539706f2543Smrg min = pEdge->end; 540706f2543Smrg } 541706f2543Smrg } else 542706f2543Smrg min = pEdge->end; 543706f2543Smrg 544706f2543Smrg pPrev = pEdge; 545706f2543Smrg pEdge = pEdge->next; 546706f2543Smrg 547706f2543Smrg if(max <= min) break; 548706f2543Smrg } 549706f2543Smrg 550706f2543Smrg return edge; 551706f2543Smrg} 552706f2543Smrg 553706f2543Smrgstatic void 554706f2543SmrgFillOutEdge(xf86EdgePtr pEdge, int limit) 555706f2543Smrg{ 556706f2543Smrg xf86EdgePtr pNext; 557706f2543Smrg int diff; 558706f2543Smrg 559706f2543Smrg if(pEdge->start > 0) pEdge->start = 0; 560706f2543Smrg 561706f2543Smrg while((pNext = pEdge->next)) { 562706f2543Smrg diff = pNext->start - pEdge->end; 563706f2543Smrg if(diff > 0) { 564706f2543Smrg pEdge->end += diff >> 1; 565706f2543Smrg pNext->start -= diff - (diff >> 1); 566706f2543Smrg } 567706f2543Smrg pEdge = pNext; 568706f2543Smrg } 569706f2543Smrg 570706f2543Smrg if(pEdge->end < limit) 571706f2543Smrg pEdge->end = limit; 572706f2543Smrg} 573706f2543Smrg 574706f2543Smrg/* 575706f2543Smrg * xf86InitOrigins() can deal with a maximum of 32 screens 576706f2543Smrg * on 32 bit architectures, 64 on 64 bit architectures. 577706f2543Smrg */ 578706f2543Smrg 579706f2543Smrgvoid 580706f2543Smrgxf86InitOrigins(void) 581706f2543Smrg{ 582706f2543Smrg unsigned long screensLeft, prevScreensLeft, mask; 583706f2543Smrg screenLayoutPtr screen; 584706f2543Smrg ScreenPtr pScreen, refScreen; 585706f2543Smrg int x1, x2, y1, y2, left, right, top, bottom; 586706f2543Smrg int i, j, ref, minX, minY, min, max; 587706f2543Smrg xf86ScreenLayoutPtr pLayout; 588706f2543Smrg Bool OldStyleConfig = FALSE; 589706f2543Smrg 590706f2543Smrg /* need to have this set up with a config file option */ 591706f2543Smrg HardEdges = FALSE; 592706f2543Smrg 593706f2543Smrg memset(xf86ScreenLayout, 0, MAXSCREENS * sizeof(xf86ScreenLayoutRec)); 594706f2543Smrg 595706f2543Smrg screensLeft = prevScreensLeft = (1 << xf86NumScreens) - 1; 596706f2543Smrg 597706f2543Smrg while(1) { 598706f2543Smrg for(mask = screensLeft, i = 0; mask; mask >>= 1, i++) { 599706f2543Smrg if(!(mask & 1L)) continue; 600706f2543Smrg 601706f2543Smrg screen = &xf86ConfigLayout.screens[i]; 602706f2543Smrg 603706f2543Smrg if (screen->refscreen != NULL && 604706f2543Smrg screen->refscreen->screennum >= xf86NumScreens) { 605706f2543Smrg screensLeft &= ~(1 << i); 606706f2543Smrg xf86Msg(X_WARNING, "Not including screen \"%s\" in origins calculation.\n", 607706f2543Smrg screen->screen->id); 608706f2543Smrg continue; 609706f2543Smrg } 610706f2543Smrg 611706f2543Smrg pScreen = xf86Screens[i]->pScreen; 612706f2543Smrg switch(screen->where) { 613706f2543Smrg case PosObsolete: 614706f2543Smrg OldStyleConfig = TRUE; 615706f2543Smrg pLayout = &xf86ScreenLayout[i]; 616706f2543Smrg /* force edge lists */ 617706f2543Smrg if(screen->left) { 618706f2543Smrg ref = screen->left->screennum; 619706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 620706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 621706f2543Smrg break; 622706f2543Smrg } 623706f2543Smrg pLayout->left = AddEdge(pLayout->left, 624706f2543Smrg 0, pScreen->height, 625706f2543Smrg xf86Screens[ref]->pScreen->width, 0, ref); 626706f2543Smrg } 627706f2543Smrg if(screen->right) { 628706f2543Smrg ref = screen->right->screennum; 629706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 630706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 631706f2543Smrg break; 632706f2543Smrg } 633706f2543Smrg pLayout->right = AddEdge(pLayout->right, 634706f2543Smrg 0, pScreen->height, -pScreen->width, 0, ref); 635706f2543Smrg } 636706f2543Smrg if(screen->top) { 637706f2543Smrg ref = screen->top->screennum; 638706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 639706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 640706f2543Smrg break; 641706f2543Smrg } 642706f2543Smrg pLayout->up = AddEdge(pLayout->up, 643706f2543Smrg 0, pScreen->width, 644706f2543Smrg 0, xf86Screens[ref]->pScreen->height, ref); 645706f2543Smrg } 646706f2543Smrg if(screen->bottom) { 647706f2543Smrg ref = screen->bottom->screennum; 648706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 649706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 650706f2543Smrg break; 651706f2543Smrg } 652706f2543Smrg pLayout->down = AddEdge(pLayout->down, 653706f2543Smrg 0, pScreen->width, 0, -pScreen->height, ref); 654706f2543Smrg } 655706f2543Smrg /* we could also try to place it based on those 656706f2543Smrg relative locations if we wanted to */ 657706f2543Smrg screen->x = screen->y = 0; 658706f2543Smrg /* FALLTHROUGH */ 659706f2543Smrg case PosAbsolute: 660706f2543Smrg pScreen->x = screen->x; 661706f2543Smrg pScreen->y = screen->y; 662706f2543Smrg screensLeft &= ~(1 << i); 663706f2543Smrg break; 664706f2543Smrg case PosRelative: 665706f2543Smrg ref = screen->refscreen->screennum; 666706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 667706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 668706f2543Smrg break; 669706f2543Smrg } 670706f2543Smrg if(screensLeft & (1 << ref)) break; 671706f2543Smrg refScreen = xf86Screens[ref]->pScreen; 672706f2543Smrg pScreen->x = refScreen->x + screen->x; 673706f2543Smrg pScreen->y = refScreen->y + screen->y; 674706f2543Smrg screensLeft &= ~(1 << i); 675706f2543Smrg break; 676706f2543Smrg case PosRightOf: 677706f2543Smrg ref = screen->refscreen->screennum; 678706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 679706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 680706f2543Smrg break; 681706f2543Smrg } 682706f2543Smrg if(screensLeft & (1 << ref)) break; 683706f2543Smrg refScreen = xf86Screens[ref]->pScreen; 684706f2543Smrg pScreen->x = refScreen->x + refScreen->width; 685706f2543Smrg pScreen->y = refScreen->y; 686706f2543Smrg screensLeft &= ~(1 << i); 687706f2543Smrg break; 688706f2543Smrg case PosLeftOf: 689706f2543Smrg ref = screen->refscreen->screennum; 690706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 691706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 692706f2543Smrg break; 693706f2543Smrg } 694706f2543Smrg if(screensLeft & (1 << ref)) break; 695706f2543Smrg refScreen = xf86Screens[ref]->pScreen; 696706f2543Smrg pScreen->x = refScreen->x - pScreen->width; 697706f2543Smrg pScreen->y = refScreen->y; 698706f2543Smrg screensLeft &= ~(1 << i); 699706f2543Smrg break; 700706f2543Smrg case PosBelow: 701706f2543Smrg ref = screen->refscreen->screennum; 702706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 703706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 704706f2543Smrg break; 705706f2543Smrg } 706706f2543Smrg if(screensLeft & (1 << ref)) break; 707706f2543Smrg refScreen = xf86Screens[ref]->pScreen; 708706f2543Smrg pScreen->x = refScreen->x; 709706f2543Smrg pScreen->y = refScreen->y + refScreen->height; 710706f2543Smrg screensLeft &= ~(1 << i); 711706f2543Smrg break; 712706f2543Smrg case PosAbove: 713706f2543Smrg ref = screen->refscreen->screennum; 714706f2543Smrg if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 715706f2543Smrg ErrorF("Referenced uninitialized screen in Layout!\n"); 716706f2543Smrg break; 717706f2543Smrg } 718706f2543Smrg if(screensLeft & (1 << ref)) break; 719706f2543Smrg refScreen = xf86Screens[ref]->pScreen; 720706f2543Smrg pScreen->x = refScreen->x; 721706f2543Smrg pScreen->y = refScreen->y - pScreen->height; 722706f2543Smrg screensLeft &= ~(1 << i); 723706f2543Smrg break; 724706f2543Smrg default: 725706f2543Smrg ErrorF("Illegal placement keyword in Layout!\n"); 726706f2543Smrg break; 727706f2543Smrg } 728706f2543Smrg 729706f2543Smrg } 730706f2543Smrg 731706f2543Smrg if(!screensLeft) break; 732706f2543Smrg 733706f2543Smrg if(screensLeft == prevScreensLeft) { 734706f2543Smrg /* All the remaining screens are referencing each other. 735706f2543Smrg Assign a value to one of them and go through again */ 736706f2543Smrg i = 0; 737706f2543Smrg while(!((1 << i) & screensLeft)){ i++; } 738706f2543Smrg 739706f2543Smrg ref = xf86ConfigLayout.screens[i].refscreen->screennum; 740706f2543Smrg xf86Screens[ref]->pScreen->x = xf86Screens[ref]->pScreen->y = 0; 741706f2543Smrg screensLeft &= ~(1 << ref); 742706f2543Smrg } 743706f2543Smrg 744706f2543Smrg prevScreensLeft = screensLeft; 745706f2543Smrg } 746706f2543Smrg 747706f2543Smrg /* justify the topmost and leftmost to (0,0) */ 748706f2543Smrg minX = xf86Screens[0]->pScreen->x; 749706f2543Smrg minY = xf86Screens[0]->pScreen->y; 750706f2543Smrg 751706f2543Smrg for(i = 1; i < xf86NumScreens; i++) { 752706f2543Smrg if(xf86Screens[i]->pScreen->x < minX) 753706f2543Smrg minX = xf86Screens[i]->pScreen->x; 754706f2543Smrg if(xf86Screens[i]->pScreen->y < minY) 755706f2543Smrg minY = xf86Screens[i]->pScreen->y; 756706f2543Smrg } 757706f2543Smrg 758706f2543Smrg if (minX || minY) { 759706f2543Smrg for(i = 0; i < xf86NumScreens; i++) { 760706f2543Smrg xf86Screens[i]->pScreen->x -= minX; 761706f2543Smrg xf86Screens[i]->pScreen->y -= minY; 762706f2543Smrg } 763706f2543Smrg } 764706f2543Smrg 765706f2543Smrg 766706f2543Smrg /* Create the edge lists */ 767706f2543Smrg 768706f2543Smrg if(!OldStyleConfig) { 769706f2543Smrg for(i = 0; i < xf86NumScreens; i++) { 770706f2543Smrg pLayout = &xf86ScreenLayout[i]; 771706f2543Smrg 772706f2543Smrg pScreen = xf86Screens[i]->pScreen; 773706f2543Smrg 774706f2543Smrg left = pScreen->x; 775706f2543Smrg right = left + pScreen->width; 776706f2543Smrg top = pScreen->y; 777706f2543Smrg bottom = top + pScreen->height; 778706f2543Smrg 779706f2543Smrg for(j = 0; j < xf86NumScreens; j++) { 780706f2543Smrg if(i == j) continue; 781706f2543Smrg 782706f2543Smrg refScreen = xf86Screens[j]->pScreen; 783706f2543Smrg 784706f2543Smrg x1 = refScreen->x; 785706f2543Smrg x2 = x1 + refScreen->width; 786706f2543Smrg y1 = refScreen->y; 787706f2543Smrg y2 = y1 + refScreen->height; 788706f2543Smrg 789706f2543Smrg if((bottom > y1) && (top < y2)) { 790706f2543Smrg min = y1 - top; 791706f2543Smrg if(min < 0) min = 0; 792706f2543Smrg max = pScreen->height - (bottom - y2); 793706f2543Smrg if(max > pScreen->height) max = pScreen->height; 794706f2543Smrg 795706f2543Smrg if(((left - 1) >= x1) && ((left - 1) < x2)) 796706f2543Smrg pLayout->left = AddEdge(pLayout->left, min, max, 797706f2543Smrg pScreen->x - refScreen->x, 798706f2543Smrg pScreen->y - refScreen->y, j); 799706f2543Smrg 800706f2543Smrg if((right >= x1) && (right < x2)) 801706f2543Smrg pLayout->right = AddEdge(pLayout->right, min, max, 802706f2543Smrg pScreen->x - refScreen->x, 803706f2543Smrg pScreen->y - refScreen->y, j); 804706f2543Smrg } 805706f2543Smrg 806706f2543Smrg 807706f2543Smrg if((left < x2) && (right > x1)) { 808706f2543Smrg min = x1 - left; 809706f2543Smrg if(min < 0) min = 0; 810706f2543Smrg max = pScreen->width - (right - x2); 811706f2543Smrg if(max > pScreen->width) max = pScreen->width; 812706f2543Smrg 813706f2543Smrg if(((top - 1) >= y1) && ((top - 1) < y2)) 814706f2543Smrg pLayout->up = AddEdge(pLayout->up, min, max, 815706f2543Smrg pScreen->x - refScreen->x, 816706f2543Smrg pScreen->y - refScreen->y, j); 817706f2543Smrg 818706f2543Smrg if((bottom >= y1) && (bottom < y2)) 819706f2543Smrg pLayout->down = AddEdge(pLayout->down, min, max, 820706f2543Smrg pScreen->x - refScreen->x, 821706f2543Smrg pScreen->y - refScreen->y, j); 822706f2543Smrg } 823706f2543Smrg } 824706f2543Smrg } 825706f2543Smrg } 826706f2543Smrg 827706f2543Smrg if(!HardEdges && !OldStyleConfig) { 828706f2543Smrg for(i = 0; i < xf86NumScreens; i++) { 829706f2543Smrg pLayout = &xf86ScreenLayout[i]; 830706f2543Smrg pScreen = xf86Screens[i]->pScreen; 831706f2543Smrg if(pLayout->left) 832706f2543Smrg FillOutEdge(pLayout->left, pScreen->height); 833706f2543Smrg if(pLayout->right) 834706f2543Smrg FillOutEdge(pLayout->right, pScreen->height); 835706f2543Smrg if(pLayout->up) 836706f2543Smrg FillOutEdge(pLayout->up, pScreen->width); 837706f2543Smrg if(pLayout->down) 838706f2543Smrg FillOutEdge(pLayout->down, pScreen->width); 839706f2543Smrg } 840706f2543Smrg } 841706f2543Smrg} 842706f2543Smrg 843706f2543Smrgvoid 844706f2543Smrgxf86ReconfigureLayout(void) 845706f2543Smrg{ 846706f2543Smrg int i; 847706f2543Smrg 848706f2543Smrg for (i = 0; i < MAXSCREENS; i++) { 849706f2543Smrg xf86ScreenLayoutPtr sl = &xf86ScreenLayout[i]; 850706f2543Smrg /* we don't have to zero these, xf86InitOrigins() takes care of that */ 851706f2543Smrg free(sl->left); 852706f2543Smrg free(sl->right); 853706f2543Smrg free(sl->up); 854706f2543Smrg free(sl->down); 855706f2543Smrg } 856706f2543Smrg 857706f2543Smrg xf86InitOrigins(); 858706f2543Smrg} 859706f2543Smrg 860706f2543Smrg 861