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