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