diff options
Diffstat (limited to 'xserver/randr/rrpointer.c')
-rw-r--r-- | xserver/randr/rrpointer.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/xserver/randr/rrpointer.c b/xserver/randr/rrpointer.c new file mode 100644 index 000000000..c88a0f83e --- /dev/null +++ b/xserver/randr/rrpointer.c @@ -0,0 +1,145 @@ +/* + * Copyright © 2006 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "randrstr.h" + +/* + * When the pointer moves, check to see if the specified position is outside + * any of theavailable CRTCs and move it to a 'sensible' place if so, where + * sensible is the closest monitor to the departing edge. + * + * Returns whether the position was adjusted + */ + +static Bool +RRCrtcContainsPosition (RRCrtcPtr crtc, int x, int y) +{ + RRModePtr mode = crtc->mode; + int scan_width, scan_height; + + if (!mode) + return FALSE; + + RRCrtcGetScanoutSize (crtc, &scan_width, &scan_height); + + if (crtc->x <= x && x < crtc->x + scan_width && + crtc->y <= y && y < crtc->y + scan_height) + return TRUE; + return FALSE; +} + +/* + * Find the CRTC nearest the specified position, ignoring 'skip' + */ +static void +RRPointerToNearestCrtc (ScreenPtr pScreen, int x, int y, RRCrtcPtr skip) +{ + rrScrPriv (pScreen); + int c; + RRCrtcPtr nearest = NULL; + int best = 0; + int best_dx = 0, best_dy = 0; + + for (c = 0; c < pScrPriv->numCrtcs; c++) + { + RRCrtcPtr crtc = pScrPriv->crtcs[c]; + RRModePtr mode = crtc->mode; + int dx, dy; + int dist; + int scan_width, scan_height; + + if (!mode) + continue; + if (crtc == skip) + continue; + + RRCrtcGetScanoutSize (crtc, &scan_width, &scan_height); + + if (x < crtc->x) + dx = crtc->x - x; + else if (x > crtc->x + scan_width) + dx = x - (crtc->x + scan_width); + else + dx = 0; + if (y < crtc->y) + dy = crtc->y - x; + else if (y > crtc->y + scan_height) + dy = y - (crtc->y + scan_height); + else + dy = 0; + dist = dx + dy; + if (!nearest || dist < best) + { + nearest = crtc; + best_dx = dx; + best_dy = dy; + } + } + if (best_dx || best_dy) + (*pScreen->SetCursorPosition) (pScreen, x + best_dx, y + best_dy, TRUE); + pScrPriv->pointerCrtc = nearest; +} + +void +RRPointerMoved (ScreenPtr pScreen, int x, int y) +{ + rrScrPriv (pScreen); + RRCrtcPtr pointerCrtc = pScrPriv->pointerCrtc; + int c; + + /* Check last known CRTC */ + if (pointerCrtc && RRCrtcContainsPosition (pointerCrtc, x, y)) + return; + + /* Check all CRTCs */ + for (c = 0; c < pScrPriv->numCrtcs; c++) + { + RRCrtcPtr crtc = pScrPriv->crtcs[c]; + + if (RRCrtcContainsPosition (crtc, x, y)) + { + /* Remember containing CRTC */ + pScrPriv->pointerCrtc = crtc; + return; + } + } + + /* None contain pointer, find nearest */ + RRPointerToNearestCrtc (pScreen, x, y, pointerCrtc); +} + +/* + * When the screen is reconfigured, move the pointer to the nearest + * CRTC + */ +void +RRPointerScreenConfigured (ScreenPtr pScreen) +{ + WindowPtr pRoot = GetCurrentRootWindow (); + ScreenPtr pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL; + int x, y; + + if (pScreen != pCurrentScreen) + return; + GetSpritePosition (&x, &y); + RRPointerToNearestCrtc (pScreen, x, y, NULL); +} |