xf86Cursor.c revision 706f2543
1/* 2 * Copyright (c) 1994-2003 by The XFree86 Project, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the copyright holder(s) 23 * and author(s) shall not be used in advertising or otherwise to promote 24 * the sale, use or other dealings in this Software without prior written 25 * authorization from the copyright holder(s) and author(s). 26 */ 27 28#ifdef HAVE_XORG_CONFIG_H 29#include <xorg-config.h> 30#endif 31 32#include <X11/X.h> 33#include <X11/Xmd.h> 34#include "input.h" 35#include "cursor.h" 36#include "mipointer.h" 37#include "scrnintstr.h" 38#include "globals.h" 39 40#include "compiler.h" 41 42#include "xf86.h" 43#include "xf86Priv.h" 44#include "xf86_OSproc.h" 45 46#include <X11/extensions/XIproto.h> 47#include "xf86Xinput.h" 48 49#ifdef XFreeXDGA 50#include "dgaproc.h" 51#endif 52 53typedef struct _xf86EdgeRec { 54 short screen; 55 short start; 56 short end; 57 DDXPointRec offset; 58 struct _xf86EdgeRec *next; 59} xf86EdgeRec, *xf86EdgePtr; 60 61typedef struct { 62 xf86EdgePtr left, right, up, down; 63} xf86ScreenLayoutRec, *xf86ScreenLayoutPtr; 64 65static Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y); 66static void xf86CrossScreen(ScreenPtr pScreen, Bool entering); 67static void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); 68 69static void xf86PointerMoved(int scrnIndex, int x, int y); 70 71static miPointerScreenFuncRec xf86PointerScreenFuncs = { 72 xf86CursorOffScreen, 73 xf86CrossScreen, 74 xf86WarpCursor, 75 /* let miPointerInitialize take care of these */ 76 NULL, 77 NULL 78}; 79 80static xf86ScreenLayoutRec xf86ScreenLayout[MAXSCREENS]; 81 82static Bool HardEdges; 83 84/* 85 * xf86InitViewport -- 86 * Initialize paning & zooming parameters, so that a driver must only 87 * check what resolutions are possible and whether the virtual area 88 * is valid if specified. 89 */ 90 91void 92xf86InitViewport(ScrnInfoPtr pScr) 93{ 94 95 pScr->PointerMoved = xf86PointerMoved; 96 97 /* 98 * Compute the initial Viewport if necessary 99 */ 100 if (pScr->display) { 101 if (pScr->display->frameX0 < 0) { 102 pScr->frameX0 = (pScr->virtualX - pScr->modes->HDisplay) / 2; 103 pScr->frameY0 = (pScr->virtualY - pScr->modes->VDisplay) / 2; 104 } else { 105 pScr->frameX0 = pScr->display->frameX0; 106 pScr->frameY0 = pScr->display->frameY0; 107 } 108 } 109 110 pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; 111 pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; 112 113 /* 114 * Now adjust the initial Viewport, so it lies within the virtual area 115 */ 116 if (pScr->frameX1 >= pScr->virtualX) 117 { 118 pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay; 119 pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; 120 } 121 122 if (pScr->frameY1 >= pScr->virtualY) 123 { 124 pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay; 125 pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; 126 } 127} 128 129 130/* 131 * xf86SetViewport -- 132 * Scroll the visual part of the screen so the pointer is visible. 133 */ 134 135void 136xf86SetViewport(ScreenPtr pScreen, int x, int y) 137{ 138 ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 139 140 (*pScr->PointerMoved)(pScreen->myNum, x, y); 141} 142 143 144static void 145xf86PointerMoved(int scrnIndex, int x, int y) 146{ 147 Bool frameChanged = FALSE; 148 ScrnInfoPtr pScr = xf86Screens[scrnIndex]; 149 150 /* 151 * check wether (x,y) belongs to the visual part of the screen 152 * if not, change the base of the displayed frame accoring 153 */ 154 if ( pScr->frameX0 > x) { 155 pScr->frameX0 = x; 156 pScr->frameX1 = x + pScr->currentMode->HDisplay - 1; 157 frameChanged = TRUE ; 158 } 159 160 if ( pScr->frameX1 < x) { 161 pScr->frameX1 = x + 1; 162 pScr->frameX0 = x - pScr->currentMode->HDisplay + 1; 163 frameChanged = TRUE ; 164 } 165 166 if ( pScr->frameY0 > y) { 167 pScr->frameY0 = y; 168 pScr->frameY1 = y + pScr->currentMode->VDisplay - 1; 169 frameChanged = TRUE; 170 } 171 172 if ( pScr->frameY1 < y) { 173 pScr->frameY1 = y; 174 pScr->frameY0 = y - pScr->currentMode->VDisplay + 1; 175 frameChanged = TRUE; 176 } 177 178 if (frameChanged && pScr->AdjustFrame != NULL) 179 pScr->AdjustFrame(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); 180} 181 182/* 183 * xf86LockZoom -- 184 * Enable/disable ZoomViewport 185 */ 186 187void 188xf86LockZoom(ScreenPtr pScreen, Bool lock) 189{ 190 XF86SCRNINFO(pScreen)->zoomLocked = lock; 191} 192 193/* 194 * xf86SwitchMode -- 195 * This is called by both keyboard processing and the VidMode extension to 196 * set a new mode. 197 */ 198 199Bool 200xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) 201{ 202 ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 203 ScreenPtr pCursorScreen; 204 Bool Switched; 205 int px, py, was_blocked; 206 DeviceIntPtr dev, it; 207 208 if (!pScr->vtSema || !mode || !pScr->SwitchMode) 209 return FALSE; 210 211#ifdef XFreeXDGA 212 if (DGAActive(pScr->scrnIndex)) 213 return FALSE; 214#endif 215 216 if (mode == pScr->currentMode) 217 return TRUE; 218 219 if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY) 220 return FALSE; 221 222 /* Let's take an educated guess for which pointer to take here. And about as 223 educated as it gets is to take the first pointer we find. 224 */ 225 for (dev = inputInfo.devices; dev; dev = dev->next) 226 { 227 if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner) 228 break; 229 } 230 231 pCursorScreen = miPointerGetScreen(dev); 232 if (pScreen == pCursorScreen) 233 miPointerGetPosition(dev, &px, &py); 234 235 was_blocked = xf86BlockSIGIO(); 236 Switched = (*pScr->SwitchMode)(pScr->scrnIndex, mode, 0); 237 if (Switched) { 238 pScr->currentMode = mode; 239 240 /* 241 * Adjust frame for new display size. 242 * Frame is centered around cursor position if cursor is on same screen. 243 */ 244 if (pScreen == pCursorScreen) 245 pScr->frameX0 = px - (mode->HDisplay / 2) + 1; 246 else 247 pScr->frameX0 = (pScr->frameX0 + pScr->frameX1 + 1 - mode->HDisplay) / 2; 248 249 if (pScr->frameX0 < 0) 250 pScr->frameX0 = 0; 251 252 pScr->frameX1 = pScr->frameX0 + mode->HDisplay - 1; 253 if (pScr->frameX1 >= pScr->virtualX) { 254 pScr->frameX0 = pScr->virtualX - mode->HDisplay; 255 pScr->frameX1 = pScr->virtualX - 1; 256 } 257 258 if (pScreen == pCursorScreen) 259 pScr->frameY0 = py - (mode->VDisplay / 2) + 1; 260 else 261 pScr->frameY0 = (pScr->frameY0 + pScr->frameY1 + 1 - mode->VDisplay) / 2; 262 263 if (pScr->frameY0 < 0) 264 pScr->frameY0 = 0; 265 266 pScr->frameY1 = pScr->frameY0 + mode->VDisplay - 1; 267 if (pScr->frameY1 >= pScr->virtualY) { 268 pScr->frameY0 = pScr->virtualY - mode->VDisplay; 269 pScr->frameY1 = pScr->virtualY - 1; 270 } 271 } 272 xf86UnblockSIGIO(was_blocked); 273 274 if (pScr->AdjustFrame) 275 (*pScr->AdjustFrame)(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); 276 277 /* The original code centered the frame around the cursor if possible. 278 * Since this is hard to achieve with multiple cursors, we do the following: 279 * - center around the first pointer 280 * - move all other pointers to the nearest edge on the screen (or leave 281 * them unmodified if they are within the boundaries). 282 */ 283 if (pScreen == pCursorScreen) 284 { 285 xf86WarpCursor(dev, pScreen, px, py); 286 } 287 288 for (it = inputInfo.devices; it; it = it->next) 289 { 290 if (it == dev) 291 continue; 292 293 if (IsPointerDevice(it) && it->spriteInfo->spriteOwner) 294 { 295 pCursorScreen = miPointerGetScreen(it); 296 if (pScreen == pCursorScreen) 297 { 298 miPointerGetPosition(it, &px, &py); 299 if (px < pScr->frameX0) 300 px = pScr->frameX0; 301 else if (px > pScr->frameX1) 302 px = pScr->frameX1; 303 304 if(py < pScr->frameY0) 305 py = pScr->frameY0; 306 else if(py > pScr->frameY1) 307 py = pScr->frameY1; 308 309 xf86WarpCursor(it, pScreen, px, py); 310 } 311 } 312 } 313 314 return Switched; 315} 316 317/* 318 * xf86ZoomViewport -- 319 * Reinitialize the visual part of the screen for another mode. 320 */ 321 322void 323xf86ZoomViewport(ScreenPtr pScreen, int zoom) 324{ 325 ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 326 DisplayModePtr mode; 327 328 if (pScr->zoomLocked || !(mode = pScr->currentMode)) 329 return; 330 331 do { 332 if (zoom > 0) 333 mode = mode->next; 334 else 335 mode = mode->prev; 336 } while (mode != pScr->currentMode && !(mode->type & M_T_USERDEF)); 337 338 (void)xf86SwitchMode(pScreen, mode); 339} 340 341 342static xf86EdgePtr 343FindEdge(xf86EdgePtr edge, int val) 344{ 345 while(edge && (edge->end <= val)) 346 edge = edge->next; 347 348 if(edge && (edge->start <= val)) 349 return edge; 350 351 return NULL; 352} 353 354/* 355 * xf86CursorOffScreen -- 356 * Check whether it is necessary to switch to another screen 357 */ 358 359static Bool 360xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y) 361{ 362 xf86EdgePtr edge; 363 int tmp; 364 365 if(screenInfo.numScreens == 1) 366 return FALSE; 367 368 if(*x < 0) { 369 tmp = *y; 370 if(tmp < 0) tmp = 0; 371 if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; 372 373 if((edge = xf86ScreenLayout[(*pScreen)->myNum].left)) 374 edge = FindEdge(edge, tmp); 375 376 if(!edge) *x = 0; 377 else { 378 *x += edge->offset.x; 379 *y += edge->offset.y; 380 *pScreen = xf86Screens[edge->screen]->pScreen; 381 } 382 } 383 384 if(*x >= (*pScreen)->width) { 385 tmp = *y; 386 if(tmp < 0) tmp = 0; 387 if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; 388 389 if((edge = xf86ScreenLayout[(*pScreen)->myNum].right)) 390 edge = FindEdge(edge, tmp); 391 392 if(!edge) *x = (*pScreen)->width - 1; 393 else { 394 *x += edge->offset.x; 395 *y += edge->offset.y; 396 *pScreen = xf86Screens[edge->screen]->pScreen; 397 } 398 } 399 400 if(*y < 0) { 401 tmp = *x; 402 if(tmp < 0) tmp = 0; 403 if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; 404 405 if((edge = xf86ScreenLayout[(*pScreen)->myNum].up)) 406 edge = FindEdge(edge, tmp); 407 408 if(!edge) *y = 0; 409 else { 410 *x += edge->offset.x; 411 *y += edge->offset.y; 412 *pScreen = xf86Screens[edge->screen]->pScreen; 413 } 414 } 415 416 if(*y >= (*pScreen)->height) { 417 tmp = *x; 418 if(tmp < 0) tmp = 0; 419 if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; 420 421 if((edge = xf86ScreenLayout[(*pScreen)->myNum].down)) 422 edge = FindEdge(edge, tmp); 423 424 if(!edge) *y = (*pScreen)->height - 1; 425 else { 426 *x += edge->offset.x; 427 *y += edge->offset.y; 428 (*pScreen) = xf86Screens[edge->screen]->pScreen; 429 } 430 } 431 432 433#if 0 434 /* This presents problems for overlapping screens when 435 HardEdges is used. Have to think about the logic more */ 436 if((*x < 0) || (*x >= (*pScreen)->width) || 437 (*y < 0) || (*y >= (*pScreen)->height)) { 438 /* We may have crossed more than one screen */ 439 xf86CursorOffScreen(pScreen, x, y); 440 } 441#endif 442 443 return TRUE; 444} 445 446 447 448/* 449 * xf86CrossScreen -- 450 * Switch to another screen 451 * 452 * Currently nothing special happens, but mi assumes the CrossScreen 453 * method exists. 454 */ 455 456static void 457xf86CrossScreen (ScreenPtr pScreen, Bool entering) 458{ 459} 460 461 462/* 463 * xf86WarpCursor -- 464 * Warp possible to another screen 465 */ 466 467/* ARGSUSED */ 468static void 469xf86WarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 470{ 471 int sigstate; 472 sigstate = xf86BlockSIGIO (); 473 miPointerWarpCursor(pDev, pScreen, x, y); 474 475 xf86Info.currentScreen = pScreen; 476 xf86UnblockSIGIO (sigstate); 477} 478 479 480void * 481xf86GetPointerScreenFuncs(void) 482{ 483 return (void *)&xf86PointerScreenFuncs; 484} 485 486 487static xf86EdgePtr 488AddEdge( 489 xf86EdgePtr edge, 490 short min, 491 short max, 492 short dx, 493 short dy, 494 short screen 495){ 496 xf86EdgePtr pEdge = edge, pPrev = NULL, pNew; 497 498 while(1) { 499 while(pEdge && (min >= pEdge->end)) { 500 pPrev = pEdge; 501 pEdge = pEdge->next; 502 } 503 504 if(!pEdge) { 505 if(!(pNew = malloc(sizeof(xf86EdgeRec)))) 506 break; 507 508 pNew->screen = screen; 509 pNew->start = min; 510 pNew->end = max; 511 pNew->offset.x = dx; 512 pNew->offset.y = dy; 513 pNew->next = NULL; 514 515 if(pPrev) 516 pPrev->next = pNew; 517 else 518 edge = pNew; 519 520 break; 521 } else if (min < pEdge->start) { 522 if(!(pNew = malloc(sizeof(xf86EdgeRec)))) 523 break; 524 525 pNew->screen = screen; 526 pNew->start = min; 527 pNew->offset.x = dx; 528 pNew->offset.y = dy; 529 pNew->next = pEdge; 530 531 if(pPrev) pPrev->next = pNew; 532 else edge = pNew; 533 534 if(max <= pEdge->start) { 535 pNew->end = max; 536 break; 537 } else { 538 pNew->end = pEdge->start; 539 min = pEdge->end; 540 } 541 } else 542 min = pEdge->end; 543 544 pPrev = pEdge; 545 pEdge = pEdge->next; 546 547 if(max <= min) break; 548 } 549 550 return edge; 551} 552 553static void 554FillOutEdge(xf86EdgePtr pEdge, int limit) 555{ 556 xf86EdgePtr pNext; 557 int diff; 558 559 if(pEdge->start > 0) pEdge->start = 0; 560 561 while((pNext = pEdge->next)) { 562 diff = pNext->start - pEdge->end; 563 if(diff > 0) { 564 pEdge->end += diff >> 1; 565 pNext->start -= diff - (diff >> 1); 566 } 567 pEdge = pNext; 568 } 569 570 if(pEdge->end < limit) 571 pEdge->end = limit; 572} 573 574/* 575 * xf86InitOrigins() can deal with a maximum of 32 screens 576 * on 32 bit architectures, 64 on 64 bit architectures. 577 */ 578 579void 580xf86InitOrigins(void) 581{ 582 unsigned long screensLeft, prevScreensLeft, mask; 583 screenLayoutPtr screen; 584 ScreenPtr pScreen, refScreen; 585 int x1, x2, y1, y2, left, right, top, bottom; 586 int i, j, ref, minX, minY, min, max; 587 xf86ScreenLayoutPtr pLayout; 588 Bool OldStyleConfig = FALSE; 589 590 /* need to have this set up with a config file option */ 591 HardEdges = FALSE; 592 593 memset(xf86ScreenLayout, 0, MAXSCREENS * sizeof(xf86ScreenLayoutRec)); 594 595 screensLeft = prevScreensLeft = (1 << xf86NumScreens) - 1; 596 597 while(1) { 598 for(mask = screensLeft, i = 0; mask; mask >>= 1, i++) { 599 if(!(mask & 1L)) continue; 600 601 screen = &xf86ConfigLayout.screens[i]; 602 603 if (screen->refscreen != NULL && 604 screen->refscreen->screennum >= xf86NumScreens) { 605 screensLeft &= ~(1 << i); 606 xf86Msg(X_WARNING, "Not including screen \"%s\" in origins calculation.\n", 607 screen->screen->id); 608 continue; 609 } 610 611 pScreen = xf86Screens[i]->pScreen; 612 switch(screen->where) { 613 case PosObsolete: 614 OldStyleConfig = TRUE; 615 pLayout = &xf86ScreenLayout[i]; 616 /* force edge lists */ 617 if(screen->left) { 618 ref = screen->left->screennum; 619 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 620 ErrorF("Referenced uninitialized screen in Layout!\n"); 621 break; 622 } 623 pLayout->left = AddEdge(pLayout->left, 624 0, pScreen->height, 625 xf86Screens[ref]->pScreen->width, 0, ref); 626 } 627 if(screen->right) { 628 ref = screen->right->screennum; 629 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 630 ErrorF("Referenced uninitialized screen in Layout!\n"); 631 break; 632 } 633 pLayout->right = AddEdge(pLayout->right, 634 0, pScreen->height, -pScreen->width, 0, ref); 635 } 636 if(screen->top) { 637 ref = screen->top->screennum; 638 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 639 ErrorF("Referenced uninitialized screen in Layout!\n"); 640 break; 641 } 642 pLayout->up = AddEdge(pLayout->up, 643 0, pScreen->width, 644 0, xf86Screens[ref]->pScreen->height, ref); 645 } 646 if(screen->bottom) { 647 ref = screen->bottom->screennum; 648 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 649 ErrorF("Referenced uninitialized screen in Layout!\n"); 650 break; 651 } 652 pLayout->down = AddEdge(pLayout->down, 653 0, pScreen->width, 0, -pScreen->height, ref); 654 } 655 /* we could also try to place it based on those 656 relative locations if we wanted to */ 657 screen->x = screen->y = 0; 658 /* FALLTHROUGH */ 659 case PosAbsolute: 660 pScreen->x = screen->x; 661 pScreen->y = screen->y; 662 screensLeft &= ~(1 << i); 663 break; 664 case PosRelative: 665 ref = screen->refscreen->screennum; 666 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 667 ErrorF("Referenced uninitialized screen in Layout!\n"); 668 break; 669 } 670 if(screensLeft & (1 << ref)) break; 671 refScreen = xf86Screens[ref]->pScreen; 672 pScreen->x = refScreen->x + screen->x; 673 pScreen->y = refScreen->y + screen->y; 674 screensLeft &= ~(1 << i); 675 break; 676 case PosRightOf: 677 ref = screen->refscreen->screennum; 678 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 679 ErrorF("Referenced uninitialized screen in Layout!\n"); 680 break; 681 } 682 if(screensLeft & (1 << ref)) break; 683 refScreen = xf86Screens[ref]->pScreen; 684 pScreen->x = refScreen->x + refScreen->width; 685 pScreen->y = refScreen->y; 686 screensLeft &= ~(1 << i); 687 break; 688 case PosLeftOf: 689 ref = screen->refscreen->screennum; 690 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 691 ErrorF("Referenced uninitialized screen in Layout!\n"); 692 break; 693 } 694 if(screensLeft & (1 << ref)) break; 695 refScreen = xf86Screens[ref]->pScreen; 696 pScreen->x = refScreen->x - pScreen->width; 697 pScreen->y = refScreen->y; 698 screensLeft &= ~(1 << i); 699 break; 700 case PosBelow: 701 ref = screen->refscreen->screennum; 702 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 703 ErrorF("Referenced uninitialized screen in Layout!\n"); 704 break; 705 } 706 if(screensLeft & (1 << ref)) break; 707 refScreen = xf86Screens[ref]->pScreen; 708 pScreen->x = refScreen->x; 709 pScreen->y = refScreen->y + refScreen->height; 710 screensLeft &= ~(1 << i); 711 break; 712 case PosAbove: 713 ref = screen->refscreen->screennum; 714 if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { 715 ErrorF("Referenced uninitialized screen in Layout!\n"); 716 break; 717 } 718 if(screensLeft & (1 << ref)) break; 719 refScreen = xf86Screens[ref]->pScreen; 720 pScreen->x = refScreen->x; 721 pScreen->y = refScreen->y - pScreen->height; 722 screensLeft &= ~(1 << i); 723 break; 724 default: 725 ErrorF("Illegal placement keyword in Layout!\n"); 726 break; 727 } 728 729 } 730 731 if(!screensLeft) break; 732 733 if(screensLeft == prevScreensLeft) { 734 /* All the remaining screens are referencing each other. 735 Assign a value to one of them and go through again */ 736 i = 0; 737 while(!((1 << i) & screensLeft)){ i++; } 738 739 ref = xf86ConfigLayout.screens[i].refscreen->screennum; 740 xf86Screens[ref]->pScreen->x = xf86Screens[ref]->pScreen->y = 0; 741 screensLeft &= ~(1 << ref); 742 } 743 744 prevScreensLeft = screensLeft; 745 } 746 747 /* justify the topmost and leftmost to (0,0) */ 748 minX = xf86Screens[0]->pScreen->x; 749 minY = xf86Screens[0]->pScreen->y; 750 751 for(i = 1; i < xf86NumScreens; i++) { 752 if(xf86Screens[i]->pScreen->x < minX) 753 minX = xf86Screens[i]->pScreen->x; 754 if(xf86Screens[i]->pScreen->y < minY) 755 minY = xf86Screens[i]->pScreen->y; 756 } 757 758 if (minX || minY) { 759 for(i = 0; i < xf86NumScreens; i++) { 760 xf86Screens[i]->pScreen->x -= minX; 761 xf86Screens[i]->pScreen->y -= minY; 762 } 763 } 764 765 766 /* Create the edge lists */ 767 768 if(!OldStyleConfig) { 769 for(i = 0; i < xf86NumScreens; i++) { 770 pLayout = &xf86ScreenLayout[i]; 771 772 pScreen = xf86Screens[i]->pScreen; 773 774 left = pScreen->x; 775 right = left + pScreen->width; 776 top = pScreen->y; 777 bottom = top + pScreen->height; 778 779 for(j = 0; j < xf86NumScreens; j++) { 780 if(i == j) continue; 781 782 refScreen = xf86Screens[j]->pScreen; 783 784 x1 = refScreen->x; 785 x2 = x1 + refScreen->width; 786 y1 = refScreen->y; 787 y2 = y1 + refScreen->height; 788 789 if((bottom > y1) && (top < y2)) { 790 min = y1 - top; 791 if(min < 0) min = 0; 792 max = pScreen->height - (bottom - y2); 793 if(max > pScreen->height) max = pScreen->height; 794 795 if(((left - 1) >= x1) && ((left - 1) < x2)) 796 pLayout->left = AddEdge(pLayout->left, min, max, 797 pScreen->x - refScreen->x, 798 pScreen->y - refScreen->y, j); 799 800 if((right >= x1) && (right < x2)) 801 pLayout->right = AddEdge(pLayout->right, min, max, 802 pScreen->x - refScreen->x, 803 pScreen->y - refScreen->y, j); 804 } 805 806 807 if((left < x2) && (right > x1)) { 808 min = x1 - left; 809 if(min < 0) min = 0; 810 max = pScreen->width - (right - x2); 811 if(max > pScreen->width) max = pScreen->width; 812 813 if(((top - 1) >= y1) && ((top - 1) < y2)) 814 pLayout->up = AddEdge(pLayout->up, min, max, 815 pScreen->x - refScreen->x, 816 pScreen->y - refScreen->y, j); 817 818 if((bottom >= y1) && (bottom < y2)) 819 pLayout->down = AddEdge(pLayout->down, min, max, 820 pScreen->x - refScreen->x, 821 pScreen->y - refScreen->y, j); 822 } 823 } 824 } 825 } 826 827 if(!HardEdges && !OldStyleConfig) { 828 for(i = 0; i < xf86NumScreens; i++) { 829 pLayout = &xf86ScreenLayout[i]; 830 pScreen = xf86Screens[i]->pScreen; 831 if(pLayout->left) 832 FillOutEdge(pLayout->left, pScreen->height); 833 if(pLayout->right) 834 FillOutEdge(pLayout->right, pScreen->height); 835 if(pLayout->up) 836 FillOutEdge(pLayout->up, pScreen->width); 837 if(pLayout->down) 838 FillOutEdge(pLayout->down, pScreen->width); 839 } 840 } 841} 842 843void 844xf86ReconfigureLayout(void) 845{ 846 int i; 847 848 for (i = 0; i < MAXSCREENS; i++) { 849 xf86ScreenLayoutPtr sl = &xf86ScreenLayout[i]; 850 /* we don't have to zero these, xf86InitOrigins() takes care of that */ 851 free(sl->left); 852 free(sl->right); 853 free(sl->up); 854 free(sl->down); 855 } 856 857 xf86InitOrigins(); 858} 859 860 861